| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- using ChocolArm64.Decoders;
- using ChocolArm64.Translation;
- using System.Reflection.Emit;
- using static ChocolArm64.Instructions.InstEmitMemoryHelper;
- namespace ChocolArm64.Instructions
- {
- static partial class InstEmit
- {
- public static void Adr(ILEmitterCtx context)
- {
- OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp;
- context.EmitLdc_I(op.Position + op.Imm);
- context.EmitStintzr(op.Rd);
- }
- public static void Adrp(ILEmitterCtx context)
- {
- OpCodeAdr64 op = (OpCodeAdr64)context.CurrOp;
- context.EmitLdc_I((op.Position & ~0xfffL) + (op.Imm << 12));
- context.EmitStintzr(op.Rd);
- }
- public static void Ldr(ILEmitterCtx context) => EmitLdr(context, false);
- public static void Ldrs(ILEmitterCtx context) => EmitLdr(context, true);
- private static void EmitLdr(ILEmitterCtx context, bool signed)
- {
- OpCodeMem64 op = (OpCodeMem64)context.CurrOp;
- EmitLoadAddress(context);
- if (signed && op.Extend64)
- {
- EmitReadSx64Call(context, op.Size);
- }
- else if (signed)
- {
- EmitReadSx32Call(context, op.Size);
- }
- else
- {
- EmitReadZxCall(context, op.Size);
- }
- if (op is IOpCodeSimd64)
- {
- context.EmitStvec(op.Rt);
- }
- else
- {
- context.EmitStintzr(op.Rt);
- }
- EmitWBackIfNeeded(context);
- }
- public static void Ldr_Literal(ILEmitterCtx context)
- {
- IOpCodeLit64 op = (IOpCodeLit64)context.CurrOp;
- if (op.Prefetch)
- {
- return;
- }
- context.EmitLdc_I8(op.Imm);
- if (op.Signed)
- {
- EmitReadSx64Call(context, op.Size);
- }
- else
- {
- EmitReadZxCall(context, op.Size);
- }
- if (op is IOpCodeSimd64)
- {
- context.EmitStvec(op.Rt);
- }
- else
- {
- context.EmitStint(op.Rt);
- }
- }
- public static void Ldp(ILEmitterCtx context)
- {
- OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp;
- void EmitReadAndStore(int rt)
- {
- if (op.Extend64)
- {
- EmitReadSx64Call(context, op.Size);
- }
- else
- {
- EmitReadZxCall(context, op.Size);
- }
- if (op is IOpCodeSimd64)
- {
- context.EmitStvec(rt);
- }
- else
- {
- context.EmitStintzr(rt);
- }
- }
- EmitLoadAddress(context);
- EmitReadAndStore(op.Rt);
- context.EmitLdtmp();
- context.EmitLdc_I8(1 << op.Size);
- context.Emit(OpCodes.Add);
- EmitReadAndStore(op.Rt2);
- EmitWBackIfNeeded(context);
- }
- public static void Str(ILEmitterCtx context)
- {
- OpCodeMem64 op = (OpCodeMem64)context.CurrOp;
- EmitLoadAddress(context);
- if (op is IOpCodeSimd64)
- {
- context.EmitLdvec(op.Rt);
- }
- else
- {
- context.EmitLdintzr(op.Rt);
- }
- EmitWriteCall(context, op.Size);
- EmitWBackIfNeeded(context);
- }
- public static void Stp(ILEmitterCtx context)
- {
- OpCodeMemPair64 op = (OpCodeMemPair64)context.CurrOp;
- EmitLoadAddress(context);
- if (op is IOpCodeSimd64)
- {
- context.EmitLdvec(op.Rt);
- }
- else
- {
- context.EmitLdintzr(op.Rt);
- }
- EmitWriteCall(context, op.Size);
- context.EmitLdtmp();
- context.EmitLdc_I8(1 << op.Size);
- context.Emit(OpCodes.Add);
- if (op is IOpCodeSimd64)
- {
- context.EmitLdvec(op.Rt2);
- }
- else
- {
- context.EmitLdintzr(op.Rt2);
- }
- EmitWriteCall(context, op.Size);
- EmitWBackIfNeeded(context);
- }
- private static void EmitLoadAddress(ILEmitterCtx context)
- {
- switch (context.CurrOp)
- {
- case OpCodeMemImm64 op:
- context.EmitLdint(op.Rn);
- if (!op.PostIdx)
- {
- // Pre-indexing.
- context.EmitLdc_I(op.Imm);
- context.Emit(OpCodes.Add);
- }
- break;
- case OpCodeMemReg64 op:
- context.EmitLdint(op.Rn);
- context.EmitLdintzr(op.Rm);
- context.EmitCast(op.IntType);
- if (op.Shift)
- {
- context.EmitLsl(op.Size);
- }
- context.Emit(OpCodes.Add);
- break;
- }
- // Save address to Scratch var since the register value may change.
- context.Emit(OpCodes.Dup);
- context.EmitSttmp();
- }
- private static void EmitWBackIfNeeded(ILEmitterCtx context)
- {
- // Check whenever the current OpCode has post-indexed write back, if so write it.
- // Note: AOpCodeMemPair inherits from AOpCodeMemImm, so this works for both.
- if (context.CurrOp is OpCodeMemImm64 op && op.WBack)
- {
- context.EmitLdtmp();
- if (op.PostIdx)
- {
- context.EmitLdc_I(op.Imm);
- context.Emit(OpCodes.Add);
- }
- context.EmitStint(op.Rn);
- }
- }
- }
- }
|