1 /*
2 ** Definitions for MIPS CPUs.
3 ** Copyright (C) 2005-2021 Mike Pall. See Copyright Notice in luajit.h
4 */
5 
6 #ifndef _LJ_TARGET_MIPS_H
7 #define _LJ_TARGET_MIPS_H
8 
9 /* -- Registers IDs ------------------------------------------------------- */
10 
11 #define GPRDEF(_) \
12   _(R0) _(R1) _(R2) _(R3) _(R4) _(R5) _(R6) _(R7) \
13   _(R8) _(R9) _(R10) _(R11) _(R12) _(R13) _(R14) _(R15) \
14   _(R16) _(R17) _(R18) _(R19) _(R20) _(R21) _(R22) _(R23) \
15   _(R24) _(R25) _(SYS1) _(SYS2) _(R28) _(SP) _(R30) _(RA)
16 #if LJ_SOFTFP
17 #define FPRDEF(_)
18 #else
19 #define FPRDEF(_) \
20   _(F0) _(F1) _(F2) _(F3) _(F4) _(F5) _(F6) _(F7) \
21   _(F8) _(F9) _(F10) _(F11) _(F12) _(F13) _(F14) _(F15) \
22   _(F16) _(F17) _(F18) _(F19) _(F20) _(F21) _(F22) _(F23) \
23   _(F24) _(F25) _(F26) _(F27) _(F28) _(F29) _(F30) _(F31)
24 #endif
25 #define VRIDDEF(_)
26 
27 #define RIDENUM(name)	RID_##name,
28 
29 enum {
30   GPRDEF(RIDENUM)		/* General-purpose registers (GPRs). */
31   FPRDEF(RIDENUM)		/* Floating-point registers (FPRs). */
32   RID_MAX,
33   RID_ZERO = RID_R0,
34   RID_TMP = RID_RA,
35   RID_GP = RID_R28,
36 
37   /* Calling conventions. */
38   RID_RET = RID_R2,
39 #if LJ_LE
40   RID_RETHI = RID_R3,
41   RID_RETLO = RID_R2,
42 #else
43   RID_RETHI = RID_R2,
44   RID_RETLO = RID_R3,
45 #endif
46 #if LJ_SOFTFP
47   RID_FPRET = RID_R2,
48 #else
49   RID_FPRET = RID_F0,
50 #endif
51   RID_CFUNCADDR = RID_R25,
52 
53   /* These definitions must match with the *.dasc file(s): */
54   RID_BASE = RID_R16,		/* Interpreter BASE. */
55   RID_LPC = RID_R18,		/* Interpreter PC. */
56   RID_DISPATCH = RID_R19,	/* Interpreter DISPATCH table. */
57   RID_LREG = RID_R20,		/* Interpreter L. */
58   RID_JGL = RID_R30,		/* On-trace: global_State + 32768. */
59 
60   /* Register ranges [min, max) and number of registers. */
61   RID_MIN_GPR = RID_R0,
62   RID_MAX_GPR = RID_RA+1,
63   RID_MIN_FPR = RID_MAX_GPR,
64 #if LJ_SOFTFP
65   RID_MAX_FPR = RID_MIN_FPR,
66 #else
67   RID_MAX_FPR = RID_F31+1,
68 #endif
69   RID_NUM_GPR = RID_MAX_GPR - RID_MIN_GPR,
70   RID_NUM_FPR = RID_MAX_FPR - RID_MIN_FPR	/* Only even regs are used. */
71 };
72 
73 #define RID_NUM_KREF		RID_NUM_GPR
74 #define RID_MIN_KREF		RID_R0
75 
76 /* -- Register sets ------------------------------------------------------- */
77 
78 /* Make use of all registers, except ZERO, TMP, SP, SYS1, SYS2, JGL and GP. */
79 #define RSET_FIXED \
80   (RID2RSET(RID_ZERO)|RID2RSET(RID_TMP)|RID2RSET(RID_SP)|\
81    RID2RSET(RID_SYS1)|RID2RSET(RID_SYS2)|RID2RSET(RID_JGL)|RID2RSET(RID_GP))
82 #define RSET_GPR	(RSET_RANGE(RID_MIN_GPR, RID_MAX_GPR) - RSET_FIXED)
83 #if LJ_SOFTFP
84 #define RSET_FPR		0
85 #else
86 #if LJ_32
87 #define RSET_FPR \
88   (RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\
89    RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\
90    RID2RSET(RID_F16)|RID2RSET(RID_F18)|RID2RSET(RID_F20)|RID2RSET(RID_F22)|\
91    RID2RSET(RID_F24)|RID2RSET(RID_F26)|RID2RSET(RID_F28)|RID2RSET(RID_F30))
92 #else
93 #define RSET_FPR		RSET_RANGE(RID_MIN_FPR, RID_MAX_FPR)
94 #endif
95 #endif
96 #define RSET_ALL		(RSET_GPR|RSET_FPR)
97 #define RSET_INIT		RSET_ALL
98 
99 #define RSET_SCRATCH_GPR \
100   (RSET_RANGE(RID_R1, RID_R15+1)|\
101    RID2RSET(RID_R24)|RID2RSET(RID_R25))
102 #if LJ_SOFTFP
103 #define RSET_SCRATCH_FPR	0
104 #else
105 #if LJ_32
106 #define RSET_SCRATCH_FPR \
107   (RID2RSET(RID_F0)|RID2RSET(RID_F2)|RID2RSET(RID_F4)|RID2RSET(RID_F6)|\
108    RID2RSET(RID_F8)|RID2RSET(RID_F10)|RID2RSET(RID_F12)|RID2RSET(RID_F14)|\
109    RID2RSET(RID_F16)|RID2RSET(RID_F18))
110 #else
111 #define RSET_SCRATCH_FPR	RSET_RANGE(RID_F0, RID_F24)
112 #endif
113 #endif
114 #define RSET_SCRATCH		(RSET_SCRATCH_GPR|RSET_SCRATCH_FPR)
115 #define REGARG_FIRSTGPR		RID_R4
116 #if LJ_32
117 #define REGARG_LASTGPR		RID_R7
118 #define REGARG_NUMGPR		4
119 #else
120 #define REGARG_LASTGPR		RID_R11
121 #define REGARG_NUMGPR		8
122 #endif
123 #if LJ_ABI_SOFTFP
124 #define REGARG_FIRSTFPR		0
125 #define REGARG_LASTFPR		0
126 #define REGARG_NUMFPR		0
127 #else
128 #define REGARG_FIRSTFPR		RID_F12
129 #if LJ_32
130 #define REGARG_LASTFPR		RID_F14
131 #define REGARG_NUMFPR		2
132 #else
133 #define REGARG_LASTFPR		RID_F19
134 #define REGARG_NUMFPR		8
135 #endif
136 #endif
137 
138 /* -- Spill slots --------------------------------------------------------- */
139 
140 /* Spill slots are 32 bit wide. An even/odd pair is used for FPRs.
141 **
142 ** SPS_FIXED: Available fixed spill slots in interpreter frame.
143 ** This definition must match with the *.dasc file(s).
144 **
145 ** SPS_FIRST: First spill slot for general use.
146 */
147 #if LJ_32
148 #define SPS_FIXED	5
149 #else
150 #define SPS_FIXED	4
151 #endif
152 #define SPS_FIRST	4
153 
154 #define SPOFS_TMP	0
155 
156 #define sps_scale(slot)		(4 * (int32_t)(slot))
157 #define sps_align(slot)		(((slot) - SPS_FIXED + 1) & ~1)
158 
159 /* -- Exit state ---------------------------------------------------------- */
160 
161 /* This definition must match with the *.dasc file(s). */
162 typedef struct {
163 #if !LJ_SOFTFP
164   lua_Number fpr[RID_NUM_FPR];	/* Floating-point registers. */
165 #endif
166   intptr_t gpr[RID_NUM_GPR];	/* General-purpose registers. */
167   int32_t spill[256];		/* Spill slots. */
168 } ExitState;
169 
170 /* Highest exit + 1 indicates stack check. */
171 #define EXITSTATE_CHECKEXIT	1
172 
173 /* Return the address of a per-trace exit stub. */
exitstub_trace_addr_(uint32_t * p)174 static LJ_AINLINE uint32_t *exitstub_trace_addr_(uint32_t *p)
175 {
176   while (*p == 0x00000000) p++;  /* Skip MIPSI_NOP. */
177   return p;
178 }
179 /* Avoid dependence on lj_jit.h if only including lj_target.h. */
180 #define exitstub_trace_addr(T, exitno) \
181   exitstub_trace_addr_((MCode *)((char *)(T)->mcode + (T)->szmcode))
182 
183 /* -- Instructions -------------------------------------------------------- */
184 
185 /* Instruction fields. */
186 #define MIPSF_S(r)	((r) << 21)
187 #define MIPSF_T(r)	((r) << 16)
188 #define MIPSF_D(r)	((r) << 11)
189 #define MIPSF_R(r)	((r) << 21)
190 #define MIPSF_H(r)	((r) << 16)
191 #define MIPSF_G(r)	((r) << 11)
192 #define MIPSF_F(r)	((r) << 6)
193 #define MIPSF_A(n)	((n) << 6)
194 #define MIPSF_M(n)	((n) << 11)
195 #define MIPSF_L(n)	((n) << 6)
196 
197 typedef enum MIPSIns {
198   MIPSI_D = 0x38,
199   MIPSI_DV = 0x10,
200   MIPSI_D32 = 0x3c,
201   /* Integer instructions. */
202   MIPSI_MOVE = 0x00000025,
203   MIPSI_NOP = 0x00000000,
204 
205   MIPSI_LI = 0x24000000,
206   MIPSI_LU = 0x34000000,
207   MIPSI_LUI = 0x3c000000,
208 
209   MIPSI_AND = 0x00000024,
210   MIPSI_ANDI = 0x30000000,
211   MIPSI_OR = 0x00000025,
212   MIPSI_ORI = 0x34000000,
213   MIPSI_XOR = 0x00000026,
214   MIPSI_XORI = 0x38000000,
215   MIPSI_NOR = 0x00000027,
216 
217   MIPSI_SLT = 0x0000002a,
218   MIPSI_SLTU = 0x0000002b,
219   MIPSI_SLTI = 0x28000000,
220   MIPSI_SLTIU = 0x2c000000,
221 
222   MIPSI_ADDU = 0x00000021,
223   MIPSI_ADDIU = 0x24000000,
224   MIPSI_SUB = 0x00000022,
225   MIPSI_SUBU = 0x00000023,
226 
227 #if !LJ_TARGET_MIPSR6
228   MIPSI_MUL = 0x70000002,
229   MIPSI_DIV = 0x0000001a,
230   MIPSI_DIVU = 0x0000001b,
231 
232   MIPSI_MOVZ = 0x0000000a,
233   MIPSI_MOVN = 0x0000000b,
234   MIPSI_MFHI = 0x00000010,
235   MIPSI_MFLO = 0x00000012,
236   MIPSI_MULT = 0x00000018,
237 #else
238   MIPSI_MUL = 0x00000098,
239   MIPSI_MUH = 0x000000d8,
240   MIPSI_DIV = 0x0000009a,
241   MIPSI_DIVU = 0x0000009b,
242 
243   MIPSI_SELEQZ = 0x00000035,
244   MIPSI_SELNEZ = 0x00000037,
245 #endif
246 
247   MIPSI_SLL = 0x00000000,
248   MIPSI_SRL = 0x00000002,
249   MIPSI_SRA = 0x00000003,
250   MIPSI_ROTR = 0x00200002,	/* MIPSXXR2 */
251   MIPSI_DROTR = 0x0020003a,
252   MIPSI_DROTR32 = 0x0020003e,
253   MIPSI_SLLV = 0x00000004,
254   MIPSI_SRLV = 0x00000006,
255   MIPSI_SRAV = 0x00000007,
256   MIPSI_ROTRV = 0x00000046,	/* MIPSXXR2 */
257   MIPSI_DROTRV = 0x00000056,
258 
259   MIPSI_INS = 0x7c000004,	/* MIPSXXR2 */
260 
261   MIPSI_SEB = 0x7c000420,	/* MIPSXXR2 */
262   MIPSI_SEH = 0x7c000620,	/* MIPSXXR2 */
263   MIPSI_WSBH = 0x7c0000a0,	/* MIPSXXR2 */
264   MIPSI_DSBH = 0x7c0000a4,
265 
266   MIPSI_B = 0x10000000,
267   MIPSI_J = 0x08000000,
268   MIPSI_JAL = 0x0c000000,
269 #if !LJ_TARGET_MIPSR6
270   MIPSI_JALX = 0x74000000,
271   MIPSI_JR = 0x00000008,
272 #else
273   MIPSI_JR = 0x00000009,
274   MIPSI_BALC = 0xe8000000,
275 #endif
276   MIPSI_JALR = 0x0000f809,
277 
278   MIPSI_BEQ = 0x10000000,
279   MIPSI_BNE = 0x14000000,
280   MIPSI_BLEZ = 0x18000000,
281   MIPSI_BGTZ = 0x1c000000,
282   MIPSI_BLTZ = 0x04000000,
283   MIPSI_BGEZ = 0x04010000,
284 
285   /* Load/store instructions. */
286   MIPSI_LW = 0x8c000000,
287   MIPSI_LD = 0xdc000000,
288   MIPSI_SW = 0xac000000,
289   MIPSI_SD = 0xfc000000,
290   MIPSI_LB = 0x80000000,
291   MIPSI_SB = 0xa0000000,
292   MIPSI_LH = 0x84000000,
293   MIPSI_SH = 0xa4000000,
294   MIPSI_LBU = 0x90000000,
295   MIPSI_LHU = 0x94000000,
296   MIPSI_LWC1 = 0xc4000000,
297   MIPSI_SWC1 = 0xe4000000,
298   MIPSI_LDC1 = 0xd4000000,
299   MIPSI_SDC1 = 0xf4000000,
300 
301   /* MIPS64 instructions. */
302   MIPSI_DADD = 0x0000002c,
303   MIPSI_DADDU = 0x0000002d,
304   MIPSI_DADDIU = 0x64000000,
305   MIPSI_DSUB = 0x0000002e,
306   MIPSI_DSUBU = 0x0000002f,
307 #if !LJ_TARGET_MIPSR6
308   MIPSI_DDIV = 0x0000001e,
309   MIPSI_DDIVU = 0x0000001f,
310   MIPSI_DMULT = 0x0000001c,
311   MIPSI_DMULTU = 0x0000001d,
312 #else
313   MIPSI_DDIV = 0x0000009e,
314   MIPSI_DMOD = 0x000000de,
315   MIPSI_DDIVU = 0x0000009f,
316   MIPSI_DMODU = 0x000000df,
317   MIPSI_DMUL = 0x0000009c,
318   MIPSI_DMUH = 0x000000dc,
319 #endif
320 
321   MIPSI_DSLL = 0x00000038,
322   MIPSI_DSRL = 0x0000003a,
323   MIPSI_DSLLV = 0x00000014,
324   MIPSI_DSRLV = 0x00000016,
325   MIPSI_DSRA = 0x0000003b,
326   MIPSI_DSRAV = 0x00000017,
327   MIPSI_DSRA32 = 0x0000003f,
328   MIPSI_DSLL32 = 0x0000003c,
329   MIPSI_DSRL32 = 0x0000003e,
330   MIPSI_DSHD = 0x7c000164,
331 
332   MIPSI_AADDU = LJ_32 ? MIPSI_ADDU : MIPSI_DADDU,
333   MIPSI_AADDIU = LJ_32 ? MIPSI_ADDIU : MIPSI_DADDIU,
334   MIPSI_ASUBU = LJ_32 ? MIPSI_SUBU : MIPSI_DSUBU,
335   MIPSI_AL = LJ_32 ? MIPSI_LW : MIPSI_LD,
336   MIPSI_AS = LJ_32 ? MIPSI_SW : MIPSI_SD,
337 #if LJ_TARGET_MIPSR6
338   MIPSI_LSA = 0x00000005,
339   MIPSI_DLSA = 0x00000015,
340   MIPSI_ALSA = LJ_32 ? MIPSI_LSA : MIPSI_DLSA,
341 #endif
342 
343   /* Extract/insert instructions. */
344   MIPSI_DEXTM = 0x7c000001,
345   MIPSI_DEXTU = 0x7c000002,
346   MIPSI_DEXT = 0x7c000003,
347   MIPSI_DINSM = 0x7c000005,
348   MIPSI_DINSU = 0x7c000006,
349   MIPSI_DINS = 0x7c000007,
350 
351   MIPSI_FLOOR_D = 0x4620000b,
352 
353   /* FP instructions. */
354   MIPSI_MOV_S = 0x46000006,
355   MIPSI_MOV_D = 0x46200006,
356 #if !LJ_TARGET_MIPSR6
357   MIPSI_MOVT_D = 0x46210011,
358   MIPSI_MOVF_D = 0x46200011,
359 #else
360   MIPSI_MIN_D = 0x4620001C,
361   MIPSI_MAX_D = 0x4620001E,
362   MIPSI_SEL_D = 0x46200010,
363 #endif
364 
365   MIPSI_ABS_D = 0x46200005,
366   MIPSI_NEG_D = 0x46200007,
367 
368   MIPSI_ADD_D = 0x46200000,
369   MIPSI_SUB_D = 0x46200001,
370   MIPSI_MUL_D = 0x46200002,
371   MIPSI_DIV_D = 0x46200003,
372   MIPSI_SQRT_D = 0x46200004,
373 
374   MIPSI_ADD_S = 0x46000000,
375   MIPSI_SUB_S = 0x46000001,
376 
377   MIPSI_CVT_D_S = 0x46000021,
378   MIPSI_CVT_W_S = 0x46000024,
379   MIPSI_CVT_S_D = 0x46200020,
380   MIPSI_CVT_W_D = 0x46200024,
381   MIPSI_CVT_S_W = 0x46800020,
382   MIPSI_CVT_D_W = 0x46800021,
383   MIPSI_CVT_S_L = 0x46a00020,
384   MIPSI_CVT_D_L = 0x46a00021,
385 
386   MIPSI_TRUNC_W_S = 0x4600000d,
387   MIPSI_TRUNC_W_D = 0x4620000d,
388   MIPSI_TRUNC_L_S = 0x46000009,
389   MIPSI_TRUNC_L_D = 0x46200009,
390   MIPSI_FLOOR_W_S = 0x4600000f,
391   MIPSI_FLOOR_W_D = 0x4620000f,
392 
393   MIPSI_MFC1 = 0x44000000,
394   MIPSI_MTC1 = 0x44800000,
395   MIPSI_DMTC1 = 0x44a00000,
396   MIPSI_DMFC1 = 0x44200000,
397 
398 #if !LJ_TARGET_MIPSR6
399   MIPSI_BC1F = 0x45000000,
400   MIPSI_BC1T = 0x45010000,
401   MIPSI_C_EQ_D = 0x46200032,
402   MIPSI_C_OLT_S = 0x46000034,
403   MIPSI_C_OLT_D = 0x46200034,
404   MIPSI_C_ULT_D = 0x46200035,
405   MIPSI_C_OLE_D = 0x46200036,
406   MIPSI_C_ULE_D = 0x46200037,
407 #else
408   MIPSI_BC1EQZ = 0x45200000,
409   MIPSI_BC1NEZ = 0x45a00000,
410   MIPSI_CMP_EQ_D = 0x46a00002,
411   MIPSI_CMP_LT_S = 0x46800004,
412   MIPSI_CMP_LT_D = 0x46a00004,
413 #endif
414 
415 } MIPSIns;
416 
417 #endif
418