Get rid of the old mono_arch_find_jit_info functions + defines as all platforms suppo...
[mono.git] / mono / mini / mini-mips.h
1 #ifndef __MONO_MINI_MIPS_H__
2 #define __MONO_MINI_MIPS_H__
3
4 #include <glib.h>
5 #include <mono/arch/mips/mips-codegen.h>
6
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"
12 #else
13 /* o64 not supported */
14 /* n64 not supported */
15 #error "MIPS unsupported ABI"
16 #endif
17
18
19 #define MONO_ARCH_CPU_SPEC mips_desc
20
21 #define MONO_MAX_IREGS 32
22 #define MONO_MAX_FREGS 32
23
24 #define MONO_SAVED_GREGS 32
25 #define MONO_SAVED_FREGS 32
26
27
28 #if SIZEOF_REGISTER == 4
29 #define IREG_SIZE       4
30 typedef guint32         mips_ireg;
31 #define FREG_SIZE       4
32 typedef gfloat          mips_freg;
33
34 #elif SIZEOF_REGISTER == 8
35
36 #define IREG_SIZE       8
37 typedef guint64         mips_ireg;
38 #define FREG_SIZE       8
39 typedef gdouble         mips_freg;
40
41 #else
42 #error Unknown REGISTER_SIZE
43 #endif
44
45 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
46 #define MSW_OFFSET      sizeof(mips_ireg)
47 #define LSW_OFFSET      0
48 #else
49 #define MSW_OFFSET      0
50 #define LSW_OFFSET      sizeof(mips_ireg)
51 #endif
52
53 /*
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
58  */
59
60 #define MIPS_V_REGS     ((1 << mips_v0) | \
61                          (1 << mips_v1))
62 #if _MIPS_SIM == _ABIO32
63 #define MIPS_T_REGS     ((1 << mips_t0) | \
64                          (1 << mips_t1) | \
65                          (1 << mips_t2) | \
66                          (1 << mips_t3) | \
67                          (1 << mips_t4) | \
68                          (1 << mips_t5) | \
69                          (1 << mips_t6) | \
70                          (1 << mips_t7))
71 #elif _MIPS_SIM == _ABIN32
72 #define MIPS_T_REGS     ((1 << mips_t0) | \
73                          (1 << mips_t1) | \
74                          (1 << mips_t2) | \
75                          (1 << mips_t3))
76 #endif
77
78
79 #define MIPS_S_REGS     ((1 << mips_s0) | \
80                          (1 << mips_s1) | \
81                          (1 << mips_s2) | \
82                          (1 << mips_s3) | \
83                          (1 << mips_s4) | \
84                          (1 << mips_s5) | \
85                          (1 << mips_s6) | \
86                          (1 << mips_s7) | \
87                          (1 << mips_fp))
88 #if _MIPS_SIM == _ABIO32
89 #define MIPS_A_REGS     ((1 << mips_a0) | \
90                          (1 << mips_a1) | \
91                          (1 << mips_a2) | \
92                          (1 << mips_a3))
93 #elif _MIPS_SIM == _ABIN32
94 #define MIPS_A_REGS     ((1 << mips_a0) | \
95                          (1 << mips_a1) | \
96                          (1 << mips_a2) | \
97                          (1 << mips_a3) | \
98                          (1 << mips_a4) | \
99                          (1 << mips_a5) | \
100                          (1 << mips_a6) | \
101                          (1 << mips_a7))
102 #endif
103
104 #define mips_temp mips_t8
105
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
109
110 #if 0
111 #define MIPS_FP_PAIR(reg)       ((1 << (reg)) | (1 << ((reg)+1)))
112 #else
113 /* Only put the even regs in */
114 #define MIPS_FP_PAIR(reg)       (1 << (reg))
115 #endif
116
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))
128
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))
156
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))
169 #endif
170
171 #define mips_ftemp mips_f18
172
173 #define MONO_ARCH_USE_FPSTACK FALSE
174 #define MONO_ARCH_FPSTACK_SIZE 0
175
176 /* Parameters used by the register allocator */
177
178 /* On Mips, for regpairs, the lower-numbered reg is most significant
179  * This is true in both big and little endian
180  */
181
182 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
183 #define RET_REG1 mips_v0
184 #define RET_REG2 mips_v1
185 #else
186 #define RET_REG1 mips_v1
187 #define RET_REG2 mips_v0
188 #endif
189
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'))
194
195 // This define is called to get specific dest register as defined
196 // by md file (letter after "dest"). Overwise return -1
197
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)))))
199
200 #define MONO_ARCH_FRAME_ALIGNMENT 8
201
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
205
206 void mips_patch (guint32 *code, guint32 target);
207
208 #define MIPS_LMF_MAGIC1 0xa5a5a5a5
209 #define MIPS_LMF_MAGIC2 0xc3c3c3c3
210
211 struct MonoLMF {
212         gpointer        previous_lmf;
213         gpointer        lmf_addr;
214         MonoMethod      *method;
215         mips_ireg       ebp;
216         gpointer        eip;
217         mips_ireg       iregs [MONO_SAVED_GREGS];
218         mips_freg       fregs [MONO_SAVED_FREGS];
219         gulong          magic;
220 };
221
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.
227  */
228 typedef struct {
229         gpointer        sc_pc;
230         mips_ireg       sc_regs [MONO_SAVED_GREGS];
231         mips_freg       sc_fpregs [MONO_SAVED_FREGS];
232 } MonoContext;
233
234 typedef struct MonoCompileArch {
235         guint           iregs_offset;
236         guint           lmf_offset;
237         guint           local_alloc_offset;
238         guint           spillvar_offset;
239         guint           spillvar_offset_float;
240         guint           tracing_offset;
241         guint           long_branch;
242 } MonoCompileArch;
243
244 #if SIZEOF_REGISTER == 4
245 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
246 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
247 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
248 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
249 #define MONO_ARCH_EMULATE_FREM 1
250 #define MONO_ARCH_BIGMUL_INTRINS 1
251 #endif
252
253 #if SIZEOF_REGISTER == 8
254 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
255 #endif
256
257 #define MIPS_RET_ADDR_OFFSET    (-sizeof(gpointer))
258 #define MIPS_FP_ADDR_OFFSET     (-8)
259 #define MIPS_STACK_ALIGNMENT    16
260 #define MIPS_STACK_PARAM_OFFSET 16              /* from sp to first parameter */
261 #define MIPS_MINIMAL_STACK_SIZE (4*sizeof(mips_ireg) + 4*sizeof(mips_ireg))
262 #define MIPS_EXTRA_STACK_SIZE   16              /* from last parameter to top of frame */
263
264 #if _MIPS_SIM == _ABIO32
265 #define MIPS_FIRST_ARG_REG      mips_a0
266 #define MIPS_LAST_ARG_REG       mips_a3
267 #define MIPS_FIRST_FPARG_REG    mips_f12
268 #define MIPS_LAST_FPARG_REG     mips_f14
269 #elif _MIPS_SIM == _ABIN32
270 #define MIPS_FIRST_ARG_REG      mips_a0
271 #define MIPS_LAST_ARG_REG       mips_t3
272 #define MIPS_FIRST_FPARG_REG    mips_f12
273 #define MIPS_LAST_FPARG_REG     mips_f19
274 #endif
275
276 #define MONO_ARCH_HAVE_IMT      1
277 #define MONO_ARCH_IMT_REG       mips_t0
278
279 #define MONO_ARCH_VTABLE_REG    mips_t0
280 #define MONO_ARCH_RGCTX_REG     mips_t0
281
282 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
283 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
284
285 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
286
287 /* XXX - a mystery, but it works */
288 #define MONO_GET_CONTEXT \
289         void *ctx = (void *)(((int)context)+24);
290
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
294
295 #define MONO_ARCH_USE_SIGACTION
296 #define MONO_ARCH_NEED_DIV_CHECK 1
297 #define MONO_ARCH_NO_IOV_CHECK 1
298
299 #define MONO_ARCH_THIS_AS_FIRST_ARG 1
300
301 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
302 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
303
304 /* we have the stack pointer, not the base pointer in sigcontext */
305 #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->sc_pc = (int)(ip); } while (0); 
306 #define MONO_CONTEXT_SET_BP(ctx,bp) do { (ctx)->sc_regs[mips_fp] = (int)(bp); } while (0); 
307 #define MONO_CONTEXT_SET_SP(ctx,sp) do { (ctx)->sc_regs[mips_sp] = (int)(sp); } while (0); 
308
309 #define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->sc_pc))
310 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->sc_regs[mips_fp]))
311 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_regs[mips_sp]))
312
313 typedef struct {
314         unsigned long zero;
315         unsigned long at; /* assembler temp */
316         unsigned long v0; /* return values */
317         unsigned long v1;
318         unsigned long a0; /* 4 - func arguments */
319         unsigned long a1;
320         unsigned long a2;
321         unsigned long a3;
322         unsigned long t0; /* 8 temporaries */
323         unsigned long t1;
324         unsigned long t2;
325         unsigned long t3;
326         unsigned long t4;
327         unsigned long t5;
328         unsigned long t6;
329         unsigned long t7;
330         unsigned long s0; /* 16 calle saved */
331         unsigned long s1;
332         unsigned long s2;
333         unsigned long s3;
334         unsigned long s4;
335         unsigned long s5;
336         unsigned long s6;
337         unsigned long s7;
338         unsigned long t8; /* 24 temps */
339         unsigned long t9; /* 25 temp / pic call-through register */
340         unsigned long k0; /* 26 kernel-reserved */
341         unsigned long k1;
342         unsigned long gp; /* 28 */
343         unsigned long sp; /* stack pointer */
344         unsigned long fp; /* frame pointer */
345         unsigned long ra; /* return address */
346 } MonoMipsStackFrame;
347
348 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do {      \
349                 guint32 sp, ra;                                 \
350                 guint32 *code = (guint32 *)(void *)func;        \
351                 short imm;                                      \
352                 memset ((ctx), 0, sizeof (*(ctx)));             \
353                 __asm__ volatile("addu %0,$0,$29" : "=r" (sp)); \
354                 /* Look for adjustment of sp */                 \
355                 while ((*code & 0xffff0000) != 0x27bd0000)      \
356                         ++code;                                 \
357                 imm = (short) (*code & 0xffff);                 \
358                 MONO_CONTEXT_SET_BP ((ctx), sp + (-imm));       \
359                 ra = *(guint32 *)(sp + (-imm) + MIPS_RET_ADDR_OFFSET);  \
360                 MONO_CONTEXT_SET_IP ((ctx),ra); \
361                 MONO_CONTEXT_SET_SP ((ctx), MONO_CONTEXT_GET_BP (ctx)); \
362         } while (0)
363
364 /* re-attaches with gdb - sometimes causes executable to hang */
365 #undef HAVE_BACKTRACE_SYMBOLS
366
367 #undef DEBUG_EXCEPTIONS
368
369 #define MONO_ZERO_REG           mips_zero
370
371 #define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
372                 MonoInst *inst; \
373                 MONO_INST_NEW ((cfg), (inst), cond); \
374                 inst->inst_p1 = (char*)name; \
375                 inst->sreg1 = sr1; \
376                 inst->sreg2 = sr2; \
377                 MONO_ADD_INS ((cfg)->cbb, inst); \
378         } while (0)
379
380 #ifndef MONO_EMIT_NEW_COMPARE_EXC
381 #define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
382                 switch (OP_MIPS_COND_EXC_##cmp_op) { \
383                 case OP_MIPS_COND_EXC_EQ: \
384                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
385                         break; \
386                 case OP_MIPS_COND_EXC_NE_UN: \
387                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
388                         break; \
389                 case OP_MIPS_COND_EXC_GT: \
390                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
391                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
392                         break; \
393                 case OP_MIPS_COND_EXC_GT_UN: \
394                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
395                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
396                         break; \
397                 case OP_MIPS_COND_EXC_LE: \
398                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
399                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
400                         break; \
401                 case OP_MIPS_COND_EXC_LE_UN: \
402                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
403                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
404                         break; \
405                 case OP_MIPS_COND_EXC_LT: \
406                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
407                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
408                         break; \
409                 case OP_MIPS_COND_EXC_LT_UN: \
410                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
411                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
412                         break; \
413                 default: \
414                         g_warning ("unknown comparison %s\n", #cmp_op); \
415                         g_assert_not_reached (); \
416                 } \
417         } while (0)
418 #endif
419
420 #ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
421 #define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
422                 guint32 cmp_reg; \
423                 if (!(imm)) { \
424                         cmp_reg = mips_zero; \
425                 } \
426                 else { \
427                         cmp_reg = mips_at; \
428                         MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
429                 } \
430                 MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
431         } while (0)
432 #endif
433
434 #ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
435 #define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
436                 MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
437         } while (0)
438 #endif
439
440 typedef struct {
441         gint8 reg;
442         gint8 size;
443         int vtsize;
444         int offset;
445 } MonoMIPSArgInfo;
446
447 extern guint8 *mips_emit_load_const(guint8 *code, int dreg, mgreg_t v);
448
449 #endif /* __MONO_MINI_MIPS_H__ */