1 #ifndef __MONO_MINI_MIPS_H__
2 #define __MONO_MINI_MIPS_H__
5 #include <mono/arch/mips/mips-codegen.h>
6 #include <mono/utils/mono-context.h>
8 #if _MIPS_SIM == _ABIO32
9 /* o32 fully supported */
10 #elif _MIPS_SIM == _ABIN32
11 /* n32 under development */
12 #warning "MIPS using n32 - under development"
14 /* o64 not supported */
15 /* n64 not supported */
16 #error "MIPS unsupported ABI"
20 #define MONO_ARCH_CPU_SPEC mips_desc
22 #define MONO_MAX_IREGS 32
23 #define MONO_MAX_FREGS 32
25 #define MONO_SAVED_GREGS 32
26 #define MONO_SAVED_FREGS 32
29 #if SIZEOF_REGISTER == 4
32 typedef gfloat mips_freg
;
34 #elif SIZEOF_REGISTER == 8
38 typedef gdouble mips_freg
;
41 #error Unknown REGISTER_SIZE
45 * at and t0 used internally
46 * v0, v1 aren't here for clarity reasons
47 * a0, a1, a2, a3 are for arguments
48 * Use t9 for indirect calls to match the ABI
51 #define MIPS_V_REGS ((1 << mips_v0) | \
53 #if _MIPS_SIM == _ABIO32
54 #define MIPS_T_REGS ((1 << mips_t0) | \
62 #elif _MIPS_SIM == _ABIN32
63 #define MIPS_T_REGS ((1 << mips_t0) | \
70 #define MIPS_S_REGS ((1 << mips_s0) | \
79 #if _MIPS_SIM == _ABIO32
80 #define MIPS_A_REGS ((1 << mips_a0) | \
84 #elif _MIPS_SIM == _ABIN32
85 #define MIPS_A_REGS ((1 << mips_a0) | \
95 #define mips_temp mips_t8
97 #define MONO_ARCH_CALLEE_REGS (MIPS_T_REGS | MIPS_V_REGS | MIPS_A_REGS)
98 #define MONO_ARCH_CALLEE_SAVED_REGS MIPS_S_REGS
99 #define MIPS_ARG_REGS MIPS_A_REGS
102 #define MIPS_FP_PAIR(reg) ((1 << (reg)) | (1 << ((reg)+1)))
104 /* Only put the even regs in */
105 #define MIPS_FP_PAIR(reg) (1 << (reg))
108 #if _MIPS_SIM == _ABIO32
109 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
110 MIPS_FP_PAIR(mips_f2) | \
111 MIPS_FP_PAIR(mips_f4) | \
112 MIPS_FP_PAIR(mips_f6) | \
113 MIPS_FP_PAIR(mips_f8) | \
114 MIPS_FP_PAIR(mips_f10) | \
115 MIPS_FP_PAIR(mips_f12) | \
116 MIPS_FP_PAIR(mips_f14) | \
117 MIPS_FP_PAIR(mips_f16) | \
118 MIPS_FP_PAIR(mips_f18))
120 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
121 MIPS_FP_PAIR(mips_f22) | \
122 MIPS_FP_PAIR(mips_f24) | \
123 MIPS_FP_PAIR(mips_f26) | \
124 MIPS_FP_PAIR(mips_f28) | \
125 MIPS_FP_PAIR(mips_f30))
126 #elif _MIPS_SIM == _ABIN32
127 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
128 MIPS_FP_PAIR(mips_f1) | \
129 MIPS_FP_PAIR(mips_f2) | \
130 MIPS_FP_PAIR(mips_f3) | \
131 MIPS_FP_PAIR(mips_f4) | \
132 MIPS_FP_PAIR(mips_f5) | \
133 MIPS_FP_PAIR(mips_f6) | \
134 MIPS_FP_PAIR(mips_f7) | \
135 MIPS_FP_PAIR(mips_f8) | \
136 MIPS_FP_PAIR(mips_f9) | \
137 MIPS_FP_PAIR(mips_f10) | \
138 MIPS_FP_PAIR(mips_f11) | \
139 MIPS_FP_PAIR(mips_f12) | \
140 MIPS_FP_PAIR(mips_f13) | \
141 MIPS_FP_PAIR(mips_f14) | \
142 MIPS_FP_PAIR(mips_f15) | \
143 MIPS_FP_PAIR(mips_f16) | \
144 MIPS_FP_PAIR(mips_f17) | \
145 MIPS_FP_PAIR(mips_f18) | \
146 MIPS_FP_PAIR(mips_f19))
148 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
149 MIPS_FP_PAIR(mips_f21) | \
150 MIPS_FP_PAIR(mips_f22) | \
151 MIPS_FP_PAIR(mips_f23) | \
152 MIPS_FP_PAIR(mips_f24) | \
153 MIPS_FP_PAIR(mips_f25) | \
154 MIPS_FP_PAIR(mips_f26) | \
155 MIPS_FP_PAIR(mips_f27) | \
156 MIPS_FP_PAIR(mips_f28) | \
157 MIPS_FP_PAIR(mips_f29) | \
158 MIPS_FP_PAIR(mips_f30) | \
159 MIPS_FP_PAIR(mips_f31))
162 #define mips_ftemp mips_f18
164 #define MONO_ARCH_USE_FPSTACK FALSE
165 #define MONO_ARCH_FPSTACK_SIZE 0
167 /* Parameters used by the register allocator */
169 /* On Mips, for regpairs, the lower-numbered reg is most significant
170 * This is true in both big and little endian
173 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
174 #define RET_REG1 mips_v0
175 #define RET_REG2 mips_v1
177 #define RET_REG1 mips_v1
178 #define RET_REG2 mips_v0
181 #define MONO_ARCH_INST_SREG2_MASK(ins) (0)
182 #define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc) == 'V' || (desc) == 'l')
183 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? RET_REG2 : -1))
184 #define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g'))
186 // This define is called to get specific dest register as defined
187 // by md file (letter after "dest"). Overwise return -1
189 #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)))))
191 #define MONO_ARCH_FRAME_ALIGNMENT 8
193 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
194 * reproduceable results for benchmarks */
195 #define MONO_ARCH_CODE_ALIGNMENT 32
197 void mips_patch (guint32
*code
, guint32 target
);
199 #define MIPS_LMF_MAGIC1 0xa5a5a5a5
200 #define MIPS_LMF_MAGIC2 0xc3c3c3c3
202 /* Registers saved in lmf->iregs */
203 #define MIPS_LMF_IREGMASK (0xffffffff & ~((1 << mips_zero) | (1 << mips_at) | MONO_ARCH_CALLEE_REGS))
206 gpointer previous_lmf
;
210 mgreg_t iregs
[MONO_SAVED_GREGS
];
211 mips_freg fregs
[MONO_SAVED_FREGS
];
215 typedef struct MonoCompileArch
{
219 guint local_alloc_offset
;
220 guint spillvar_offset
;
221 guint spillvar_offset_float
;
222 guint tracing_offset
;
225 gboolean omit_fp_computed
;
228 #if SIZEOF_REGISTER == 4
229 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
230 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
231 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
232 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
233 #define MONO_ARCH_EMULATE_FREM 1
234 #define MONO_ARCH_BIGMUL_INTRINS 1
237 #if SIZEOF_REGISTER == 8
238 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
241 #define MIPS_RET_ADDR_OFFSET (-sizeof(gpointer))
242 #define MIPS_FP_ADDR_OFFSET (-8)
243 #define MIPS_STACK_ALIGNMENT 16
244 #define MIPS_STACK_PARAM_OFFSET 16 /* from sp to first parameter */
245 #define MIPS_MINIMAL_STACK_SIZE (4*sizeof(mgreg_t) + 4*sizeof(mgreg_t))
246 #define MIPS_EXTRA_STACK_SIZE 16 /* from last parameter to top of frame */
248 #if _MIPS_SIM == _ABIO32
249 #define MIPS_FIRST_ARG_REG mips_a0
250 #define MIPS_LAST_ARG_REG mips_a3
251 #define MIPS_FIRST_FPARG_REG mips_f12
252 #define MIPS_LAST_FPARG_REG mips_f14
253 #elif _MIPS_SIM == _ABIN32
254 #define MIPS_FIRST_ARG_REG mips_a0
255 #define MIPS_LAST_ARG_REG mips_t3
256 #define MIPS_FIRST_FPARG_REG mips_f12
257 #define MIPS_LAST_FPARG_REG mips_f19
260 #define MONO_ARCH_HAVE_IMT 1
261 #define MONO_ARCH_IMT_REG mips_t0
263 #define MONO_ARCH_VTABLE_REG mips_a0
264 #define MONO_ARCH_RGCTX_REG MONO_ARCH_IMT_REG
266 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
267 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
269 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
270 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
271 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
272 #define MONO_ARCH_HAVE_XP_UNWIND 1
273 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
274 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
275 #define MONO_ARCH_GSHARED_SUPPORTED 1
277 /* set the next to 0 once inssel-mips.brg is updated */
278 #define MIPS_PASS_STRUCTS_BY_VALUE 1
280 #define MONO_ARCH_USE_SIGACTION
281 #define MONO_ARCH_NEED_DIV_CHECK 1
282 #define MONO_ARCH_NO_IOV_CHECK 1
284 #define MONO_ARCH_THIS_AS_FIRST_ARG 1
286 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
287 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
291 unsigned long at
; /* assembler temp */
292 unsigned long v0
; /* return values */
294 unsigned long a0
; /* 4 - func arguments */
298 unsigned long t0
; /* 8 temporaries */
306 unsigned long s0
; /* 16 calle saved */
314 unsigned long t8
; /* 24 temps */
315 unsigned long t9
; /* 25 temp / pic call-through register */
316 unsigned long k0
; /* 26 kernel-reserved */
318 unsigned long gp
; /* 28 */
319 unsigned long sp
; /* stack pointer */
320 unsigned long fp
; /* frame pointer */
321 unsigned long ra
; /* return address */
322 } MonoMipsStackFrame
;
324 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
325 MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
326 MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0)); \
327 MONO_CONTEXT_SET_IP ((ctx), (func)); \
330 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
332 /* re-attaches with gdb - sometimes causes executable to hang */
333 #undef HAVE_BACKTRACE_SYMBOLS
335 #undef DEBUG_EXCEPTIONS
337 #define MONO_ZERO_REG mips_zero
339 #define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
341 MONO_INST_NEW ((cfg), (inst), cond); \
342 inst->inst_p1 = (char*)name; \
345 MONO_ADD_INS ((cfg)->cbb, inst); \
348 #ifndef MONO_EMIT_NEW_COMPARE_EXC
349 #define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
350 switch (OP_MIPS_COND_EXC_##cmp_op) { \
351 case OP_MIPS_COND_EXC_EQ: \
352 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
354 case OP_MIPS_COND_EXC_NE_UN: \
355 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
357 case OP_MIPS_COND_EXC_GT: \
358 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
359 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
361 case OP_MIPS_COND_EXC_GT_UN: \
362 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
363 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
365 case OP_MIPS_COND_EXC_LE: \
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_EQ, mips_at, mips_zero, exc); \
369 case OP_MIPS_COND_EXC_LE_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_EQ, mips_at, mips_zero, exc); \
373 case OP_MIPS_COND_EXC_LT: \
374 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
375 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
377 case OP_MIPS_COND_EXC_LT_UN: \
378 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
379 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
382 g_warning ("unknown comparison %s\n", #cmp_op); \
383 g_assert_not_reached (); \
388 #ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
389 #define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
392 cmp_reg = mips_zero; \
396 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
398 MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
402 #ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
403 #define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
404 MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
415 extern guint8
*mips_emit_load_const(guint8
*code
, int dreg
, mgreg_t v
);
417 #endif /* __MONO_MINI_MIPS_H__ */