1 /* 2 ** Definitions for ARM CPUs. 3 ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h 4 */ 5 6 #ifndef _LJ_TARGET_ARM_H 7 #define _LJ_TARGET_ARM_H 8 9 /* -- Registers IDs ------------------------------------------------------- */ 10 11 #define GPRDEF(_) \ 12 _(R0) _(R1) _(R2) _(R3) _(R4) _(R5) _(R6) _(R7) \ 13 _(R8) _(R9) _(R10) _(R11) _(R12) _(SP) _(LR) _(PC) 14 #if LJ_SOFTFP 15 #define FPRDEF(_) 16 #else 17 #define FPRDEF(_) \ 18 _(D0) _(D1) _(D2) _(D3) _(D4) _(D5) _(D6) _(D7) \ 19 _(D8) _(D9) _(D10) _(D11) _(D12) _(D13) _(D14) _(D15) 20 #endif 21 #define VRIDDEF(_) 22 23 #define RIDENUM(name) RID_##name, 24 25 enum { 26 GPRDEF(RIDENUM) /* General-purpose registers (GPRs). */ 27 FPRDEF(RIDENUM) /* Floating-point registers (FPRs). */ 28 RID_MAX, 29 RID_TMP = RID_LR, 30 31 /* Calling conventions. */ 32 RID_RET = RID_R0, 33 RID_RETLO = RID_R0, 34 RID_RETHI = RID_R1, 35 #if LJ_SOFTFP 36 RID_FPRET = RID_R0, 37 #else 38 RID_FPRET = RID_D0, 39 #endif 40 41 /* These definitions must match with the *.dasc file(s): */ 42 RID_BASE = RID_R9, /* Interpreter BASE. */ 43 RID_LPC = RID_R6, /* Interpreter PC. */ 44 RID_DISPATCH = RID_R7, /* Interpreter DISPATCH table. */ 45 RID_LREG = RID_R8, /* Interpreter L. */ 46 47 /* Register ranges [min, max) and number of registers. */ 48 RID_MIN_GPR = RID_R0, 49 RID_MAX_GPR = RID_PC+1, 50 RID_MIN_FPR = RID_MAX_GPR, 51 #if LJ_SOFTFP 52 RID_MAX_FPR = RID_MIN_FPR, 53 #else 54 RID_MAX_FPR = RID_D15+1, 55 #endif 56 RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR, 57 RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR 58 }; 59 60 #define RID_NUM_KREF RID_NUM_GPR 61 #define RID_MIN_KREF RID_R0 62 63 /* -- Register sets ------------------------------------------------------- */ 64 65 /* Make use of all registers, except sp, lr and pc. */ 66 #define RSET_GPR (RSET_RANGE(RID_MIN_GPR, RID_R12+1)) 67 #define RSET_GPREVEN \ 68 (RID2RSET(RID_R0)|RID2RSET(RID_R2)|RID2RSET(RID_R4)|RID2RSET(RID_R6)| \ 69 RID2RSET(RID_R8)|RID2RSET(RID_R10)) 70 #define RSET_GPRODD \ 71 (RID2RSET(RID_R1)|RID2RSET(RID_R3)|RID2RSET(RID_R5)|RID2RSET(RID_R7)| \ 72 RID2RSET(RID_R9)|RID2RSET(RID_R11)) 73 #if LJ_SOFTFP 74 #define RSET_FPR 0 75 #else 76 #define RSET_FPR (RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)) 77 #endif 78 #define RSET_ALL (RSET_GPR|RSET_FPR) 79 #define RSET_INIT RSET_ALL 80 81 /* ABI-specific register sets. lr is an implicit scratch register. */ 82 #define RSET_SCRATCH_GPR_ (RSET_RANGE(RID_R0, RID_R3+1)|RID2RSET(RID_R12)) 83 #ifdef __APPLE__ 84 #define RSET_SCRATCH_GPR (RSET_SCRATCH_GPR_|RID2RSET(RID_R9)) 85 #else 86 #define RSET_SCRATCH_GPR RSET_SCRATCH_GPR_ 87 #endif 88 #if LJ_SOFTFP 89 #define RSET_SCRATCH_FPR 0 90 #else 91 #define RSET_SCRATCH_FPR (RSET_RANGE(RID_D0, RID_D7+1)) 92 #endif 93 #define RSET_SCRATCH (RSET_SCRATCH_GPR|RSET_SCRATCH_FPR) 94 #define REGARG_FIRSTGPR RID_R0 95 #define REGARG_LASTGPR RID_R3 96 #define REGARG_NUMGPR 4 97 #if LJ_ABI_SOFTFP 98 #define REGARG_FIRSTFPR 0 99 #define REGARG_LASTFPR 0 100 #define REGARG_NUMFPR 0 101 #else 102 #define REGARG_FIRSTFPR RID_D0 103 #define REGARG_LASTFPR RID_D7 104 #define REGARG_NUMFPR 8 105 #endif 106 107 /* -- Spill slots --------------------------------------------------------- */ 108 109 /* Spill slots are 32 bit wide. An even/odd pair is used for FPRs. 110 ** 111 ** SPS_FIXED: Available fixed spill slots in interpreter frame. 112 ** This definition must match with the *.dasc file(s). 113 ** 114 ** SPS_FIRST: First spill slot for general use. Reserve min. two 32 bit slots. 115 */ 116 #define SPS_FIXED 2 117 #define SPS_FIRST 2 118 119 #define SPOFS_TMP 0 120 121 #define sps_scale(slot) (4 * (int32_t)(slot)) 122 #define sps_align(slot) (((slot) - SPS_FIXED + 1) & ~1) 123 124 /* -- Exit state ---------------------------------------------------------- */ 125 126 /* This definition must match with the *.dasc file(s). */ 127 typedef struct { 128 #if !LJ_SOFTFP 129 lua_Number fpr[RID_NUM_FPR]; /* Floating-point registers. */ 130 #endif 131 int32_t gpr[RID_NUM_GPR]; /* General-purpose registers. */ 132 int32_t spill[256]; /* Spill slots. */ 133 } ExitState; 134 135 /* PC after instruction that caused an exit. Used to find the trace number. */ 136 #define EXITSTATE_PCREG RID_PC 137 /* Highest exit + 1 indicates stack check. */ 138 #define EXITSTATE_CHECKEXIT 1 139 140 #define EXITSTUB_SPACING 4 141 #define EXITSTUBS_PER_GROUP 32 142 143 /* -- Instructions -------------------------------------------------------- */ 144 145 /* Instruction fields. */ 146 #define ARMF_CC(ai, cc) (((ai) ^ ARMI_CCAL) | ((cc) << 28)) 147 #define ARMF_N(r) ((r) << 16) 148 #define ARMF_D(r) ((r) << 12) 149 #define ARMF_S(r) ((r) << 8) 150 #define ARMF_M(r) (r) 151 #define ARMF_SH(sh, n) (((sh) << 5) | ((n) << 7)) 152 #define ARMF_RSH(sh, r) (0x10 | ((sh) << 5) | ARMF_S(r)) 153 154 typedef enum ARMIns { 155 ARMI_CCAL = 0xe0000000, 156 ARMI_S = 0x000100000, 157 ARMI_K12 = 0x02000000, 158 ARMI_KNEG = 0x00200000, 159 ARMI_LS_W = 0x00200000, 160 ARMI_LS_U = 0x00800000, 161 ARMI_LS_P = 0x01000000, 162 ARMI_LS_R = 0x02000000, 163 ARMI_LSX_I = 0x00400000, 164 165 ARMI_AND = 0xe0000000, 166 ARMI_EOR = 0xe0200000, 167 ARMI_SUB = 0xe0400000, 168 ARMI_RSB = 0xe0600000, 169 ARMI_ADD = 0xe0800000, 170 ARMI_ADC = 0xe0a00000, 171 ARMI_SBC = 0xe0c00000, 172 ARMI_RSC = 0xe0e00000, 173 ARMI_TST = 0xe1100000, 174 ARMI_TEQ = 0xe1300000, 175 ARMI_CMP = 0xe1500000, 176 ARMI_CMN = 0xe1700000, 177 ARMI_ORR = 0xe1800000, 178 ARMI_MOV = 0xe1a00000, 179 ARMI_BIC = 0xe1c00000, 180 ARMI_MVN = 0xe1e00000, 181 182 ARMI_NOP = 0xe1a00000, 183 184 ARMI_MUL = 0xe0000090, 185 ARMI_SMULL = 0xe0c00090, 186 187 ARMI_LDR = 0xe4100000, 188 ARMI_LDRB = 0xe4500000, 189 ARMI_LDRH = 0xe01000b0, 190 ARMI_LDRSB = 0xe01000d0, 191 ARMI_LDRSH = 0xe01000f0, 192 ARMI_LDRD = 0xe00000d0, 193 ARMI_STR = 0xe4000000, 194 ARMI_STRB = 0xe4400000, 195 ARMI_STRH = 0xe00000b0, 196 ARMI_STRD = 0xe00000f0, 197 ARMI_PUSH = 0xe92d0000, 198 199 ARMI_B = 0xea000000, 200 ARMI_BL = 0xeb000000, 201 ARMI_BLX = 0xfa000000, 202 ARMI_BLXr = 0xe12fff30, 203 204 /* ARMv6 */ 205 ARMI_REV = 0xe6bf0f30, 206 ARMI_SXTB = 0xe6af0070, 207 ARMI_SXTH = 0xe6bf0070, 208 ARMI_UXTB = 0xe6ef0070, 209 ARMI_UXTH = 0xe6ff0070, 210 211 /* ARMv6T2 */ 212 ARMI_MOVW = 0xe3000000, 213 ARMI_MOVT = 0xe3400000, 214 ARMI_BFI = 0xe7c00010, 215 216 /* VFP */ 217 ARMI_VMOV_D = 0xeeb00b40, 218 ARMI_VMOV_S = 0xeeb00a40, 219 ARMI_VMOVI_D = 0xeeb00b00, 220 221 ARMI_VMOV_R_S = 0xee100a10, 222 ARMI_VMOV_S_R = 0xee000a10, 223 ARMI_VMOV_RR_D = 0xec500b10, 224 ARMI_VMOV_D_RR = 0xec400b10, 225 226 ARMI_VADD_D = 0xee300b00, 227 ARMI_VSUB_D = 0xee300b40, 228 ARMI_VMUL_D = 0xee200b00, 229 ARMI_VMLA_D = 0xee000b00, 230 ARMI_VMLS_D = 0xee000b40, 231 ARMI_VNMLS_D = 0xee100b00, 232 ARMI_VDIV_D = 0xee800b00, 233 234 ARMI_VABS_D = 0xeeb00bc0, 235 ARMI_VNEG_D = 0xeeb10b40, 236 ARMI_VSQRT_D = 0xeeb10bc0, 237 238 ARMI_VCMP_D = 0xeeb40b40, 239 ARMI_VCMPZ_D = 0xeeb50b40, 240 241 ARMI_VMRS = 0xeef1fa10, 242 243 ARMI_VCVT_S32_F32 = 0xeebd0ac0, 244 ARMI_VCVT_S32_F64 = 0xeebd0bc0, 245 ARMI_VCVT_U32_F32 = 0xeebc0ac0, 246 ARMI_VCVT_U32_F64 = 0xeebc0bc0, 247 ARMI_VCVT_F32_S32 = 0xeeb80ac0, 248 ARMI_VCVT_F64_S32 = 0xeeb80bc0, 249 ARMI_VCVT_F32_U32 = 0xeeb80a40, 250 ARMI_VCVT_F64_U32 = 0xeeb80b40, 251 ARMI_VCVT_F32_F64 = 0xeeb70bc0, 252 ARMI_VCVT_F64_F32 = 0xeeb70ac0, 253 254 ARMI_VLDR_S = 0xed100a00, 255 ARMI_VLDR_D = 0xed100b00, 256 ARMI_VSTR_S = 0xed000a00, 257 ARMI_VSTR_D = 0xed000b00, 258 } ARMIns; 259 260 typedef enum ARMShift { 261 ARMSH_LSL, ARMSH_LSR, ARMSH_ASR, ARMSH_ROR 262 } ARMShift; 263 264 /* ARM condition codes. */ 265 typedef enum ARMCC { 266 CC_EQ, CC_NE, CC_CS, CC_CC, CC_MI, CC_PL, CC_VS, CC_VC, 267 CC_HI, CC_LS, CC_GE, CC_LT, CC_GT, CC_LE, CC_AL, 268 CC_HS = CC_CS, CC_LO = CC_CC 269 } ARMCC; 270 271 #endif 272