| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- using ARMeilleure.Decoders;
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.State;
- using ARMeilleure.Translation;
- using static ARMeilleure.Instructions.InstEmitHelper;
- using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
- using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
- namespace ARMeilleure.Instructions
- {
- static partial class InstEmit32
- {
- public static void Clrex(ArmEmitterContext context)
- {
- EmitClearExclusive(context);
- }
- public static void Csdb(ArmEmitterContext context)
- {
- // Execute as no-op.
- }
- public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
- public static void Dsb(ArmEmitterContext context) => EmitBarrier(context);
- public static void Ldrex(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
- }
- public static void Ldrexb(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
- }
- public static void Ldrexd(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, DWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
- }
- public static void Ldrexh(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive);
- }
- public static void Lda(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
- }
- public static void Ldab(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Ordered);
- }
- public static void Ldaex(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, WordSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Ldaexb(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, ByteSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Ldaexd(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, DWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Ldaexh(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Ldah(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, HWordSizeLog2, AccessType.LoadZx | AccessType.Ordered);
- }
- // Stores.
- public static void Strex(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, WordSizeLog2, AccessType.Store | AccessType.Exclusive);
- }
- public static void Strexb(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, ByteSizeLog2, AccessType.Store | AccessType.Exclusive);
- }
- public static void Strexd(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, DWordSizeLog2, AccessType.Store | AccessType.Exclusive);
- }
- public static void Strexh(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, HWordSizeLog2, AccessType.Store | AccessType.Exclusive);
- }
- public static void Stl(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, WordSizeLog2, AccessType.Store | AccessType.Ordered);
- }
- public static void Stlb(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, ByteSizeLog2, AccessType.Store | AccessType.Ordered);
- }
- public static void Stlex(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, WordSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Stlexb(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, ByteSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Stlexd(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, DWordSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Stlexh(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, HWordSizeLog2, AccessType.Store | AccessType.Exclusive | AccessType.Ordered);
- }
- public static void Stlh(ArmEmitterContext context)
- {
- EmitExLoadOrStore(context, HWordSizeLog2, AccessType.Store | AccessType.Ordered);
- }
- private static void EmitExLoadOrStore(ArmEmitterContext context, int size, AccessType accType)
- {
- IOpCode32MemEx op = (IOpCode32MemEx)context.CurrOp;
- Operand address = context.Copy(GetIntA32(context, op.Rn));
- var exclusive = (accType & AccessType.Exclusive) != 0;
- var ordered = (accType & AccessType.Ordered) != 0;
- if (ordered)
- {
- EmitBarrier(context);
- }
- if ((accType & AccessType.Load) != 0)
- {
- if (size == DWordSizeLog2)
- {
- // Keep loads atomic - make the call to get the whole region and then decompose it into parts
- // for the registers.
- Operand value = EmitLoadExclusive(context, address, exclusive, size);
- Operand valueLow = context.ConvertI64ToI32(value);
- valueLow = context.ZeroExtend32(OperandType.I64, valueLow);
- Operand valueHigh = context.ShiftRightUI(value, Const(32));
- Operand lblBigEndian = Label();
- Operand lblEnd = Label();
- context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
- SetIntA32(context, op.Rt, valueLow);
- SetIntA32(context, op.Rt | 1, valueHigh);
- context.Branch(lblEnd);
- context.MarkLabel(lblBigEndian);
- SetIntA32(context, op.Rt | 1, valueLow);
- SetIntA32(context, op.Rt, valueHigh);
- context.MarkLabel(lblEnd);
- }
- else
- {
- SetIntA32(context, op.Rt, EmitLoadExclusive(context, address, exclusive, size));
- }
- }
- else
- {
- if (size == DWordSizeLog2)
- {
- // Split the result into 2 words (based on endianness)
- Operand lo = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
- Operand hi = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt | 1));
- Operand lblBigEndian = Label();
- Operand lblEnd = Label();
- context.BranchIfTrue(lblBigEndian, GetFlag(PState.EFlag));
- Operand leResult = context.BitwiseOr(lo, context.ShiftLeft(hi, Const(32)));
- EmitStoreExclusive(context, address, leResult, exclusive, size, op.Rd, a32: true);
- context.Branch(lblEnd);
- context.MarkLabel(lblBigEndian);
- Operand beResult = context.BitwiseOr(hi, context.ShiftLeft(lo, Const(32)));
- EmitStoreExclusive(context, address, beResult, exclusive, size, op.Rd, a32: true);
- context.MarkLabel(lblEnd);
- }
- else
- {
- Operand value = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
- EmitStoreExclusive(context, address, value, exclusive, size, op.Rd, a32: true);
- }
- }
- }
- private static void EmitBarrier(ArmEmitterContext context)
- {
- // Note: This barrier is most likely not necessary, and probably
- // doesn't make any difference since we need to do a ton of stuff
- // (software MMU emulation) to read or write anything anyway.
- }
- }
- }
|