1 #ifndef __MONO_MINI_MIPS_H__
2 #define __MONO_MINI_MIPS_H__
5 #include <mono/arch/mips/mips-codegen.h>
7 #if _MIPS_SIM == _ABIO32
8 /* o32 fully supported */
9 #elif _MIPS_SIM == _ABIN32
10 /* n32 under development */
11 #warning "MIPS using n32 - under development"
13 /* o64 not supported */
14 /* n64 not supported */
15 #error "MIPS unsupported ABI"
19 #define MONO_ARCH_CPU_SPEC mips_desc
21 #define MONO_MAX_IREGS 32
22 #define MONO_MAX_FREGS 32
24 #define MONO_SAVED_GREGS 32
25 #define MONO_SAVED_FREGS 32
28 #if SIZEOF_REGISTER == 4
30 typedef guint32 mips_ireg;
32 typedef gfloat mips_freg;
34 #elif SIZEOF_REGISTER == 8
37 typedef guint64 mips_ireg;
39 typedef gdouble mips_freg;
42 #error Unknown REGISTER_SIZE
45 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
46 #define MSW_OFFSET sizeof(mips_ireg)
50 #define LSW_OFFSET sizeof(mips_ireg)
54 * at and t0 used internally
55 * v0, v1 aren't here for clarity reasons
56 * a0, a1, a2, a3 are for arguments
57 * Use t9 for indirect calls to match the ABI
60 #define MIPS_V_REGS ((1 << mips_v0) | \
62 #if _MIPS_SIM == _ABIO32
63 #define MIPS_T_REGS ((1 << mips_t0) | \
71 #elif _MIPS_SIM == _ABIN32
72 #define MIPS_T_REGS ((1 << mips_t0) | \
79 #define MIPS_S_REGS ((1 << mips_s0) | \
88 #if _MIPS_SIM == _ABIO32
89 #define MIPS_A_REGS ((1 << mips_a0) | \
93 #elif _MIPS_SIM == _ABIN32
94 #define MIPS_A_REGS ((1 << mips_a0) | \
104 #define mips_temp mips_t8
106 #define MONO_ARCH_CALLEE_REGS (MIPS_T_REGS | MIPS_V_REGS)
107 #define MONO_ARCH_CALLEE_SAVED_REGS MIPS_S_REGS
108 #define MIPS_ARG_REGS MIPS_A_REGS
111 #define MIPS_FP_PAIR(reg) ((1 << (reg)) | (1 << ((reg)+1)))
113 /* Only put the even regs in */
114 #define MIPS_FP_PAIR(reg) (1 << (reg))
117 #if _MIPS_SIM == _ABIO32
118 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
119 MIPS_FP_PAIR(mips_f2) | \
120 MIPS_FP_PAIR(mips_f4) | \
121 MIPS_FP_PAIR(mips_f6) | \
122 MIPS_FP_PAIR(mips_f8) | \
123 MIPS_FP_PAIR(mips_f10) | \
124 MIPS_FP_PAIR(mips_f12) | \
125 MIPS_FP_PAIR(mips_f14) | \
126 MIPS_FP_PAIR(mips_f16) | \
127 MIPS_FP_PAIR(mips_f18))
129 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
130 MIPS_FP_PAIR(mips_f22) | \
131 MIPS_FP_PAIR(mips_f24) | \
132 MIPS_FP_PAIR(mips_f26) | \
133 MIPS_FP_PAIR(mips_f28) | \
134 MIPS_FP_PAIR(mips_f30))
135 #elif _MIPS_SIM == _ABIN32
136 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
137 MIPS_FP_PAIR(mips_f1) | \
138 MIPS_FP_PAIR(mips_f2) | \
139 MIPS_FP_PAIR(mips_f3) | \
140 MIPS_FP_PAIR(mips_f4) | \
141 MIPS_FP_PAIR(mips_f5) | \
142 MIPS_FP_PAIR(mips_f6) | \
143 MIPS_FP_PAIR(mips_f7) | \
144 MIPS_FP_PAIR(mips_f8) | \
145 MIPS_FP_PAIR(mips_f9) | \
146 MIPS_FP_PAIR(mips_f10) | \
147 MIPS_FP_PAIR(mips_f11) | \
148 MIPS_FP_PAIR(mips_f12) | \
149 MIPS_FP_PAIR(mips_f13) | \
150 MIPS_FP_PAIR(mips_f14) | \
151 MIPS_FP_PAIR(mips_f15) | \
152 MIPS_FP_PAIR(mips_f16) | \
153 MIPS_FP_PAIR(mips_f17) | \
154 MIPS_FP_PAIR(mips_f18) | \
155 MIPS_FP_PAIR(mips_f19))
157 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
158 MIPS_FP_PAIR(mips_f21) | \
159 MIPS_FP_PAIR(mips_f22) | \
160 MIPS_FP_PAIR(mips_f23) | \
161 MIPS_FP_PAIR(mips_f24) | \
162 MIPS_FP_PAIR(mips_f25) | \
163 MIPS_FP_PAIR(mips_f26) | \
164 MIPS_FP_PAIR(mips_f27) | \
165 MIPS_FP_PAIR(mips_f28) | \
166 MIPS_FP_PAIR(mips_f29) | \
167 MIPS_FP_PAIR(mips_f30) | \
168 MIPS_FP_PAIR(mips_f31))
171 #define mips_ftemp mips_f18
173 #define MONO_ARCH_USE_FPSTACK FALSE
174 #define MONO_ARCH_FPSTACK_SIZE 0
176 /* Parameters used by the register allocator */
178 /* On Mips, for regpairs, the lower-numbered reg is most significant
179 * This is true in both big and little endian
182 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
183 #define RET_REG1 mips_v0
184 #define RET_REG2 mips_v1
186 #define RET_REG1 mips_v1
187 #define RET_REG2 mips_v0
190 #define MONO_ARCH_INST_SREG2_MASK(ins) (0)
191 #define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc) == 'V' || (desc) == 'l')
192 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? RET_REG2 : -1))
193 #define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g'))
195 // This define is called to get specific dest register as defined
196 // by md file (letter after "dest"). Overwise return -1
198 #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)))))
200 #define MONO_ARCH_FRAME_ALIGNMENT 8
202 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
203 * reproduceable results for benchmarks */
204 #define MONO_ARCH_CODE_ALIGNMENT 32
206 void mips_patch (guint32 *code, guint32 target);
208 #define MIPS_LMF_MAGIC1 0xa5a5a5a5
209 #define MIPS_LMF_MAGIC2 0xc3c3c3c3
212 gpointer previous_lmf;
217 mips_ireg iregs [MONO_SAVED_GREGS];
218 mips_freg fregs [MONO_SAVED_FREGS];
222 /* we define our own structure and we'll copy the data
223 * from sigcontext/ucontext/mach when we need it.
224 * This also makes us save stack space and time when copying
225 * We might also want to add an additional field to propagate
226 * the original context from the signal handler.
230 mips_ireg sc_regs [MONO_SAVED_GREGS];
231 mips_freg sc_fpregs [MONO_SAVED_FREGS];
234 typedef struct MonoCompileArch {
237 guint local_alloc_offset;
238 guint spillvar_offset;
239 guint spillvar_offset_float;
240 guint tracing_offset;
243 #if SIZEOF_REGISTER == 4
244 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
245 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
246 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
247 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
248 #define MONO_ARCH_EMULATE_FREM 1
249 #define MONO_ARCH_BIGMUL_INTRINS 1
252 #if SIZEOF_REGISTER == 8
253 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
256 #define MIPS_RET_ADDR_OFFSET (-sizeof(gpointer))
257 #define MIPS_FP_ADDR_OFFSET (-8)
258 #define MIPS_STACK_ALIGNMENT 16
259 #define MIPS_STACK_PARAM_OFFSET 16 /* from sp to first parameter */
260 #define MIPS_MINIMAL_STACK_SIZE (4*sizeof(mips_ireg) + 4*sizeof(mips_ireg))
261 #define MIPS_EXTRA_STACK_SIZE 16 /* from last parameter to top of frame */
263 #if _MIPS_SIM == _ABIO32
264 #define MIPS_FIRST_ARG_REG mips_a0
265 #define MIPS_LAST_ARG_REG mips_a3
266 #define MIPS_FIRST_FPARG_REG mips_f12
267 #define MIPS_LAST_FPARG_REG mips_f14
268 #elif _MIPS_SIM == _ABIN32
269 #define MIPS_FIRST_ARG_REG mips_a0
270 #define MIPS_LAST_ARG_REG mips_t3
271 #define MIPS_FIRST_FPARG_REG mips_f12
272 #define MIPS_LAST_FPARG_REG mips_f19
275 //#define MONO_ARCH_HAVE_IMT 1
276 //#define MONO_ARCH_IMT_REG mips_v0 /* XXX */
277 #define MONO_ARCH_COMMON_VTABLE_TRAMPOLINE 1
279 //#define MONO_ARCH_VTABLE_REG mips_v0 /* XXX */
280 #define MONO_ARCH_RGCTX_REG mips_v0 /* XXX */
282 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
283 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
285 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
287 /* XXX - a mystery, but it works */
288 #define MONO_GET_CONTEXT \
289 void *ctx = (void *)(((int)context)+24);
291 /* set the next to 0 once inssel-mips.brg is updated */
292 #define MIPS_PASS_STRUCTS_BY_VALUE 1
293 #define MIPS_SMALL_RET_STRUCT_IN_REG 0
295 #define MONO_ARCH_USE_SIGACTION
296 #define MONO_ARCH_NEED_DIV_CHECK 1
297 #define MONO_ARCH_NO_IOV_CHECK 1
299 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
300 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
302 /* we have the stack pointer, not the base pointer in sigcontext */
303 #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (int)(ip); } while (0);
304 #define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (int)(bp); } while (0);
305 #define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (int)(sp); } while (0);
307 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_pc))
308 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_fp]))
309 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
313 unsigned long at; /* assembler temp */
314 unsigned long v0; /* return values */
316 unsigned long a0; /* 4 - func arguments */
320 unsigned long t0; /* 8 temporaries */
328 unsigned long s0; /* 16 calle saved */
336 unsigned long t8; /* 24 temps */
337 unsigned long t9; /* 25 temp / pic call-through register */
338 unsigned long k0; /* 26 kernel-reserved */
340 unsigned long gp; /* 28 */
341 unsigned long sp; /* stack pointer */
342 unsigned long fp; /* frame pointer */
343 unsigned long ra; /* return address */
344 } MonoMipsStackFrame;
346 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
348 guint32 *code = (guint32 *)(void *)func; \
350 memset ((ctx), 0, sizeof (*(ctx))); \
351 __asm__ volatile("addu %0,$0,$29" : "=r" (sp)); \
352 /* Look for adjustment of sp */ \
353 while ((*code & 0xffff0000) != 0x27bd0000) \
355 imm = (short) (*code & 0xffff); \
356 MONO_CONTEXT_SET_BP ((ctx), sp + (-imm)); \
357 ra = *(guint32 *)(sp + (-imm) + MIPS_RET_ADDR_OFFSET); \
358 MONO_CONTEXT_SET_IP ((ctx),ra); \
359 MONO_CONTEXT_SET_SP ((ctx), MONO_CONTEXT_GET_BP (ctx)); \
362 /* re-attaches with gdb - sometimes causes executable to hang */
363 #undef HAVE_BACKTRACE_SYMBOLS
365 #undef DEBUG_EXCEPTIONS
367 #define MONO_ZERO_REG mips_zero
369 #define MONO_EMIT_NEW_BRANCH_UNREG_LABEL(cfg,op,sr1,label) do { \
371 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
374 inst->inst_i0 = label; \
375 inst->flags = MONO_INST_BRLABEL; \
376 mono_bblock_add_inst ((cfg)->cbb, inst); \
379 #define MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg,op,sr1,sr2,label) do { \
381 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
385 inst->inst_i0 = label; \
386 inst->flags = MONO_INST_BRLABEL; \
387 mono_bblock_add_inst ((cfg)->cbb, inst); \
390 #define MONO_EMIT_NEW_BRANCH_NONZERO_LABEL(cfg,op,sr1,targetbb) do { \
392 MonoInst *target_label; \
393 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
394 target_label->opcode = OP_LABEL; \
395 target_label->next = (targetbb)->code; \
396 target_label->inst_c0 = (targetbb)->native_offset; \
397 (targetbb)->code = target_label; \
398 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
400 (inst)->sreg1 = sr1; \
401 (inst)->sreg2 = sr2; \
402 inst->inst_i0 = target_label; \
403 inst->flags = MONO_INST_BRLABEL; \
404 mono_bblock_add_inst ((cfg)->cbb, inst); \
407 #define MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg,op,sr1,sr2,targetbb) do { \
409 MonoInst *target_label; \
410 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
411 target_label->opcode = OP_LABEL; \
412 target_label->next = (targetbb)->code; \
413 target_label->inst_c0 = (targetbb)->native_offset; \
414 (targetbb)->code = target_label; \
415 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
417 (inst)->sreg1 = sr1; \
418 (inst)->sreg2 = sr2; \
419 inst->inst_i0 = target_label; \
420 inst->flags = MONO_INST_BRLABEL; \
421 mono_bblock_add_inst ((cfg)->cbb, inst); \
424 #ifndef MONO_EMIT_NEW_COMPARE_BRANCH_LABEL
425 #define MONO_EMIT_NEW_COMPARE_BRANCH_LABEL(cfg, cmp_op, sreg1, sreg2, label) \
429 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BEQ, sreg1, sreg2, label); \
432 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, sreg1, sreg2, label); \
435 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
436 MONO_EMIT_NEW_BIALU_IMM (s, OP_IXOR, mips_at, mips_at, 1); \
437 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
440 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
441 MONO_EMIT_NEW_BIALU_IMM (s, OP_IXOR, mips_at, mips_at, 1); \
442 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
445 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
446 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
449 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
450 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
453 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
454 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
457 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
458 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
461 g_assert_not_reached(); \
466 #ifndef MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL
467 #define MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL(cfg, cmp_op, sreg1, imm, label) \
471 cmp_reg = mips_zero; \
475 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
477 MONO_EMIT_NEW_COMPARE_BRANCH_LABEL(cfg, cmp_op, sreg1, cmp_reg, label); \
481 #ifndef MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK
482 #define MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg, cmp_op, sreg1, sreg2, block) \
486 MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BEQ, sreg1, sreg2, block); \
489 MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BNE, sreg1, sreg2, block); \
492 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
493 MONO_EMIT_NEW_BRANCH_BIREG_BLOCK (cfg, OP_MIPS_BNE, mips_at, mips_zero, block); \
496 g_assert_not_reached (); \
501 #ifndef MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK
502 #define MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK(cfg, cmp_op, sreg1, imm, block) \
506 cmp_reg = mips_zero; \
510 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
512 MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg, cmp_op, sreg1, cmp_reg, block); \
516 #define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
518 MONO_INST_NEW ((cfg), (inst), cond); \
519 inst->inst_p1 = (char*)name; \
522 MONO_ADD_INS ((cfg)->cbb, inst); \
525 #ifndef MONO_EMIT_NEW_COMPARE_EXC
526 #define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
527 switch (OP_MIPS_COND_EXC_##cmp_op) { \
528 case OP_MIPS_COND_EXC_EQ: \
529 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
531 case OP_MIPS_COND_EXC_NE_UN: \
532 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
534 case OP_MIPS_COND_EXC_GT: \
535 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
536 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
538 case OP_MIPS_COND_EXC_GT_UN: \
539 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
540 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
542 case OP_MIPS_COND_EXC_LE: \
543 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
544 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
546 case OP_MIPS_COND_EXC_LE_UN: \
547 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
548 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
550 case OP_MIPS_COND_EXC_LT: \
551 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
552 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
554 case OP_MIPS_COND_EXC_LT_UN: \
555 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
556 MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
559 g_warning ("unknown comparison %s\n", #cmp_op); \
560 g_assert_not_reached (); \
565 #ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
566 #define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
569 cmp_reg = mips_zero; \
573 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
575 MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
579 #ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
580 #define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
581 MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
592 extern guint8 *mips_emit_load_const(guint8 *code, int dreg, mgreg_t v);
594 #endif /* __MONO_MINI_MIPS_H__ */