[interp] Small fixes (#11667)
[mono-project.git] / mono / mini / mini-mips.h
blob007c637009597a7a6e8a4ecea570f729ca6f2eb5
1 /**
2 * \file
3 */
5 #ifndef __MONO_MINI_MIPS_H__
6 #define __MONO_MINI_MIPS_H__
8 #include <glib.h>
9 #include <mono/arch/mips/mips-codegen.h>
10 #include <mono/utils/mono-context.h>
12 #if _MIPS_SIM == _ABIO32
13 /* o32 fully supported */
14 #elif _MIPS_SIM == _ABIN32
15 /* n32 under development */
16 #warning "MIPS using n32 - under development"
17 #else
18 /* o64 not supported */
19 /* n64 not supported */
20 #error "MIPS unsupported ABI"
21 #endif
24 #define MONO_ARCH_CPU_SPEC mono_mips_desc
26 #define MONO_MAX_IREGS 32
27 #define MONO_MAX_FREGS 32
29 #define MONO_SAVED_GREGS 32
30 #define MONO_SAVED_FREGS 32
33 #if SIZEOF_REGISTER == 4
34 #define IREG_SIZE 4
35 #define FREG_SIZE 4
36 typedef gfloat mips_freg;
38 #elif SIZEOF_REGISTER == 8
40 #define IREG_SIZE 8
41 #define FREG_SIZE 8
42 typedef gdouble mips_freg;
44 #else
45 #error Unknown REGISTER_SIZE
46 #endif
49 * at and t0 used internally
50 * v0, v1 aren't here for clarity reasons
51 * a0, a1, a2, a3 are for arguments
52 * Use t9 for indirect calls to match the ABI
55 #define MIPS_V_REGS ((1 << mips_v0) | \
56 (1 << mips_v1))
57 #if _MIPS_SIM == _ABIO32
58 #define MIPS_T_REGS ((1 << mips_t0) | \
59 (1 << mips_t1) | \
60 (1 << mips_t2) | \
61 (1 << mips_t3) | \
62 (1 << mips_t4) | \
63 (1 << mips_t5) | \
64 (1 << mips_t6) | \
65 (1 << mips_t7))
66 #elif _MIPS_SIM == _ABIN32
67 #define MIPS_T_REGS ((1 << mips_t0) | \
68 (1 << mips_t1) | \
69 (1 << mips_t2) | \
70 (1 << mips_t3))
71 #endif
74 #define MIPS_S_REGS ((1 << mips_s0) | \
75 (1 << mips_s1) | \
76 (1 << mips_s2) | \
77 (1 << mips_s3) | \
78 (1 << mips_s4) | \
79 (1 << mips_s5) | \
80 (1 << mips_s6) | \
81 (1 << mips_s7) | \
82 (1 << mips_fp))
83 #if _MIPS_SIM == _ABIO32
84 #define MIPS_A_REGS ((1 << mips_a0) | \
85 (1 << mips_a1) | \
86 (1 << mips_a2) | \
87 (1 << mips_a3))
88 #elif _MIPS_SIM == _ABIN32
89 #define MIPS_A_REGS ((1 << mips_a0) | \
90 (1 << mips_a1) | \
91 (1 << mips_a2) | \
92 (1 << mips_a3) | \
93 (1 << mips_a4) | \
94 (1 << mips_a5) | \
95 (1 << mips_a6) | \
96 (1 << mips_a7))
97 #endif
99 #define mips_temp mips_t8
101 #define MONO_ARCH_CALLEE_REGS (MIPS_T_REGS | MIPS_V_REGS | MIPS_A_REGS)
102 #define MONO_ARCH_CALLEE_SAVED_REGS MIPS_S_REGS
103 #define MIPS_ARG_REGS MIPS_A_REGS
105 #if 0
106 #define MIPS_FP_PAIR(reg) ((1 << (reg)) | (1 << ((reg)+1)))
107 #else
108 /* Only put the even regs in */
109 #define MIPS_FP_PAIR(reg) (1 << (reg))
110 #endif
112 #if _MIPS_SIM == _ABIO32
113 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
114 MIPS_FP_PAIR(mips_f2) | \
115 MIPS_FP_PAIR(mips_f4) | \
116 MIPS_FP_PAIR(mips_f6) | \
117 MIPS_FP_PAIR(mips_f8) | \
118 MIPS_FP_PAIR(mips_f10) | \
119 MIPS_FP_PAIR(mips_f12) | \
120 MIPS_FP_PAIR(mips_f14) | \
121 MIPS_FP_PAIR(mips_f16) | \
122 MIPS_FP_PAIR(mips_f18))
124 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
125 MIPS_FP_PAIR(mips_f22) | \
126 MIPS_FP_PAIR(mips_f24) | \
127 MIPS_FP_PAIR(mips_f26) | \
128 MIPS_FP_PAIR(mips_f28) | \
129 MIPS_FP_PAIR(mips_f30))
130 #elif _MIPS_SIM == _ABIN32
131 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
132 MIPS_FP_PAIR(mips_f1) | \
133 MIPS_FP_PAIR(mips_f2) | \
134 MIPS_FP_PAIR(mips_f3) | \
135 MIPS_FP_PAIR(mips_f4) | \
136 MIPS_FP_PAIR(mips_f5) | \
137 MIPS_FP_PAIR(mips_f6) | \
138 MIPS_FP_PAIR(mips_f7) | \
139 MIPS_FP_PAIR(mips_f8) | \
140 MIPS_FP_PAIR(mips_f9) | \
141 MIPS_FP_PAIR(mips_f10) | \
142 MIPS_FP_PAIR(mips_f11) | \
143 MIPS_FP_PAIR(mips_f12) | \
144 MIPS_FP_PAIR(mips_f13) | \
145 MIPS_FP_PAIR(mips_f14) | \
146 MIPS_FP_PAIR(mips_f15) | \
147 MIPS_FP_PAIR(mips_f16) | \
148 MIPS_FP_PAIR(mips_f17) | \
149 MIPS_FP_PAIR(mips_f18) | \
150 MIPS_FP_PAIR(mips_f19))
152 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
153 MIPS_FP_PAIR(mips_f21) | \
154 MIPS_FP_PAIR(mips_f22) | \
155 MIPS_FP_PAIR(mips_f23) | \
156 MIPS_FP_PAIR(mips_f24) | \
157 MIPS_FP_PAIR(mips_f25) | \
158 MIPS_FP_PAIR(mips_f26) | \
159 MIPS_FP_PAIR(mips_f27) | \
160 MIPS_FP_PAIR(mips_f28) | \
161 MIPS_FP_PAIR(mips_f29) | \
162 MIPS_FP_PAIR(mips_f30) | \
163 MIPS_FP_PAIR(mips_f31))
164 #endif
166 #define mips_ftemp mips_f18
168 #define MONO_ARCH_USE_FPSTACK FALSE
170 /* Parameters used by the register allocator */
172 /* On Mips, for regpairs, the lower-numbered reg is most significant
173 * This is true in both big and little endian
176 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
177 #define RET_REG1 mips_v0
178 #define RET_REG2 mips_v1
179 #else
180 #define RET_REG1 mips_v1
181 #define RET_REG2 mips_v0
182 #endif
184 #define MONO_ARCH_INST_SREG2_MASK(ins) (0)
185 #define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc) == 'V' || (desc) == 'l')
186 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? RET_REG2 : -1))
187 #define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g'))
189 // This define is called to get specific dest register as defined
190 // by md file (letter after "dest"). Overwise return -1
192 #define MONO_ARCH_INST_FIXED_REG(desc) (((desc) == '0') ? mips_zero : (((desc) == 'a') ? mips_at : ((((desc) == 'v')) ? mips_v0 : (((desc) == 'V') ? RET_REG1 : (((desc) == 'g') ? mips_f0 : -1)))))
194 #define MONO_ARCH_FRAME_ALIGNMENT 8
196 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
197 * reproduceable results for benchmarks */
198 #define MONO_ARCH_CODE_ALIGNMENT 32
200 void mips_patch (guint32 *code, guint32 target);
202 #define MIPS_LMF_MAGIC1 0xa5a5a5a5
203 #define MIPS_LMF_MAGIC2 0xc3c3c3c3
205 /* Registers saved in lmf->iregs */
206 #define MIPS_LMF_IREGMASK (0xffffffff & ~((1 << mips_zero) | (1 << mips_at) | MONO_ARCH_CALLEE_REGS))
208 struct MonoLMF {
209 gpointer previous_lmf;
210 gpointer lmf_addr;
211 MonoMethod *method;
212 gpointer eip;
213 host_mgreg_t iregs [MONO_SAVED_GREGS];
214 mips_freg fregs [MONO_SAVED_FREGS];
215 gulong magic;
218 typedef struct MonoCompileArch {
219 CallInfo *cinfo;
220 guint iregs_offset;
221 guint lmf_offset;
222 guint local_alloc_offset;
223 guint spillvar_offset;
224 guint spillvar_offset_float;
225 guint tracing_offset;
226 guint long_branch;
227 gboolean omit_fp;
228 gboolean omit_fp_computed;
229 } MonoCompileArch;
231 #if SIZEOF_REGISTER == 4
232 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
233 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
234 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
235 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
236 #define MONO_ARCH_EMULATE_FREM 1
237 #endif
240 * mips backend misses some instructions that enable emitting of optimal
241 * code on other targets and, additionally, the register allocator gets
242 * confused by this optimization, failing to allocate all hw regs.
244 #if SIZEOF_REGISTER == 4
245 #define MONO_ARCH_NO_DIV_WITH_MUL
246 #endif
248 #if SIZEOF_REGISTER == 8
249 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
250 #endif
252 #define MIPS_RET_ADDR_OFFSET (-sizeof(gpointer))
253 #define MIPS_FP_ADDR_OFFSET (-8)
254 #define MIPS_STACK_ALIGNMENT 16
255 #define MIPS_STACK_PARAM_OFFSET 16 /* from sp to first parameter */
256 #define MIPS_MINIMAL_STACK_SIZE (4*sizeof(mgreg_t) + 4*sizeof(mgreg_t))
257 #define MIPS_EXTRA_STACK_SIZE 16 /* from last parameter to top of frame */
259 #if _MIPS_SIM == _ABIO32
260 #define MIPS_FIRST_ARG_REG mips_a0
261 #define MIPS_LAST_ARG_REG mips_a3
262 #define MIPS_FIRST_FPARG_REG mips_f12
263 #define MIPS_LAST_FPARG_REG mips_f14
264 #elif _MIPS_SIM == _ABIN32
265 #define MIPS_FIRST_ARG_REG mips_a0
266 #define MIPS_LAST_ARG_REG mips_t3
267 #define MIPS_FIRST_FPARG_REG mips_f12
268 #define MIPS_LAST_FPARG_REG mips_f19
269 #endif
271 #define MONO_ARCH_IMT_REG mips_t0
273 #define MONO_ARCH_VTABLE_REG mips_a0
274 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
276 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
277 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
279 #define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
280 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
281 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
282 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
283 #define MONO_ARCH_GSHARED_SUPPORTED 1
285 /* set the next to 0 once inssel-mips.brg is updated */
286 #define MIPS_PASS_STRUCTS_BY_VALUE 1
288 #define MONO_ARCH_USE_SIGACTION
289 #define MONO_ARCH_NEED_DIV_CHECK 1
290 #define MONO_ARCH_NO_IOV_CHECK 1
292 // Does the ABI have a volatile non-parameter register, so tailcall
293 // can pass context to generics or interfaces?
294 #define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 0 // FIXME?
296 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
297 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
299 typedef struct {
300 unsigned long zero;
301 unsigned long at; /* assembler temp */
302 unsigned long v0; /* return values */
303 unsigned long v1;
304 unsigned long a0; /* 4 - func arguments */
305 unsigned long a1;
306 unsigned long a2;
307 unsigned long a3;
308 unsigned long t0; /* 8 temporaries */
309 unsigned long t1;
310 unsigned long t2;
311 unsigned long t3;
312 unsigned long t4;
313 unsigned long t5;
314 unsigned long t6;
315 unsigned long t7;
316 unsigned long s0; /* 16 calle saved */
317 unsigned long s1;
318 unsigned long s2;
319 unsigned long s3;
320 unsigned long s4;
321 unsigned long s5;
322 unsigned long s6;
323 unsigned long s7;
324 unsigned long t8; /* 24 temps */
325 unsigned long t9; /* 25 temp / pic call-through register */
326 unsigned long k0; /* 26 kernel-reserved */
327 unsigned long k1;
328 unsigned long gp; /* 28 */
329 unsigned long sp; /* stack pointer */
330 unsigned long fp; /* frame pointer */
331 unsigned long ra; /* return address */
332 } MonoMipsStackFrame;
334 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
335 MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
336 MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0)); \
337 MONO_CONTEXT_SET_IP ((ctx), (func)); \
338 } while (0)
340 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
342 /* re-attaches with gdb - sometimes causes executable to hang */
343 #undef HAVE_BACKTRACE_SYMBOLS
345 #undef DEBUG_EXCEPTIONS
347 #define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
348 MonoInst *inst; \
349 MONO_INST_NEW ((cfg), (inst), cond); \
350 inst->inst_p1 = (char*)name; \
351 inst->sreg1 = sr1; \
352 inst->sreg2 = sr2; \
353 MONO_ADD_INS ((cfg)->cbb, inst); \
354 } while (0)
356 #ifndef MONO_EMIT_NEW_COMPARE_EXC
357 #define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
358 switch (OP_MIPS_COND_EXC_##cmp_op) { \
359 case OP_MIPS_COND_EXC_EQ: \
360 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
361 break; \
362 case OP_MIPS_COND_EXC_NE_UN: \
363 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
364 break; \
365 case OP_MIPS_COND_EXC_GT: \
366 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
367 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
368 break; \
369 case OP_MIPS_COND_EXC_GT_UN: \
370 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
371 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
372 break; \
373 case OP_MIPS_COND_EXC_LE: \
374 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
375 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
376 break; \
377 case OP_MIPS_COND_EXC_LE_UN: \
378 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
379 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
380 break; \
381 case OP_MIPS_COND_EXC_LT: \
382 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
383 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
384 break; \
385 case OP_MIPS_COND_EXC_LT_UN: \
386 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
387 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
388 break; \
389 default: \
390 g_warning ("unknown comparison %s\n", #cmp_op); \
391 g_assert_not_reached (); \
393 } while (0)
394 #endif
396 #ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
397 #define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
398 guint32 cmp_reg; \
399 if (!(imm)) { \
400 cmp_reg = mips_zero; \
402 else { \
403 cmp_reg = mips_at; \
404 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
406 MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
407 } while (0)
408 #endif
410 #ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
411 #define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
412 MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
413 } while (0)
414 #endif
416 typedef struct {
417 gint8 reg;
418 gint8 size;
419 int vtsize;
420 int offset;
421 } MonoMIPSArgInfo;
423 extern guint8 *mips_emit_load_const(guint8 *code, int dreg, mgreg_t v);
425 #endif /* __MONO_MINI_MIPS_H__ */