Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / mini-mips.h
1 /**
2  * \file
3  */
4
5 #ifndef __MONO_MINI_MIPS_H__
6 #define __MONO_MINI_MIPS_H__
7
8 #include <glib.h>
9 #include <mono/arch/mips/mips-codegen.h>
10 #include <mono/utils/mono-context.h>
11
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
22
23
24 #define MONO_ARCH_CPU_SPEC mono_mips_desc
25
26 #define MONO_MAX_IREGS 32
27 #define MONO_MAX_FREGS 32
28
29 #define MONO_SAVED_GREGS 32
30 #define MONO_SAVED_FREGS 32
31
32
33 #if SIZEOF_REGISTER == 4
34 #define IREG_SIZE       4
35 #define FREG_SIZE       4
36 typedef gfloat          mips_freg;
37
38 #elif SIZEOF_REGISTER == 8
39
40 #define IREG_SIZE       8
41 #define FREG_SIZE       8
42 typedef gdouble         mips_freg;
43
44 #else
45 #error Unknown REGISTER_SIZE
46 #endif
47
48 /*
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
53  */
54
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
72
73
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
98
99 #define mips_temp mips_t8
100
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
104
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
111
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))
123
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))
151
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
165
166 #define mips_ftemp mips_f18
167
168 #define MONO_ARCH_USE_FPSTACK FALSE
169 #define MONO_ARCH_FPSTACK_SIZE 0
170
171 /* Parameters used by the register allocator */
172
173 /* On Mips, for regpairs, the lower-numbered reg is most significant
174  * This is true in both big and little endian
175  */
176
177 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
178 #define RET_REG1 mips_v0
179 #define RET_REG2 mips_v1
180 #else
181 #define RET_REG1 mips_v1
182 #define RET_REG2 mips_v0
183 #endif
184
185 #define MONO_ARCH_INST_SREG2_MASK(ins)          (0)
186 #define MONO_ARCH_INST_IS_REGPAIR(desc)         ((desc) == 'V' || (desc) == 'l')
187 #define MONO_ARCH_INST_REGPAIR_REG2(desc,hreg1) (((desc) == 'l') ? ((hreg1) + 1) : (((desc) == 'V') ? RET_REG2 : -1))
188 #define MONO_ARCH_INST_IS_FLOAT(desc)           ((desc == 'f') || (desc == 'g'))
189
190 // This define is called to get specific dest register as defined
191 // by md file (letter after "dest"). Overwise return -1
192
193 #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
195 #define MONO_ARCH_FRAME_ALIGNMENT 8
196
197 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get 
198  * reproduceable results for benchmarks */
199 #define MONO_ARCH_CODE_ALIGNMENT 32
200
201 void mips_patch (guint32 *code, guint32 target);
202
203 #define MIPS_LMF_MAGIC1 0xa5a5a5a5
204 #define MIPS_LMF_MAGIC2 0xc3c3c3c3
205
206 /* Registers saved in lmf->iregs */
207 #define MIPS_LMF_IREGMASK (0xffffffff & ~((1 << mips_zero) | (1 << mips_at) | MONO_ARCH_CALLEE_REGS))
208
209 struct MonoLMF {
210         gpointer        previous_lmf;
211         gpointer        lmf_addr;
212         MonoMethod      *method;
213         gpointer        eip;
214         mgreg_t     iregs [MONO_SAVED_GREGS];
215         mips_freg       fregs [MONO_SAVED_FREGS];
216         gulong          magic;
217 };
218
219 typedef struct MonoCompileArch {
220         gpointer    cinfo;
221         guint           iregs_offset;
222         guint           lmf_offset;
223         guint           local_alloc_offset;
224         guint           spillvar_offset;
225         guint           spillvar_offset_float;
226         guint           tracing_offset;
227         guint           long_branch;
228         gboolean    omit_fp;
229         gboolean    omit_fp_computed;
230 } MonoCompileArch;
231
232 #if SIZEOF_REGISTER == 4
233 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
234 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
235 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
236 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
237 #define MONO_ARCH_EMULATE_FREM 1
238 #endif
239
240 /*
241  * mips backend misses some instructions that enable emitting of optimal
242  * code on other targets and, additionally, the register allocator gets
243  * confused by this optimization, failing to allocate all hw regs.
244  */
245 #if SIZEOF_REGISTER == 4
246 #define MONO_ARCH_NO_DIV_WITH_MUL
247 #endif
248
249 #if SIZEOF_REGISTER == 8
250 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
251 #endif
252
253 #define MIPS_RET_ADDR_OFFSET    (-sizeof(gpointer))
254 #define MIPS_FP_ADDR_OFFSET     (-8)
255 #define MIPS_STACK_ALIGNMENT    16
256 #define MIPS_STACK_PARAM_OFFSET 16              /* from sp to first parameter */
257 #define MIPS_MINIMAL_STACK_SIZE (4*sizeof(mgreg_t) + 4*sizeof(mgreg_t))
258 #define MIPS_EXTRA_STACK_SIZE   16              /* from last parameter to top of frame */
259
260 #if _MIPS_SIM == _ABIO32
261 #define MIPS_FIRST_ARG_REG      mips_a0
262 #define MIPS_LAST_ARG_REG       mips_a3
263 #define MIPS_FIRST_FPARG_REG    mips_f12
264 #define MIPS_LAST_FPARG_REG     mips_f14
265 #elif _MIPS_SIM == _ABIN32
266 #define MIPS_FIRST_ARG_REG      mips_a0
267 #define MIPS_LAST_ARG_REG       mips_t3
268 #define MIPS_FIRST_FPARG_REG    mips_f12
269 #define MIPS_LAST_FPARG_REG     mips_f19
270 #endif
271
272 #define MONO_ARCH_IMT_REG       mips_t0
273
274 #define MONO_ARCH_VTABLE_REG    mips_a0
275 #define MONO_ARCH_RGCTX_REG     MONO_ARCH_IMT_REG
276
277 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS 1
278 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS 1
279
280 #define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE 1
281 #define MONO_ARCH_SOFT_DEBUG_SUPPORTED 1
282 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX 1
283 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX 1
284 #define MONO_ARCH_GSHARED_SUPPORTED 1
285 #define MONO_ARCH_HAVE_INIT_LMF_EXT 1
286
287 /* set the next to 0 once inssel-mips.brg is updated */
288 #define MIPS_PASS_STRUCTS_BY_VALUE 1
289
290 #define MONO_ARCH_USE_SIGACTION
291 #define MONO_ARCH_NEED_DIV_CHECK 1
292 #define MONO_ARCH_NO_IOV_CHECK 1
293
294 #define MIPS_NUM_REG_ARGS (MIPS_LAST_ARG_REG-MIPS_FIRST_ARG_REG+1)
295 #define MIPS_NUM_REG_FPARGS (MIPS_LAST_FPARG_REG-MIPS_FIRST_FPARG_REG+1)
296
297 typedef struct {
298         unsigned long zero;
299         unsigned long at; /* assembler temp */
300         unsigned long v0; /* return values */
301         unsigned long v1;
302         unsigned long a0; /* 4 - func arguments */
303         unsigned long a1;
304         unsigned long a2;
305         unsigned long a3;
306         unsigned long t0; /* 8 temporaries */
307         unsigned long t1;
308         unsigned long t2;
309         unsigned long t3;
310         unsigned long t4;
311         unsigned long t5;
312         unsigned long t6;
313         unsigned long t7;
314         unsigned long s0; /* 16 calle saved */
315         unsigned long s1;
316         unsigned long s2;
317         unsigned long s3;
318         unsigned long s4;
319         unsigned long s5;
320         unsigned long s6;
321         unsigned long s7;
322         unsigned long t8; /* 24 temps */
323         unsigned long t9; /* 25 temp / pic call-through register */
324         unsigned long k0; /* 26 kernel-reserved */
325         unsigned long k1;
326         unsigned long gp; /* 28 */
327         unsigned long sp; /* stack pointer */
328         unsigned long fp; /* frame pointer */
329         unsigned long ra; /* return address */
330 } MonoMipsStackFrame;
331
332 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do {      \
333         MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0));                       \
334         MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0));                       \
335         MONO_CONTEXT_SET_IP ((ctx), (func));                                                            \
336         } while (0)
337
338 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
339
340 /* re-attaches with gdb - sometimes causes executable to hang */
341 #undef HAVE_BACKTRACE_SYMBOLS
342
343 #undef DEBUG_EXCEPTIONS
344
345 #define MONO_EMIT_NEW_MIPS_COND_EXC(cfg,cond,sr1,sr2,name) do { \
346                 MonoInst *inst; \
347                 MONO_INST_NEW ((cfg), (inst), cond); \
348                 inst->inst_p1 = (char*)name; \
349                 inst->sreg1 = sr1; \
350                 inst->sreg2 = sr2; \
351                 MONO_ADD_INS ((cfg)->cbb, inst); \
352         } while (0)
353
354 #ifndef MONO_EMIT_NEW_COMPARE_EXC
355 #define MONO_EMIT_NEW_COMPARE_EXC(cfg, cmp_op, sreg1, sreg2, exc) do { \
356                 switch (OP_MIPS_COND_EXC_##cmp_op) { \
357                 case OP_MIPS_COND_EXC_EQ: \
358                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, sreg1, sreg2, exc); \
359                         break; \
360                 case OP_MIPS_COND_EXC_NE_UN: \
361                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, sreg1, sreg2, exc); \
362                         break; \
363                 case OP_MIPS_COND_EXC_GT: \
364                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
365                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
366                         break; \
367                 case OP_MIPS_COND_EXC_GT_UN: \
368                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
369                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
370                         break; \
371                 case OP_MIPS_COND_EXC_LE: \
372                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg2, sreg1); \
373                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
374                         break; \
375                 case OP_MIPS_COND_EXC_LE_UN: \
376                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg2, sreg1); \
377                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_EQ, mips_at, mips_zero, exc); \
378                         break; \
379                 case OP_MIPS_COND_EXC_LT: \
380                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLT, mips_at, sreg1, sreg2); \
381                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
382                         break; \
383                 case OP_MIPS_COND_EXC_LT_UN: \
384                         MONO_EMIT_NEW_BIALU (cfg, OP_MIPS_SLTU, mips_at, sreg1, sreg2); \
385                         MONO_EMIT_NEW_MIPS_COND_EXC (cfg, OP_MIPS_COND_EXC_NE_UN, mips_at, mips_zero, exc); \
386                         break; \
387                 default: \
388                         g_warning ("unknown comparison %s\n", #cmp_op); \
389                         g_assert_not_reached (); \
390                 } \
391         } while (0)
392 #endif
393
394 #ifndef MONO_EMIT_NEW_COMPARE_IMM_EXC
395 #define MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
396                 guint32 cmp_reg; \
397                 if (!(imm)) { \
398                         cmp_reg = mips_zero; \
399                 } \
400                 else { \
401                         cmp_reg = mips_at; \
402                         MONO_EMIT_NEW_ICONST (cfg, cmp_reg, (imm)); \
403                 } \
404                 MONO_EMIT_NEW_COMPARE_EXC (cfg, cmp_op, sreg1, cmp_reg, exc); \
405         } while (0)
406 #endif
407
408 #ifndef MONO_EMIT_NEW_ICOMPARE_IMM_EXC
409 #define MONO_EMIT_NEW_ICOMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc) do { \
410                 MONO_EMIT_NEW_COMPARE_IMM_EXC(cfg, cmp_op, sreg1, imm, exc); \
411         } while (0)
412 #endif
413
414 typedef struct {
415         gint8 reg;
416         gint8 size;
417         int vtsize;
418         int offset;
419 } MonoMIPSArgInfo;
420
421 extern guint8 *mips_emit_load_const(guint8 *code, int dreg, mgreg_t v);
422
423 #endif /* __MONO_MINI_MIPS_H__ */