InstEmitMemory.cs
1 using ARMeilleure.Decoders; 2 using ARMeilleure.IntermediateRepresentation; 3 using ARMeilleure.Translation; 4 5 using static ARMeilleure.Instructions.InstEmitHelper; 6 using static ARMeilleure.Instructions.InstEmitMemoryHelper; 7 using static ARMeilleure.IntermediateRepresentation.Operand.Factory; 8 9 namespace ARMeilleure.Instructions 10 { 11 static partial class InstEmit 12 { 13 public static void Adr(ArmEmitterContext context) 14 { 15 OpCodeAdr op = (OpCodeAdr)context.CurrOp; 16 17 SetIntOrZR(context, op.Rd, Const(op.Address + (ulong)op.Immediate)); 18 } 19 20 public static void Adrp(ArmEmitterContext context) 21 { 22 OpCodeAdr op = (OpCodeAdr)context.CurrOp; 23 24 ulong address = (op.Address & ~0xfffUL) + ((ulong)op.Immediate << 12); 25 26 SetIntOrZR(context, op.Rd, Const(address)); 27 } 28 29 public static void Ldr(ArmEmitterContext context) => EmitLdr(context, signed: false); 30 public static void Ldrs(ArmEmitterContext context) => EmitLdr(context, signed: true); 31 32 private static void EmitLdr(ArmEmitterContext context, bool signed) 33 { 34 OpCodeMem op = (OpCodeMem)context.CurrOp; 35 36 Operand address = GetAddress(context); 37 38 if (signed && op.Extend64) 39 { 40 EmitLoadSx64(context, address, op.Rt, op.Size); 41 } 42 else if (signed) 43 { 44 EmitLoadSx32(context, address, op.Rt, op.Size); 45 } 46 else 47 { 48 EmitLoadZx(context, address, op.Rt, op.Size); 49 } 50 51 EmitWBackIfNeeded(context, address); 52 } 53 54 public static void Ldr_Literal(ArmEmitterContext context) 55 { 56 IOpCodeLit op = (IOpCodeLit)context.CurrOp; 57 58 if (op.Prefetch) 59 { 60 return; 61 } 62 63 if (op.Signed) 64 { 65 EmitLoadSx64(context, Const(op.Immediate), op.Rt, op.Size); 66 } 67 else 68 { 69 EmitLoadZx(context, Const(op.Immediate), op.Rt, op.Size); 70 } 71 } 72 73 public static void Ldp(ArmEmitterContext context) 74 { 75 OpCodeMemPair op = (OpCodeMemPair)context.CurrOp; 76 77 void EmitLoad(int rt, Operand ldAddr) 78 { 79 if (op.Extend64) 80 { 81 EmitLoadSx64(context, ldAddr, rt, op.Size); 82 } 83 else 84 { 85 EmitLoadZx(context, ldAddr, rt, op.Size); 86 } 87 } 88 89 Operand address = GetAddress(context); 90 Operand address2 = GetAddress(context, 1L << op.Size); 91 92 EmitLoad(op.Rt, address); 93 EmitLoad(op.Rt2, address2); 94 95 EmitWBackIfNeeded(context, address); 96 } 97 98 public static void Str(ArmEmitterContext context) 99 { 100 OpCodeMem op = (OpCodeMem)context.CurrOp; 101 102 Operand address = GetAddress(context); 103 104 EmitStore(context, address, op.Rt, op.Size); 105 106 EmitWBackIfNeeded(context, address); 107 } 108 109 public static void Stp(ArmEmitterContext context) 110 { 111 OpCodeMemPair op = (OpCodeMemPair)context.CurrOp; 112 113 Operand address = GetAddress(context); 114 Operand address2 = GetAddress(context, 1L << op.Size); 115 116 EmitStore(context, address, op.Rt, op.Size); 117 EmitStore(context, address2, op.Rt2, op.Size); 118 119 EmitWBackIfNeeded(context, address); 120 } 121 122 private static Operand GetAddress(ArmEmitterContext context, long addend = 0) 123 { 124 Operand address = default; 125 126 switch (context.CurrOp) 127 { 128 case OpCodeMemImm op: 129 { 130 address = context.Copy(GetIntOrSP(context, op.Rn)); 131 132 // Pre-indexing. 133 if (!op.PostIdx) 134 { 135 address = context.Add(address, Const(op.Immediate + addend)); 136 } 137 else if (addend != 0) 138 { 139 address = context.Add(address, Const(addend)); 140 } 141 142 break; 143 } 144 145 case OpCodeMemReg op: 146 { 147 Operand n = GetIntOrSP(context, op.Rn); 148 149 Operand m = GetExtendedM(context, op.Rm, op.IntType); 150 151 if (op.Shift) 152 { 153 m = context.ShiftLeft(m, Const(op.Size)); 154 } 155 156 address = context.Add(n, m); 157 158 if (addend != 0) 159 { 160 address = context.Add(address, Const(addend)); 161 } 162 163 break; 164 } 165 } 166 167 return address; 168 } 169 170 private static void EmitWBackIfNeeded(ArmEmitterContext context, Operand address) 171 { 172 // Check whenever the current OpCode has post-indexed write back, if so write it. 173 if (context.CurrOp is OpCodeMemImm op && op.WBack) 174 { 175 if (op.PostIdx) 176 { 177 address = context.Add(address, Const(op.Immediate)); 178 } 179 180 SetIntOrSP(context, op.Rn, address); 181 } 182 } 183 } 184 }