- Fix atomic ops on s390
[mono.git] / mono / mini / mini-s390.h
blob457ec78c0a3298a4ec9fb84aeb33279a6efbf9b5
1 #ifndef __MONO_MINI_S390_H__
2 #define __MONO_MINI_S390_H__
4 #include <mono/arch/s390/s390-codegen.h>
5 #include <signal.h>
7 #define MONO_MAX_IREGS 16
8 #define MONO_MAX_FREGS 16
10 #define MONO_ARCH_FRAME_ALIGNMENT 8
12 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
13 MonoInst *inst; \
14 int tmpr = 0; \
15 int sReg, dReg; \
17 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
18 if (size > 256) { \
19 tmpr = mono_regstate_next_int (cfg->rs); \
20 MONO_EMIT_NEW_ICONST(cfg,tmpr,size); \
21 inst->dreg = dest; \
22 inst->inst_offset = offset; \
23 inst->sreg1 = src; \
24 inst->inst_imm = imm; \
25 inst->sreg2 = tmpr; \
26 } else { \
27 if (s390_is_uimm12(offset)) { \
28 inst->dreg = dest; \
29 inst->inst_offset = offset; \
30 } else { \
31 dReg = mono_regstate_next_int (cfg->rs); \
32 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
33 dReg, dest, offset); \
34 inst->dreg = dReg; \
35 inst->inst_offset = 0; \
36 } \
37 if (s390_is_uimm12(imm)) { \
38 inst->sreg1 = src; \
39 inst->inst_imm = imm; \
40 } else { \
41 sReg = mono_regstate_next_int (cfg->rs); \
42 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
43 sReg, src, imm); \
44 inst->sreg1 = sReg; \
45 inst->inst_imm = 0; \
46 } \
47 } \
48 inst->opcode = OP_S390_MOVE; \
49 inst->unused = size; \
50 mono_bblock_add_inst (cfg->cbb, inst); \
51 } while (0)
53 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
54 switch (size) { \
55 case 1: \
56 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
57 dr, sr, so); \
58 break; \
59 case 2: \
60 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
61 dr, sr, so); \
62 break; \
63 case 4: \
64 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOAD_MEMBASE, \
65 dr, sr, so); \
66 break; \
67 case 8: \
68 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOAD_MEMBASE, \
69 dr, sr, so); \
70 dr++; so += sizeof(guint32); \
71 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOAD_MEMBASE, \
72 dr, sr, so); \
73 break; \
74 } \
75 } while (0)
77 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
78 int tmpr; \
79 switch (size) { \
80 case 1: \
81 tmpr = mono_regstate_next_int (cfg->rs); \
82 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
83 tmpr, sr, so); \
84 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
85 tmpr, dr, dx); \
86 break; \
87 case 2: \
88 tmpr = mono_regstate_next_int (cfg->rs); \
89 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
90 tmpr, sr, so); \
91 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
92 tmpr, dr, dx); \
93 break; \
94 case 4: \
95 case 8: \
96 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
97 break; \
98 } \
99 } while (0)
101 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get
102 * reproduceable results for benchmarks */
103 #define MONO_ARCH_CODE_ALIGNMENT 32
105 struct MonoLMF {
106 gpointer previous_lmf;
107 gpointer lmf_addr;
108 MonoMethod *method;
109 gulong ebp;
110 gulong eip;
111 gulong gregs[16];
112 gdouble fregs[16];
115 typedef struct ucontext MonoContext;
117 typedef struct MonoCompileArch {
118 } MonoCompileArch;
120 typedef struct
122 void *prev;
123 void *unused[5];
124 void *regs[8];
125 void *return_address;
126 } MonoS390StackFrame;
128 #define MONO_ARCH_EMULATE_FCONV_TO_I8 1
129 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1
130 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1
131 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
132 #define MONO_ARCH_EMULATE_LMUL 1
133 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW 1
134 #define MONO_ARCH_NEED_DIV_CHECK 1
135 #define MONO_ARCH_HAVE_OUT_OF_LINE_BBLOCKS 1
136 // #define MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION 1
138 #define MONO_ARCH_USE_SIGACTION 1
139 // #define CUSTOM_STACK_WALK 1
140 // #define CUSTOM_EXCEPTION_HANDLING 1
141 #define mono_find_jit_info mono_arch_find_jit_info
143 #define S390_STACK_ALIGNMENT 8
144 #define S390_FIRST_ARG_REG s390_r2
145 #define S390_LAST_ARG_REG s390_r6
146 #define S390_FIRST_FPARG_REG s390_f0
147 #define S390_LAST_FPARG_REG s390_f2
148 #define S390_PASS_STRUCTS_BY_VALUE 1
149 #define S390_SMALL_RET_STRUCT_IN_REG 1
151 #define S390_NUM_REG_ARGS (S390_LAST_ARG_REG-S390_FIRST_ARG_REG+1)
152 #define S390_NUM_REG_FPARGS (S390_LAST_FPARG_REG-S390_FIRST_FPARG_REG)
154 #define S390_OFFSET(b, t) (guchar *) ((gint32) (b) - (gint32) (t))
155 #define S390_RELATIVE(b, t) (guchar *) ((((gint32) (b) - (gint32) (t))) / 2)
157 #define CODEPTR(c, o) (o) = (short *) ((guint32) c - 2)
158 #define PTRSLOT(c, o) *(o) = (short) ((guint32) c - (guint32) (o) + 2)/2
160 #define S390_CC_EQ 8
161 #define S390_ALIGN(v, a) (((a) > 0 ? (((v) + ((a) - 1)) & ~((a) - 1)) : (v)))
163 #define MONO_CONTEXT_SET_IP(ctx,ip) \
164 do { \
165 (ctx)->uc_mcontext.gregs[14] = (unsigned long)ip; \
166 (ctx)->uc_mcontext.psw.addr = (unsigned long)ip; \
167 } while (0);
169 #define MONO_CONTEXT_SET_SP(ctx,bp) MONO_CONTEXT_SET_BP((ctx),(bp))
170 #define MONO_CONTEXT_SET_BP(ctx,bp) \
171 do { \
172 (ctx)->uc_mcontext.gregs[15] = (unsigned long)bp; \
173 (ctx)->uc_stack.ss_sp = (unsigned long)bp; \
174 } while (0);
176 #define MONO_CONTEXT_GET_IP(ctx) context_get_ip ((ctx))
177 #define MONO_CONTEXT_GET_BP(ctx) MONO_CONTEXT_GET_SP((ctx))
178 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->uc_mcontext.gregs[15]))
180 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx,func) do { \
181 MonoS390StackFrame *sframe; \
182 __asm__ volatile("l %0,0(15)" : "=r" (sframe)); \
183 MONO_CONTEXT_SET_BP ((ctx), sframe->prev); \
184 sframe = (MonoS390StackFrame*)sframe->prev; \
185 MONO_CONTEXT_SET_IP ((ctx), sframe->return_address); \
186 } while (0)
188 /*------------------------------------------------------------------*/
189 /* */
190 /* Name - context_get_ip */
191 /* */
192 /* Function - Extract the current instruction address from the */
193 /* context. */
194 /* */
195 /*------------------------------------------------------------------*/
197 static inline gpointer
198 context_get_ip (MonoContext *ctx)
200 gpointer ip;
202 ip = (gpointer) ((gint32) (ctx->uc_mcontext.psw.addr) & 0x7fffffff);
203 return ip;
206 /*========================= End of Function ========================*/
208 /*------------------------------------------------------------------*/
209 /* */
210 /* Name - s390_patch */
211 /* */
212 /* Function - Patch the code with a given value. */
213 /* */
214 /*------------------------------------------------------------------*/
216 static void inline
217 s390_patch (guchar *code, gint32 target)
219 gint32 *offset = (gint32 *) code;
221 if (target != 00) {
222 *offset = target;
226 /*========================= End of Function ========================*/
228 /*------------------------------------------------------------------*/
229 /* */
230 /* Name - restoreLMF */
231 /* */
232 /* Function - Restore the LMF state prior to exiting a method. */
233 /* */
234 /*------------------------------------------------------------------*/
236 #define restoreLMF(code, frame_reg, stack_usage) do \
238 int lmfOffset = 0; \
240 s390_lr (code, s390_r13, frame_reg); \
242 lmfOffset = stack_usage - sizeof(MonoLMF); \
244 /*-------------------------------------------------*/ \
245 /* r13 = my lmf */ \
246 /*-------------------------------------------------*/ \
247 s390_ahi (code, s390_r13, lmfOffset); \
249 /*-------------------------------------------------*/ \
250 /* r6 = &jit_tls->lmf */ \
251 /*-------------------------------------------------*/ \
252 s390_l (code, s390_r6, 0, s390_r13, \
253 G_STRUCT_OFFSET(MonoLMF, lmf_addr)); \
255 /*-------------------------------------------------*/ \
256 /* r0 = lmf.previous_lmf */ \
257 /*-------------------------------------------------*/ \
258 s390_l (code, s390_r0, 0, s390_r13, \
259 G_STRUCT_OFFSET(MonoLMF, previous_lmf)); \
261 /*-------------------------------------------------*/ \
262 /* jit_tls->lmf = previous_lmf */ \
263 /*-------------------------------------------------*/ \
264 s390_l (code, s390_r13, 0, s390_r6, 0); \
265 s390_st (code, s390_r0, 0, s390_r6, 0); \
266 } while (0)
268 /*========================= End of Function ========================*/
270 #endif /* __MONO_MINI_S390_H__ */