public static void EmitDataLoadOper2(ILEmitterCtx context) { switch (context.CurrOp) { case IOpCodeAluImm64 op: context.EmitLdc_I(op.Imm); break; case IOpCodeAluRs64 op: context.EmitLdintzr(op.Rm); switch (op.ShiftType) { case ShiftType.Lsl: context.EmitLsl(op.Shift); break; case ShiftType.Lsr: context.EmitLsr(op.Shift); break; case ShiftType.Asr: context.EmitAsr(op.Shift); break; case ShiftType.Ror: context.EmitRor(op.Shift); break; } break; case IOpCodeAluRx64 op: context.EmitLdintzr(op.Rm); context.EmitCast(op.IntType); context.EmitLsl(op.Shift); break; } }
public static void EmitAluLoadOper2(ILEmitterCtx context, bool setCarry = true) { switch (context.CurrOp) { // ARM32. case OpCode32AluImm op: context.EmitLdc_I4(op.Imm); if (op.SetFlags && op.IsRotated) { context.EmitLdc_I4((int)((uint)op.Imm >> 31)); context.EmitStflg((int)PState.CBit); } break; case OpCode32AluRsImm op: EmitLoadRmShiftedByImmediate(context, op, setCarry); break; case OpCodeT16AluImm8 op: context.EmitLdc_I4(op.Imm); break; // ARM64. case IOpCodeAluImm64 op: context.EmitLdc_I(op.Imm); break; case IOpCodeAluRs64 op: context.EmitLdintzr(op.Rm); switch (op.ShiftType) { case ShiftType.Lsl: context.EmitLsl(op.Shift); break; case ShiftType.Lsr: context.EmitLsr(op.Shift); break; case ShiftType.Asr: context.EmitAsr(op.Shift); break; case ShiftType.Ror: context.EmitRor(op.Shift); break; } break; case IOpCodeAluRx64 op: context.EmitLdintzr(op.Rm); context.EmitCast(op.IntType); context.EmitLsl(op.Shift); break; default: throw new InvalidOperationException(); } }
private static void EmitRrxC(ILEmitterCtx context, bool setCarry) { // Rotate right by 1 with carry. if (setCarry) { context.Emit(OpCodes.Dup); context.EmitLdc_I4(1); context.Emit(OpCodes.And); context.EmitSttmp(); } context.EmitLsr(1); context.EmitLdflg((int)PState.CBit); context.EmitLsl(31); context.Emit(OpCodes.Or); if (setCarry) { context.EmitLdtmp(); context.EmitStflg((int)PState.CBit); } }
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 EmitBfmLsl(ILEmitterCtx context) { OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; context.EmitLdintzr(op.Rn); context.EmitLsl(op.GetBitsCount() - op.Shift); context.EmitStintzr(op.Rd); }
public static void Bfm(ILEmitterCtx context) { OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; if (op.Pos < op.Shift) { //BFI. context.EmitLdintzr(op.Rn); int shift = op.GetBitsCount() - op.Shift; int width = op.Pos + 1; long mask = (long)(ulong.MaxValue >> (64 - width)); context.EmitLdc_I(mask); context.Emit(OpCodes.And); context.EmitLsl(shift); context.EmitLdintzr(op.Rd); context.EmitLdc_I(~(mask << shift)); context.Emit(OpCodes.And); context.Emit(OpCodes.Or); context.EmitStintzr(op.Rd); } else { //BFXIL. context.EmitLdintzr(op.Rn); context.EmitLsr(op.Shift); int width = op.Pos - op.Shift + 1; long mask = (long)(ulong.MaxValue >> (64 - width)); context.EmitLdc_I(mask); context.Emit(OpCodes.And); context.EmitLdintzr(op.Rd); context.EmitLdc_I(~mask); context.Emit(OpCodes.And); context.Emit(OpCodes.Or); context.EmitStintzr(op.Rd); } }
public static void Sbfm(ILEmitterCtx context) { OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; int bitsCount = op.GetBitsCount(); if (op.Pos + 1 == bitsCount) { EmitSbfmShift(context); } else if (op.Pos < op.Shift) { EmitSbfiz(context); } else if (op.Pos == 7 && op.Shift == 0) { EmitSbfmCast(context, OpCodes.Conv_I1); } else if (op.Pos == 15 && op.Shift == 0) { EmitSbfmCast(context, OpCodes.Conv_I2); } else if (op.Pos == 31 && op.Shift == 0) { EmitSbfmCast(context, OpCodes.Conv_I4); } else { EmitBfmLoadRn(context); context.EmitLdintzr(op.Rn); context.EmitLsl(bitsCount - 1 - op.Pos); context.EmitAsr(bitsCount - 1); context.EmitLdc_I(~op.TMask); context.Emit(OpCodes.And); context.Emit(OpCodes.Or); context.EmitStintzr(op.Rd); } }
private static void EmitLslC(ILEmitterCtx context, bool setCarry, int shift) { if ((uint)shift > 32) { EmitShiftByMoreThan32(context, setCarry); } else if (shift == 32) { if (setCarry) { context.EmitLdc_I4(1); context.Emit(OpCodes.And); context.EmitStflg((int)PState.CBit); } else { context.Emit(OpCodes.Pop); } context.EmitLdc_I4(0); } else { if (setCarry) { context.Emit(OpCodes.Dup); context.EmitLsr(32 - shift); context.EmitLdc_I4(1); context.Emit(OpCodes.And); context.EmitStflg((int)PState.CBit); } context.EmitLsl(shift); } }
private static void EmitBfiz(ILEmitterCtx context, bool signed) { OpCodeBfm64 op = (OpCodeBfm64)context.CurrOp; int width = op.Pos + 1; context.EmitLdintzr(op.Rn); context.EmitLsl(op.GetBitsCount() - width); if (signed) { context.EmitAsr(op.Shift - width); } else { context.EmitLsr(op.Shift - width); } context.EmitStintzr(op.Rd); }
private static void EmitLoadOrStore(ILEmitterCtx context, int size, AccessType accType) { OpCode32Mem op = (OpCode32Mem)context.CurrOp; if (op.Index || op.WBack) { EmitLoadFromRegister(context, op.Rn); context.EmitLdc_I4(op.Imm); context.Emit(op.Add ? OpCodes.Add : OpCodes.Sub); context.EmitSttmp(); } if (op.Index) { context.EmitLdtmp(); } else { EmitLoadFromRegister(context, op.Rn); } if ((accType & AccessType.Load) != 0) { if ((accType & AccessType.Signed) != 0) { EmitReadSx32Call(context, size); } else { EmitReadZxCall(context, size); } if (op.WBack) { context.EmitLdtmp(); EmitStoreToRegister(context, op.Rn); } if (size == DWordSizeLog2) { context.Emit(OpCodes.Dup); context.EmitLdflg((int)PState.EBit); ILLabel lblBigEndian = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.Emit(OpCodes.Brtrue_S, lblBigEndian); //Little endian mode. context.Emit(OpCodes.Conv_U4); EmitStoreToRegister(context, op.Rt); context.EmitLsr(32); context.Emit(OpCodes.Conv_U4); EmitStoreToRegister(context, op.Rt | 1); context.Emit(OpCodes.Br_S, lblEnd); //Big endian mode. context.MarkLabel(lblBigEndian); context.EmitLsr(32); context.Emit(OpCodes.Conv_U4); EmitStoreToRegister(context, op.Rt); context.Emit(OpCodes.Conv_U4); EmitStoreToRegister(context, op.Rt | 1); context.MarkLabel(lblEnd); } else { EmitStoreToRegister(context, op.Rt); } } else { if (op.WBack) { context.EmitLdtmp(); EmitStoreToRegister(context, op.Rn); } EmitLoadFromRegister(context, op.Rt); if (size == DWordSizeLog2) { context.Emit(OpCodes.Conv_U8); context.EmitLdflg((int)PState.EBit); ILLabel lblBigEndian = new ILLabel(); ILLabel lblEnd = new ILLabel(); context.Emit(OpCodes.Brtrue_S, lblBigEndian); //Little endian mode. EmitLoadFromRegister(context, op.Rt | 1); context.Emit(OpCodes.Conv_U8); context.EmitLsl(32); context.Emit(OpCodes.Or); context.Emit(OpCodes.Br_S, lblEnd); //Big endian mode. context.MarkLabel(lblBigEndian); context.EmitLsl(32); EmitLoadFromRegister(context, op.Rt | 1); context.Emit(OpCodes.Conv_U8); context.Emit(OpCodes.Or); context.MarkLabel(lblEnd); } EmitWriteCall(context, size); } }