InstEmitBfm.cs
1 using ARMeilleure.Decoders; 2 using ARMeilleure.IntermediateRepresentation; 3 using ARMeilleure.Translation; 4 5 using static ARMeilleure.Instructions.InstEmitHelper; 6 using static ARMeilleure.IntermediateRepresentation.Operand.Factory; 7 8 namespace ARMeilleure.Instructions 9 { 10 static partial class InstEmit 11 { 12 public static void Bfm(ArmEmitterContext context) 13 { 14 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 15 16 Operand d = GetIntOrZR(context, op.Rd); 17 Operand n = GetIntOrZR(context, op.Rn); 18 19 Operand res; 20 21 if (op.Pos < op.Shift) 22 { 23 // BFI. 24 int shift = op.GetBitsCount() - op.Shift; 25 26 int width = op.Pos + 1; 27 28 long mask = (long)(ulong.MaxValue >> (64 - width)); 29 30 res = context.ShiftLeft(context.BitwiseAnd(n, Const(n.Type, mask)), Const(shift)); 31 32 res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~(mask << shift)))); 33 } 34 else 35 { 36 // BFXIL. 37 int shift = op.Shift; 38 39 int width = op.Pos - shift + 1; 40 41 long mask = (long)(ulong.MaxValue >> (64 - width)); 42 43 res = context.BitwiseAnd(context.ShiftRightUI(n, Const(shift)), Const(n.Type, mask)); 44 45 res = context.BitwiseOr(res, context.BitwiseAnd(d, Const(d.Type, ~mask))); 46 } 47 48 SetIntOrZR(context, op.Rd, res); 49 } 50 51 public static void Sbfm(ArmEmitterContext context) 52 { 53 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 54 55 int bitsCount = op.GetBitsCount(); 56 57 if (op.Pos + 1 == bitsCount) 58 { 59 EmitSbfmShift(context); 60 } 61 else if (op.Pos < op.Shift) 62 { 63 EmitSbfiz(context); 64 } 65 else if (op.Pos == 7 && op.Shift == 0) 66 { 67 Operand n = GetIntOrZR(context, op.Rn); 68 69 SetIntOrZR(context, op.Rd, context.SignExtend8(n.Type, n)); 70 } 71 else if (op.Pos == 15 && op.Shift == 0) 72 { 73 Operand n = GetIntOrZR(context, op.Rn); 74 75 SetIntOrZR(context, op.Rd, context.SignExtend16(n.Type, n)); 76 } 77 else if (op.Pos == 31 && op.Shift == 0) 78 { 79 Operand n = GetIntOrZR(context, op.Rn); 80 81 SetIntOrZR(context, op.Rd, context.SignExtend32(n.Type, n)); 82 } 83 else 84 { 85 Operand res = GetIntOrZR(context, op.Rn); 86 87 res = context.ShiftLeft(res, Const(bitsCount - 1 - op.Pos)); 88 res = context.ShiftRightSI(res, Const(bitsCount - 1)); 89 res = context.BitwiseAnd(res, Const(res.Type, ~op.TMask)); 90 91 Operand n2 = GetBfmN(context); 92 93 SetIntOrZR(context, op.Rd, context.BitwiseOr(res, n2)); 94 } 95 } 96 97 public static void Ubfm(ArmEmitterContext context) 98 { 99 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 100 101 if (op.Pos + 1 == op.GetBitsCount()) 102 { 103 EmitUbfmShift(context); 104 } 105 else if (op.Pos < op.Shift) 106 { 107 EmitUbfiz(context); 108 } 109 else if (op.Pos + 1 == op.Shift) 110 { 111 EmitBfmLsl(context); 112 } 113 else if (op.Pos == 7 && op.Shift == 0) 114 { 115 Operand n = GetIntOrZR(context, op.Rn); 116 117 SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xff))); 118 } 119 else if (op.Pos == 15 && op.Shift == 0) 120 { 121 Operand n = GetIntOrZR(context, op.Rn); 122 123 SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xffff))); 124 } 125 else 126 { 127 SetIntOrZR(context, op.Rd, GetBfmN(context)); 128 } 129 } 130 131 private static void EmitSbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: true); 132 private static void EmitUbfiz(ArmEmitterContext context) => EmitBfiz(context, signed: false); 133 134 private static void EmitBfiz(ArmEmitterContext context, bool signed) 135 { 136 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 137 138 int width = op.Pos + 1; 139 140 Operand res = GetIntOrZR(context, op.Rn); 141 142 res = context.ShiftLeft(res, Const(op.GetBitsCount() - width)); 143 144 res = signed 145 ? context.ShiftRightSI(res, Const(op.Shift - width)) 146 : context.ShiftRightUI(res, Const(op.Shift - width)); 147 148 SetIntOrZR(context, op.Rd, res); 149 } 150 151 private static void EmitSbfmShift(ArmEmitterContext context) 152 { 153 EmitBfmShift(context, signed: true); 154 } 155 156 private static void EmitUbfmShift(ArmEmitterContext context) 157 { 158 EmitBfmShift(context, signed: false); 159 } 160 161 private static void EmitBfmShift(ArmEmitterContext context, bool signed) 162 { 163 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 164 165 Operand res = GetIntOrZR(context, op.Rn); 166 167 res = signed 168 ? context.ShiftRightSI(res, Const(op.Shift)) 169 : context.ShiftRightUI(res, Const(op.Shift)); 170 171 SetIntOrZR(context, op.Rd, res); 172 } 173 174 private static void EmitBfmLsl(ArmEmitterContext context) 175 { 176 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 177 178 Operand res = GetIntOrZR(context, op.Rn); 179 180 int shift = op.GetBitsCount() - op.Shift; 181 182 SetIntOrZR(context, op.Rd, context.ShiftLeft(res, Const(shift))); 183 } 184 185 private static Operand GetBfmN(ArmEmitterContext context) 186 { 187 OpCodeBfm op = (OpCodeBfm)context.CurrOp; 188 189 Operand res = GetIntOrZR(context, op.Rn); 190 191 long mask = op.WMask & op.TMask; 192 193 return context.BitwiseAnd(context.RotateRight(res, Const(op.Shift)), Const(res.Type, mask)); 194 } 195 } 196 }