1 #ifndef __MONO_MINI_MIPS_H__
2 #define __MONO_MINI_MIPS_H__
4 #include <mono/arch/mips/mips-codegen.h>
7 #define MONO_MAX_IREGS 32
8 #define MONO_MAX_FREGS 32
10 #define MONO_SAVED_GREGS 32
11 #define MONO_SAVED_FREGS 32
14 * at and t0 used internally
15 * v0, v1 aren't here for clarity reasons
16 * a0, a1, a2, a3 are for arguments
17 * Use t9 for indirect calls to match the ABI
20 #define MIPS_V_REGS ((1 << mips_v0) | \
22 #define MIPS_T_REGS ((1 << mips_t0) | \
30 #define MIPS_S_REGS ((1 << mips_s0) | \
39 #define MIPS_A_REGS ((1 << mips_a0) | \
44 #define mips_temp mips_t8
46 #define MONO_ARCH_CALLEE_REGS (MIPS_T_REGS | MIPS_V_REGS)
47 #define MONO_ARCH_CALLEE_SAVED_REGS MIPS_S_REGS
48 #define MIPS_ARG_REGS MIPS_A_REGS
51 #define MIPS_FP_PAIR(reg) ((1 << (reg)) | (1 << ((reg)+1)))
53 /* Only put the even regs in */
54 #define MIPS_FP_PAIR(reg) (1 << (reg))
57 #define MONO_ARCH_CALLEE_FREGS (MIPS_FP_PAIR(mips_f0) | \
58 MIPS_FP_PAIR(mips_f2) | \
59 MIPS_FP_PAIR(mips_f4) | \
60 MIPS_FP_PAIR(mips_f6) | \
61 MIPS_FP_PAIR(mips_f8) | \
62 MIPS_FP_PAIR(mips_f10) | \
63 MIPS_FP_PAIR(mips_f12) | \
64 MIPS_FP_PAIR(mips_f14) | \
65 MIPS_FP_PAIR(mips_f16) | \
66 MIPS_FP_PAIR(mips_f18))
68 #define MONO_ARCH_CALLEE_SAVED_FREGS (MIPS_FP_PAIR(mips_f20) | \
69 MIPS_FP_PAIR(mips_f22) | \
70 MIPS_FP_PAIR(mips_f24) | \
71 MIPS_FP_PAIR(mips_f26) | \
72 MIPS_FP_PAIR(mips_f28) | \
73 MIPS_FP_PAIR(mips_f30))
75 #define mips_ftemp mips_f18
77 #define MONO_ARCH_USE_FPSTACK FALSE
78 #define MONO_ARCH_FPSTACK_SIZE 0
80 /* Parameters used by the register allocator */
81 #define MONO_ARCH_HAS_XP_LOCAL_REGALLOC
83 /* On Mips, for regpairs, the lower-numbered reg is most significant
84 * This is true in both big and little endian
87 #define MONO_ARCH_INST_SREG2_MASK(ins) (0)
88 #define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc) == 'V' || (desc) == 'l')
89 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? ((hreg1) - 1) : -1))
90 #define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g'))
92 // This define is called to get specific dest register as defined
93 // by md file (letter after "dest"). Overwise return -1
95 #define MONO_ARCH_INST_FIXED_REG(desc) (((desc) == '0') ? mips_zero : (((desc) == 'a') ? mips_at : ((((desc) == 'v')) ? mips_v0 : (((desc) == 'V') ? mips_v1 : (((desc) == 'g') ? mips_f0 : -1)))))
97 #define MONO_ARCH_FRAME_ALIGNMENT 8
99 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
100 * reproduceable results for benchmarks */
101 #define MONO_ARCH_CODE_ALIGNMENT 32
103 void mips_patch (guint32 *code, guint32 target);
106 gpointer previous_lmf;
111 gulong iregs [MONO_SAVED_GREGS];
112 gfloat fregs [MONO_SAVED_FREGS];
116 /* we define our own structure and we'll copy the data
117 * from sigcontext/ucontext/mach when we need it.
118 * This also makes us save stack space and time when copying
119 * We might also want to add an additional field to propagate
120 * the original context from the signal handler.
124 gulong sc_regs [MONO_SAVED_GREGS];
125 gfloat sc_fpregs [MONO_SAVED_FREGS];
128 typedef struct MonoCompileArch {
131 guint spillvar_offset;
132 guint spillvar_offset_float;
135 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
136 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
137 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
138 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
139 #define MONO_ARCH_EMULATE_FREM 1
140 #define MONO_ARCH_BIGMUL_INTRINS 1
142 #define MIPS_RET_ADDR_OFFSET (-4)
143 #define MIPS_FP_ADDR_OFFSET (-8)
144 #define MIPS_STACK_ALIGNMENT 16
145 #define MIPS_STACK_PARAM_OFFSET 16 /* from sp to first parameter */
146 #define MIPS_MINIMAL_STACK_SIZE (4*4 + 4*4)
147 #define MIPS_EXTRA_STACK_SIZE 16 /* from last parameter to top of frame */
148 #define MIPS_FIRST_ARG_REG mips_a0
149 #define MIPS_LAST_ARG_REG mips_a3
150 #define MIPS_FIRST_FPARG_REG mips_f12
151 #define MIPS_LAST_FPARG_REG mips_f14
155 /* XXX - a mystery, but it works */
156 #define MONO_GET_CONTEXT \
157 void *ctx = (void *)(((int)context)+24);
159 /* set the next to 0 once inssel-mips.brg is updated */
160 #define MIPS_PASS_STRUCTS_BY_VALUE 1
161 #define MIPS_SMALL_RET_STRUCT_IN_REG 0
163 #define MONO_ARCH_USE_SIGACTION
164 #define MONO_ARCH_NEED_DIV_CHECK 1
166 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
167 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
169 /* we have the stack pointer, not the base pointer in sigcontext */
170 #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (int)ip; } while (0);
171 #define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_sp] = (int)bp; } while (0);
172 #define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (int)sp; } while (0);
174 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_pc))
175 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
176 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
180 unsigned long at; /* assembler temp */
181 unsigned long v0; /* return values */
183 unsigned long a0; /* 4 - func arguments */
187 unsigned long t0; /* 8 temporaries */
195 unsigned long s0; /* 16 calle saved */
203 unsigned long t8; /* 24 temps */
204 unsigned long t9; /* 25 temp / pic call-through register */
205 unsigned long k0; /* 26 kernel-reserved */
207 unsigned long gp; /* 28 */
208 unsigned long sp; /* stack pointer */
209 unsigned long fp; /* frame pointer */
210 unsigned long ra; /* return address */
211 } MonoMipsStackFrame;
213 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
215 guint32 *code = (guint32 *)(void *)func; \
217 memset ((ctx), 0, sizeof (*(ctx))); \
218 __asm__ volatile("addu %0,$0,$29" : "=r" (sp)); \
219 /* Look for adjustment of sp */ \
220 while ((*code & 0xffff0000) != 0x27bd0000) \
222 imm = (short) (*code & 0xffff); \
223 MONO_CONTEXT_SET_BP ((ctx), sp + (-imm)); \
224 ra = *(guint32 *)(sp + (-imm) + MIPS_RET_ADDR_OFFSET); \
225 MONO_CONTEXT_SET_IP ((ctx),ra); \
229 #define mono_find_jit_info mono_arch_find_jit_info
230 #define CUSTOM_STACK_WALK
233 /* re-attaches with gdb - sometimes causes executable to hang */
234 #undef HAVE_BACKTRACE_SYMBOLS
236 #undef CUSTOM_EXCEPTION_HANDLING
238 #define MONO_ZERO_REG mips_zero
240 #define MONO_EMIT_NEW_BRANCH_UNREG_LABEL(cfg,op,sr1,label) do { \
242 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
245 inst->inst_i0 = label; \
246 inst->flags = MONO_INST_BRLABEL; \
247 mono_bblock_add_inst ((cfg)->cbb, inst); \
250 #define MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg,op,sr1,sr2,label) do { \
252 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
256 inst->inst_i0 = label; \
257 inst->flags = MONO_INST_BRLABEL; \
258 mono_bblock_add_inst ((cfg)->cbb, inst); \
261 #define MONO_EMIT_NEW_BRANCH_NONZERO_LABEL(cfg,op,sr1,targetbb) do { \
263 MonoInst *target_label; \
264 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
265 target_label->opcode = OP_LABEL; \
266 target_label->next = (targetbb)->code; \
267 target_label->inst_c0 = (targetbb)->native_offset; \
268 (targetbb)->code = target_label; \
269 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
271 (inst)->sreg1 = sr1; \
272 (inst)->sreg2 = sr2; \
273 inst->inst_i0 = target_label; \
274 inst->flags = MONO_INST_BRLABEL; \
275 mono_bblock_add_inst ((cfg)->cbb, inst); \
278 #define MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg,op,sr1,sr2,targetbb) do { \
280 MonoInst *target_label; \
281 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
282 target_label->opcode = OP_LABEL; \
283 target_label->next = (targetbb)->code; \
284 target_label->inst_c0 = (targetbb)->native_offset; \
285 (targetbb)->code = target_label; \
286 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
288 (inst)->sreg1 = sr1; \
289 (inst)->sreg2 = sr2; \
290 inst->inst_i0 = target_label; \
291 inst->flags = MONO_INST_BRLABEL; \
292 mono_bblock_add_inst ((cfg)->cbb, inst); \
295 #ifndef MONO_EMIT_NEW_COMPARE_BRANCH_LABEL
296 #define MONO_EMIT_NEW_COMPARE_BRANCH_LABEL(cfg, cmp_op, sreg1, sreg2, label) \
300 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BEQ, sreg1, sreg2, label); \
303 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, sreg1, sreg2, label); \
306 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
307 MONO_EMIT_NEW_BIALU_IMM (s, OP_MIPS_XORI, mips_at, mips_at, 1); \
308 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
311 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
312 MONO_EMIT_NEW_BIALU_IMM (s, OP_MIPS_XORI, mips_at, mips_at, 1); \
313 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
316 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
317 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
320 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
321 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
324 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
325 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
328 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
329 MONO_EMIT_NEW_BRANCH_BIREG_LABEL(cfg, OP_MIPS_BNE, mips_at, mips_zero, label); \
332 g_assert_not_reached(); \
337 #ifndef MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL
338 #define MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL(cfg, cmp_op, sreg1, imm, label) \
342 cmp_reg = mips_zero; \
346 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
348 MONO_EMIT_NEW_COMPARE_BRANCH_LABEL(cfg, cmp_op, sreg1, cmp_reg, label); \
352 #ifndef MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK
353 #define MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg, cmp_op, sreg1, sreg2, block) \
357 MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BEQ, sreg1, sreg2, block); \
360 MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BNE, sreg1, sreg2, block); \
363 MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
364 MONO_EMIT_NEW_BRANCH_BIREG_BLOCK(cfg, OP_MIPS_BNE, mips_at, mips_zero, block); \
367 g_assert_not_reached(); \
372 #ifndef MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK
373 #define MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK(cfg, cmp_op, sreg1, imm, block) \
377 cmp_reg = mips_zero; \
381 MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
383 MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(cfg, cmp_op, sreg1, cmp_reg, block); \
394 #endif /* __MONO_MINI_MIPS_H__ */