[build] Skips RemoteExecuted bases tests on monodroid
[mono-project.git] / mono / mini / mini-s390x.c
blob5f63931ffcb6fbd84e66d229e2e743d60100ee71
1 /**
2 * \file
3 * Function - S/390 backend for the Mono code generator.
5 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
7 * Date - January, 2004
9 * Derivation - From mini-x86 & mini-ppc by -
10 * Paolo Molaro (lupus@ximian.com)
11 * Dietmar Maurer (dietmar@ximian.com)
15 /*------------------------------------------------------------------*/
16 /* D e f i n e s */
17 /*------------------------------------------------------------------*/
19 #define MAX_ARCH_DELEGATE_PARAMS 7
21 #define EMIT_COND_BRANCH(ins,cond) \
22 { \
23 if (ins->inst_true_bb->native_offset) { \
24 int displace; \
25 displace = ((cfg->native_code + \
26 ins->inst_true_bb->native_offset) - code) / 2; \
27 if (s390_is_imm16(displace)) { \
28 s390_brc (code, cond, displace); \
29 } else { \
30 s390_jcl (code, cond, displace); \
31 } \
32 } else { \
33 mono_add_patch_info (cfg, code - cfg->native_code, \
34 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
35 s390_jcl (code, cond, 0); \
36 } \
39 #define EMIT_UNCOND_BRANCH(ins) \
40 { \
41 if (ins->inst_target_bb->native_offset) { \
42 int displace; \
43 displace = ((cfg->native_code + \
44 ins->inst_target_bb->native_offset) - code) / 2; \
45 if (s390_is_imm16(displace)) { \
46 s390_brc (code, S390_CC_UN, displace); \
47 } else { \
48 s390_jcl (code, S390_CC_UN, displace); \
49 } \
50 } else { \
51 mono_add_patch_info (cfg, code - cfg->native_code, \
52 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
53 s390_jcl (code, S390_CC_UN, 0); \
54 } \
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
58 do { \
59 mono_add_patch_info (cfg, code - cfg->native_code, \
60 MONO_PATCH_INFO_EXC, exc_name); \
61 s390_jcl (code, cond, 0); \
62 } while (0);
64 #define EMIT_COMP_AND_BRANCH(ins, cab, cmp) \
65 { \
66 if (ins->inst_true_bb->native_offset) { \
67 int displace; \
68 displace = ((cfg->native_code + \
69 ins->inst_true_bb->native_offset) - code) / 2; \
70 if (s390_is_imm16(displace)) { \
71 s390_##cab (code, ins->sreg1, ins->sreg2, \
72 ins->sreg3, displace); \
73 } else { \
74 s390_##cmp (code, ins->sreg1, ins->sreg2); \
75 displace = ((cfg->native_code + \
76 ins->inst_true_bb->native_offset) - code) / 2; \
77 s390_jcl (code, ins->sreg3, displace); \
78 } \
79 } else { \
80 s390_##cmp (code, ins->sreg1, ins->sreg2); \
81 mono_add_patch_info (cfg, code - cfg->native_code, \
82 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
83 s390_jcl (code, ins->sreg3, 0); \
84 } \
87 #define EMIT_COMP_AND_BRANCH_IMM(ins, cab, cmp, lat, logical) \
88 { \
89 if (ins->inst_true_bb->native_offset) { \
90 int displace; \
91 if ((ins->backend.data == 0) && (!logical)) { \
92 s390_##lat (code, ins->sreg1, ins->sreg1); \
93 displace = ((cfg->native_code + \
94 ins->inst_true_bb->native_offset) - code) / 2; \
95 if (s390_is_imm16(displace)) { \
96 s390_brc (code, ins->sreg3, displace); \
97 } else { \
98 s390_jcl (code, ins->sreg3, displace); \
99 } \
100 } else { \
101 S390_SET (code, s390_r0, ins->backend.data); \
102 displace = ((cfg->native_code + \
103 ins->inst_true_bb->native_offset) - code) / 2; \
104 if (s390_is_imm16(displace)) { \
105 s390_##cab (code, ins->sreg1, s390_r0, \
106 ins->sreg3, displace); \
107 } else { \
108 s390_##cmp (code, ins->sreg1, s390_r0); \
109 displace = ((cfg->native_code + \
110 ins->inst_true_bb->native_offset) - code) / 2; \
111 s390_jcl (code, ins->sreg3, displace); \
114 } else { \
115 if ((ins->backend.data == 0) && (!logical)) { \
116 s390_##lat (code, ins->sreg1, ins->sreg1); \
117 } else { \
118 S390_SET (code, s390_r0, ins->backend.data); \
119 s390_##cmp (code, ins->sreg1, s390_r0); \
121 mono_add_patch_info (cfg, code - cfg->native_code, \
122 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
123 s390_jcl (code, ins->sreg3, 0); \
127 #define CHECK_SRCDST_COM \
128 if (ins->dreg == ins->sreg2) { \
129 src2 = ins->sreg1; \
130 } else { \
131 src2 = ins->sreg2; \
132 if (ins->dreg != ins->sreg1) { \
133 s390_lgr (code, ins->dreg, ins->sreg1); \
137 #define CHECK_SRCDST_NCOM \
138 if (ins->dreg == ins->sreg2) { \
139 src2 = s390_r13; \
140 s390_lgr (code, s390_r13, ins->sreg2); \
141 } else { \
142 src2 = ins->sreg2; \
144 if (ins->dreg != ins->sreg1) { \
145 s390_lgr (code, ins->dreg, ins->sreg1); \
148 #define CHECK_SRCDST_COM_I \
149 if (ins->dreg == ins->sreg2) { \
150 src2 = ins->sreg1; \
151 } else { \
152 src2 = ins->sreg2; \
153 if (ins->dreg != ins->sreg1) { \
154 s390_lgfr (code, ins->dreg, ins->sreg1); \
158 #define CHECK_SRCDST_NCOM_I \
159 if (ins->dreg == ins->sreg2) { \
160 src2 = s390_r13; \
161 s390_lgfr (code, s390_r13, ins->sreg2); \
162 } else { \
163 src2 = ins->sreg2; \
165 if (ins->dreg != ins->sreg1) { \
166 s390_lgfr (code, ins->dreg, ins->sreg1); \
169 #define CHECK_SRCDST_COM_F \
170 if (ins->dreg == ins->sreg2) { \
171 src2 = ins->sreg1; \
172 } else { \
173 src2 = ins->sreg2; \
174 if (ins->dreg != ins->sreg1) { \
175 s390_ldr (code, ins->dreg, ins->sreg1); \
179 #define CHECK_SRCDST_NCOM_F \
180 if (ins->dreg == ins->sreg2) { \
181 src2 = s390_f15; \
182 s390_ldr (code, s390_r13, ins->sreg2); \
183 } else { \
184 src2 = ins->sreg2; \
186 if (ins->dreg != ins->sreg1) { \
187 s390_ldr (code, ins->dreg, ins->sreg1); \
190 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
191 MonoInst *inst; \
192 int sReg, dReg; \
193 MONO_INST_NEW (cfg, inst, OP_NOP); \
194 if (size > 256) { \
195 inst->dreg = dest; \
196 inst->inst_offset = offset; \
197 inst->sreg1 = src; \
198 inst->inst_imm = imm; \
199 } else { \
200 if (s390_is_uimm12(offset)) { \
201 inst->dreg = dest; \
202 inst->inst_offset = offset; \
203 } else { \
204 dReg = mono_alloc_preg (cfg); \
205 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
206 dReg, dest, offset); \
207 inst->dreg = dReg; \
208 inst->inst_offset = 0; \
210 if (s390_is_uimm12(imm)) { \
211 inst->sreg1 = src; \
212 inst->inst_imm = imm; \
213 } else { \
214 sReg = mono_alloc_preg (cfg); \
215 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
216 sReg, src, imm); \
217 inst->sreg1 = sReg; \
218 inst->inst_imm = 0; \
221 inst->opcode = OP_S390_MOVE; \
222 inst->backend.size = size; \
223 MONO_ADD_INS (cfg->cbb, inst); \
224 } while (0)
226 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
227 int reg = mono_alloc_preg (cfg); \
228 switch (size) { \
229 case 0: \
230 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
231 break; \
232 case 1: \
233 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
234 reg, sr, so); \
235 break; \
236 case 2: \
237 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
238 reg, sr, so); \
239 break; \
240 case 4: \
241 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
242 reg, sr, so); \
243 break; \
244 case 8: \
245 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
246 reg, sr, so); \
247 break; \
249 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
250 } while (0)
252 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
253 int tmpr; \
254 switch (size) { \
255 case 0: \
256 tmpr = mono_alloc_preg (cfg); \
257 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
258 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
259 dr, dx, tmpr); \
260 break; \
261 case 1: \
262 tmpr = mono_alloc_preg (cfg); \
263 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
264 tmpr, sr, so); \
265 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
266 dr, dx, tmpr); \
267 break; \
268 case 2: \
269 tmpr = mono_alloc_preg (cfg); \
270 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
271 tmpr, sr, so); \
272 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
273 dr, dx, tmpr); \
274 break; \
275 case 4: \
276 tmpr = mono_alloc_preg (cfg); \
277 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
278 tmpr, sr, so); \
279 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
280 dr, dx, tmpr); \
281 break; \
282 case 8: \
283 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
284 break; \
286 } while (0)
288 #undef DEBUG
289 #define DEBUG(a) if (cfg->verbose_level > 1) a
291 #define MAX_EXC 16
293 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
295 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
296 #define S390X_NOP_SIZE sizeof(RR_Format)
298 #define MAX(a, b) ((a) > (b) ? (a) : (b))
301 * imt trampoline size values
303 #define CMP_SIZE 24
304 #define LOADCON_SIZE 20
305 #define LOAD_SIZE 6
306 #define BR_SIZE 2
307 #define JUMP_SIZE 6
308 #define ENABLE_WRONG_METHOD_CHECK 0
310 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
311 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
313 /*========================= End of Defines =========================*/
315 /*------------------------------------------------------------------*/
316 /* I n c l u d e s */
317 /*------------------------------------------------------------------*/
319 #include "mini.h"
320 #include <string.h>
321 #include <sys/types.h>
322 #include <unistd.h>
324 #include <mono/metadata/abi-details.h>
325 #include <mono/metadata/appdomain.h>
326 #include <mono/metadata/debug-helpers.h>
327 #include <mono/metadata/profiler-private.h>
328 #include <mono/utils/mono-error.h>
329 #include <mono/utils/mono-error-internals.h>
330 #include <mono/utils/mono-math.h>
331 #include <mono/utils/mono-mmap.h>
332 #include <mono/utils/mono-hwcap.h>
333 #include <mono/utils/mono-threads.h>
334 #include <mono/utils/unlocked.h>
336 #include "mini-s390x.h"
337 #include "cpu-s390x.h"
338 #include "support-s390x.h"
339 #include "jit-icalls.h"
340 #include "ir-emit.h"
341 #include "trace.h"
342 #include "mini-gc.h"
343 #include "aot-runtime.h"
344 #include "mini-runtime.h"
346 /*========================= End of Includes ========================*/
348 /*------------------------------------------------------------------*/
349 /* T y p e d e f s */
350 /*------------------------------------------------------------------*/
352 typedef struct {
353 guint stack_size,
354 local_size,
355 code_size,
356 parm_size,
357 offset,
358 offStruct,
359 retStruct;
360 } size_data;
362 /*------------------------------------------------------------------*/
363 /* Used by the instrument_emit_epilog */
364 /*------------------------------------------------------------------*/
366 enum {
367 SAVE_NONE,
368 SAVE_STRUCT,
369 SAVE_ONE,
370 SAVE_TWO,
371 SAVE_R4,
372 SAVE_R8
375 typedef struct InstList InstList;
377 struct InstList {
378 InstList *prev;
379 InstList *next;
380 MonoInst *data;
383 typedef enum {
384 RegTypeGeneral,
385 RegTypeBase,
386 RegTypeFP,
387 RegTypeFPR4,
388 RegTypeStructByVal,
389 RegTypeStructByValInFP,
390 RegTypeStructByAddr,
391 RegTypeStructByAddrOnStack
392 } ArgStorage;
394 typedef struct {
395 gint32 offset; /* offset from caller's stack */
396 gint32 offparm; /* offset from callee's stack */
397 guint16 vtsize; /* in param area */
398 guint8 reg;
399 ArgStorage regtype;
400 guint32 size; /* Size of structure used by RegTypeStructByVal */
401 gint32 type; /* Data type of argument */
402 } ArgInfo;
404 typedef struct {
405 int nargs;
406 int lastgr;
407 guint32 stack_usage;
408 guint32 struct_ret;
409 ArgInfo ret;
410 ArgInfo sigCookie;
411 size_data sz;
412 int vret_arg_index;
413 MonoMethodSignature *sig;
414 ArgInfo args [1];
415 } CallInfo;
417 typedef struct {
418 gint64 gr[5]; /* R2-R6 */
419 gdouble fp[3]; /* F0-F2 */
420 } __attribute__ ((__packed__)) RegParm;
422 typedef struct {
423 RR_Format basr;
424 RI_Format j;
425 void *pTrigger;
426 RXY_Format lg;
427 RXY_Format trigger;
428 } __attribute__ ((__packed__)) breakpoint_t;
430 /*========================= End of Typedefs ========================*/
432 /*------------------------------------------------------------------*/
433 /* P r o t o t y p e s */
434 /*------------------------------------------------------------------*/
436 static void indent (int);
437 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
438 static void decodeParm (MonoType *, void *, int);
439 static void enter_method (MonoMethod *, RegParm *, char *);
440 static void leave_method (MonoMethod *, ...);
441 static inline void add_general (guint *, size_data *, ArgInfo *);
442 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
443 static inline void add_float (guint *, size_data *, ArgInfo *, gboolean);
444 static CallInfo * get_call_info (MonoMemPool *, MonoMethodSignature *);
445 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
446 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
447 static void compare_and_branch(MonoBasicBlock *, MonoInst *, int, gboolean);
449 /*========================= End of Prototypes ======================*/
451 /*------------------------------------------------------------------*/
452 /* G l o b a l V a r i a b l e s */
453 /*------------------------------------------------------------------*/
455 __thread int indent_level = 0;
456 __thread FILE *trFd = NULL;
457 int curThreadNo = 0;
460 * The code generated for sequence points reads from this location,
461 * which is made read-only when single stepping is enabled.
463 static gpointer ss_trigger_page;
466 * Enabled breakpoints read from this trigger page
468 static gpointer bp_trigger_page;
470 breakpoint_t breakpointCode;
472 static mono_mutex_t mini_arch_mutex;
474 static const char * grNames[] = {
475 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
476 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
477 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
478 "s390_r15"
481 static const char * fpNames[] = {
482 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
483 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
484 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
485 "s390_f15"
488 static const char * vrNames[] = {
489 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
490 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
491 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
492 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
495 /*====================== End of Global Variables ===================*/
497 /*------------------------------------------------------------------*/
498 /* */
499 /* Name - mono_arch_regname */
500 /* */
501 /* Function - Returns the name of the register specified by */
502 /* the input parameter. */
503 /* */
504 /*------------------------------------------------------------------*/
506 const char*
507 mono_arch_regname (int reg)
509 if (reg >= 0 && reg < 16)
510 return grNames [reg];
511 else
512 return "unknown";
515 /*========================= End of Function ========================*/
517 /*------------------------------------------------------------------*/
518 /* */
519 /* Name - mono_arch_fregname */
520 /* */
521 /* Function - Returns the name of the register specified by */
522 /* the input parameter. */
523 /* */
524 /*------------------------------------------------------------------*/
526 const char*
527 mono_arch_fregname (int reg)
529 if (reg >= 0 && reg < 16)
530 return fpNames [reg];
531 else
532 return "unknown";
535 /*========================= End of Function ========================*/
537 /*------------------------------------------------------------------*/
538 /* */
539 /* Name - mono_arch_xregname */
540 /* */
541 /* Function - Returns the name of the register specified by */
542 /* the input parameter. */
543 /* */
544 /*------------------------------------------------------------------*/
546 const char *
547 mono_arch_xregname (int reg)
549 if (reg < s390_VR_NREG)
550 return vrNames [reg];
551 else
552 return "unknown";
555 /*========================= End of Function ========================*/
557 /*------------------------------------------------------------------*/
558 /* */
559 /* Name - arch_get_argument_info */
560 /* */
561 /* Function - Gathers information on parameters such as size, */
562 /* alignment, and padding. arg_info should be large */
563 /* enough to hold param_count + 1 entries. */
564 /* */
565 /* Parameters - @csig - Method signature */
566 /* @param_count - No. of parameters to consider */
567 /* @arg_info - An array to store the result info */
568 /* */
569 /* Returns - Size of the activation frame */
570 /* */
571 /*------------------------------------------------------------------*/
574 mono_arch_get_argument_info (MonoMethodSignature *csig,
575 int param_count,
576 MonoJitArgumentInfo *arg_info)
578 int k, frame_size = 0;
579 int size, align, pad;
580 int offset = 8;
582 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
583 frame_size += sizeof (gpointer);
584 offset += 8;
587 arg_info [0].offset = offset;
589 if (csig->hasthis) {
590 frame_size += sizeof (gpointer);
591 offset += 8;
594 arg_info [0].size = frame_size;
596 for (k = 0; k < param_count; k++) {
598 if (csig->pinvoke)
599 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
600 else
601 size = mini_type_stack_size (csig->params [k], &align);
603 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
604 arg_info [k].pad = pad;
605 frame_size += size;
606 arg_info [k + 1].pad = 0;
607 arg_info [k + 1].size = size;
608 offset += pad;
609 arg_info [k + 1].offset = offset;
610 offset += size;
613 align = MONO_ARCH_FRAME_ALIGNMENT;
614 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
615 arg_info [k].pad = pad;
617 return frame_size;
620 /*========================= End of Function ========================*/
622 /*------------------------------------------------------------------*/
623 /* */
624 /* Name - emit_unwind_regs. */
625 /* */
626 /* Function - Emit unwind information for a range of registers. */
627 /* */
628 /*------------------------------------------------------------------*/
630 static void __inline__
631 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
633 int i;
635 for (i = start; i < end; i++) {
636 mono_emit_unwind_op_offset (cfg, code, i, offset);
637 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
638 offset += sizeof(gulong);
642 /*========================= End of Function ========================*/
644 /*------------------------------------------------------------------*/
645 /* */
646 /* Name - retFitsInReg. */
647 /* */
648 /* Function - Determines if a value can be returned in one or */
649 /* two registers. */
650 /* */
651 /*------------------------------------------------------------------*/
653 static inline gboolean
654 retFitsInReg(guint32 size)
656 switch (size) {
657 case 0:
658 case 1:
659 case 2:
660 case 4:
661 case 8:
662 return (TRUE);
663 break;
664 default:
665 return (FALSE);
669 /*========================= End of Function ========================*/
671 /*------------------------------------------------------------------*/
672 /* */
673 /* Name - backStackPtr. */
674 /* */
675 /* Function - Restore Stack Pointer to previous frame. */
676 /* */
677 /*------------------------------------------------------------------*/
679 static inline guint8 *
680 backUpStackPtr(MonoCompile *cfg, guint8 *code)
682 int stackSize = cfg->stack_usage;
684 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
685 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
686 } else {
687 if (cfg->frame_reg != STK_BASE)
688 s390_lgr (code, STK_BASE, cfg->frame_reg);
690 if (s390_is_imm16 (stackSize)) {
691 s390_aghi (code, STK_BASE, stackSize);
692 } else {
693 while (stackSize > 32767) {
694 s390_aghi (code, STK_BASE, 32767);
695 stackSize -= 32767;
697 s390_aghi (code, STK_BASE, stackSize);
701 return (code);
704 /*========================= End of Function ========================*/
706 /*------------------------------------------------------------------*/
707 /* */
708 /* Name - indent */
709 /* */
710 /* Function - Perform nice indenting to current level */
711 /* */
712 /*------------------------------------------------------------------*/
714 static void
715 indent (int diff) {
716 int v;
717 if (diff < 0)
718 indent_level += diff;
719 v = indent_level;
720 fprintf (trFd, "%p [%3d] ",(void *)pthread_self(),v);
721 while (v-- > 0) {
722 fprintf (trFd, ". ");
724 if (diff > 0)
725 indent_level += diff;
728 /*========================= End of Function ========================*/
730 /*------------------------------------------------------------------*/
731 /* */
732 /* Name - cvtMonoType */
733 /* */
734 /* Function - Convert a mono-type to a string. */
735 /* */
736 /*------------------------------------------------------------------*/
738 static const char *
739 cvtMonoType(MonoTypeEnum t)
741 switch(t)
743 case MONO_TYPE_END:
744 return "MONO_TYPE_END";
745 case MONO_TYPE_VOID:
746 return "MONO_TYPE_VOID";
747 case MONO_TYPE_BOOLEAN:
748 return "MONO_TYPE_BOOLEAN";
749 case MONO_TYPE_CHAR:
750 return "MONO_TYPE_CHAR";
751 case MONO_TYPE_I1:
752 return "MONO_TYPE_I1";
753 case MONO_TYPE_U1:
754 return "MONO_TYPE_U1";
755 case MONO_TYPE_I2:
756 return "MONO_TYPE_I2";
757 case MONO_TYPE_U2:
758 return "MONO_TYPE_U2";
759 case MONO_TYPE_I4:
760 return "MONO_TYPE_I4";
761 case MONO_TYPE_U4:
762 return "MONO_TYPE_U4";
763 case MONO_TYPE_I8:
764 return "MONO_TYPE_I8";
765 case MONO_TYPE_U8:
766 return "MONO_TYPE_U8";
767 case MONO_TYPE_R4:
768 return "MONO_TYPE_R4";
769 case MONO_TYPE_R8:
770 return "MONO_TYPE_R8";
771 case MONO_TYPE_STRING:
772 return "MONO_TYPE_STRING";
773 case MONO_TYPE_PTR:
774 return "MONO_TYPE_PTR";
775 case MONO_TYPE_BYREF:
776 return "MONO_TYPE_BYREF";
777 case MONO_TYPE_VALUETYPE:
778 return "MONO_TYPE_VALUETYPE";
779 case MONO_TYPE_CLASS:
780 return "MONO_TYPE_CLASS";
781 case MONO_TYPE_VAR:
782 return "MONO_TYPE_VAR";
783 case MONO_TYPE_ARRAY:
784 return "MONO_TYPE_ARRAY";
785 case MONO_TYPE_GENERICINST:
786 return "MONO_TYPE_GENERICINST";
787 case MONO_TYPE_TYPEDBYREF:
788 return "MONO_TYPE_TYPEDBYREF";
789 case MONO_TYPE_I:
790 return "MONO_TYPE_I";
791 case MONO_TYPE_U:
792 return "MONO_TYPE_U";
793 case MONO_TYPE_FNPTR:
794 return "MONO_TYPE_FNPTR";
795 case MONO_TYPE_OBJECT:
796 return "MONO_TYPE_OBJECT";
797 case MONO_TYPE_SZARRAY:
798 return "MONO_TYPE_SZARRAY";
799 case MONO_TYPE_MVAR:
800 return "MONO_TYPE_MVAR";
801 case MONO_TYPE_CMOD_REQD:
802 return "MONO_TYPE_CMOD_REQD";
803 case MONO_TYPE_CMOD_OPT:
804 return "MONO_TYPE_CMOD_OPT";
805 case MONO_TYPE_INTERNAL:
806 return "MONO_TYPE_INTERNAL";
807 case MONO_TYPE_MODIFIER:
808 return "MONO_TYPE_MODIFIER";
809 case MONO_TYPE_SENTINEL:
810 return "MONO_TYPE_SENTINEL";
811 case MONO_TYPE_PINNED:
812 return "MONO_TYPE_PINNED";
813 default:
816 return "unknown";
819 /*========================= End of Function ========================*/
821 /*------------------------------------------------------------------*/
822 /* */
823 /* Name - decodeParmString */
824 /* */
825 /* Function - Decode a parameter string for the trace. */
826 /* */
827 /*------------------------------------------------------------------*/
829 static void
830 decodeParmString (MonoString *s)
832 ERROR_DECL (error);
833 char *str = mono_string_to_utf8_checked(s, error);
834 if (is_ok (error)) {
835 fprintf (trFd, "[STRING:%p:%s], ", s, str);
836 g_free (str);
837 } else {
838 mono_error_cleanup (error);
839 fprintf (trFd, "[STRING:%p:], ", s);
843 /*========================= End of Function ========================*/
845 /*------------------------------------------------------------------*/
846 /* */
847 /* Name - decodeParm */
848 /* */
849 /* Function - Decode a parameter for the trace. */
850 /* */
851 /*------------------------------------------------------------------*/
854 static void
855 decodeParm(MonoType *type, void *curParm, int size)
857 guint32 simpleType;
859 if (type->byref) {
860 fprintf (trFd, "[BYREF:%p], ", *((char **) curParm));
861 } else {
862 simpleType = mini_get_underlying_type(type)->type;
863 enum_parmtype:
864 switch (simpleType) {
865 case MONO_TYPE_I :
866 fprintf (trFd, "[INTPTR:%p], ", *((int **) curParm));
867 break;
868 case MONO_TYPE_U :
869 fprintf (trFd, "[UINTPTR:%p], ", *((int **) curParm));
870 break;
871 case MONO_TYPE_BOOLEAN :
872 fprintf (trFd, "[BOOL:%ld], ", *((gint64 *) curParm));
873 break;
874 case MONO_TYPE_CHAR :
875 fprintf (trFd, "[CHAR:%c], ", *((int *) curParm));
876 break;
877 case MONO_TYPE_I1 :
878 fprintf (trFd, "[INT1:%ld], ", *((gint64 *) curParm));
879 break;
880 case MONO_TYPE_I2 :
881 fprintf (trFd, "[INT2:%ld], ", *((gint64 *) curParm));
882 break;
883 case MONO_TYPE_I4 :
884 fprintf (trFd, "[INT4:%ld], ", *((gint64 *) curParm));
885 break;
886 case MONO_TYPE_U1 :
887 fprintf (trFd, "[UINT1:%lu], ", *((guint64 *) curParm));
888 break;
889 case MONO_TYPE_U2 :
890 fprintf (trFd, "[UINT2:%lu], ", *((guint64 *) curParm));
891 break;
892 case MONO_TYPE_U4 :
893 fprintf (trFd, "[UINT4:%lu], ", *((guint64 *) curParm));
894 break;
895 case MONO_TYPE_U8 :
896 fprintf (trFd, "[UINT8:%lu], ", *((guint64 *) curParm));
897 break;
898 case MONO_TYPE_STRING : {
899 MonoString *s = *((MonoString **) curParm);
900 if (s) {
901 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
902 decodeParmString (s);
903 } else {
904 fprintf (trFd, "[STRING:null], ");
906 break;
908 case MONO_TYPE_CLASS :
909 case MONO_TYPE_OBJECT : {
910 MonoObject *obj = *((MonoObject **) curParm);
911 MonoClass *klass;
912 if ((obj) && (obj->vtable)) {
913 fprintf (trFd, "[CLASS/OBJ:");
914 klass = obj->vtable->klass;
915 fprintf (trFd, "%p [%p] ",obj,curParm);
916 if (klass == mono_defaults.string_class) {
917 decodeParmString ((MonoString *)obj);
918 } else if (klass == mono_defaults.int32_class) {
919 fprintf (trFd, "[INT32:%p:%d]",
920 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
921 } else
922 fprintf (trFd, "[%s.%s:%p]",
923 m_class_get_name_space (klass), m_class_get_name (klass), obj);
924 fprintf (trFd, "], ");
925 } else {
926 fprintf (trFd, "[OBJECT:null], ");
928 break;
930 case MONO_TYPE_PTR :
931 fprintf (trFd, "[PTR:%p], ", *((gpointer **) (curParm)));
932 break;
933 case MONO_TYPE_FNPTR :
934 fprintf (trFd, "[FNPTR:%p], ", *((gpointer **) (curParm)));
935 break;
936 case MONO_TYPE_ARRAY :
937 fprintf (trFd, "[ARRAY:%p], ", *((gpointer **) (curParm)));
938 break;
939 case MONO_TYPE_SZARRAY :
940 fprintf (trFd, "[SZARRAY:%p], ", *((gpointer **) (curParm)));
941 break;
942 case MONO_TYPE_I8 :
943 fprintf (trFd, "[INT8:%ld], ", *((gint64 *) (curParm)));
944 break;
945 case MONO_TYPE_R4 :
946 fprintf (trFd, "[FLOAT4:%g], ", *((float *) (curParm)));
947 break;
948 case MONO_TYPE_R8 :
949 fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
950 break;
951 case MONO_TYPE_VALUETYPE : {
952 int i;
953 MonoMarshalType *info;
955 if (m_class_is_enumtype (type->data.klass)) {
956 simpleType = mono_class_enum_basetype (type->data.klass)->type;
957 fprintf (trFd, "{VALUETYPE} - ");
958 goto enum_parmtype;
961 info = mono_marshal_load_type_info (type->data.klass);
963 if ((info->native_size == sizeof(float)) &&
964 (info->num_fields == 1) &&
965 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
966 fprintf (trFd, "[FLOAT4:%f], ", *((float *) (curParm)));
967 break;
970 if ((info->native_size == sizeof(double)) &&
971 (info->num_fields == 1) &&
972 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
973 fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
974 break;
977 fprintf (trFd, "[VALUETYPE:");
978 for (i = 0; i < size; i++)
979 fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
980 fprintf (trFd, "], ");
981 break;
983 case MONO_TYPE_TYPEDBYREF: {
984 int i;
985 fprintf (trFd, "[TYPEDBYREF:");
986 for (i = 0; i < size; i++)
987 fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
988 fprintf (trFd, "]");
989 break;
991 default :
992 fprintf (trFd, "[%s], ",cvtMonoType(simpleType));
997 /*========================= End of Function ========================*/
999 /*------------------------------------------------------------------*/
1000 /* */
1001 /* Name - enter_method */
1002 /* */
1003 /* Function - Perform tracing of the entry to the current */
1004 /* method. */
1005 /* */
1006 /*------------------------------------------------------------------*/
1008 static void
1009 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
1011 int i, oParm = 0, iParm = 0;
1012 MonoClass *klass;
1013 MonoObject *obj;
1014 MonoMethodSignature *sig;
1015 char *fname;
1016 guint64 ip;
1017 CallInfo *cinfo;
1018 ArgInfo *ainfo;
1019 void *curParm;
1021 if (trFd == NULL) {
1022 char buf[32];
1023 sprintf(buf, "/tmp/mono.%d.trc.%d", getpid(), curThreadNo++);
1024 trFd = fopen(buf, "w");
1026 fname = mono_method_full_name (method, TRUE);
1027 indent (1);
1028 fprintf (trFd, "ENTER: %s ", fname);
1029 g_free (fname);
1031 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
1032 fprintf (trFd, "ip: %p sp: %p - ", (gpointer) ip, sp);
1034 if (rParm == NULL)
1035 return;
1037 sig = mono_method_signature (method);
1039 cinfo = get_call_info (NULL, sig);
1041 if (cinfo->struct_ret) {
1042 fprintf (trFd, "[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
1043 iParm = 1;
1046 if (sig->hasthis) {
1047 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
1048 obj = (MonoObject *) this_arg;
1049 switch(m_class_get_this_arg (method->klass)->type) {
1050 case MONO_TYPE_VALUETYPE:
1051 if (obj) {
1052 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
1053 fprintf (trFd, "this:[value:%p:%016lx], ", this_arg, *value);
1054 } else
1055 fprintf (trFd, "this:[NULL], ");
1056 break;
1057 case MONO_TYPE_STRING:
1058 if (obj) {
1059 if (obj->vtable) {
1060 klass = obj->vtable->klass;
1061 if (klass == mono_defaults.string_class) {
1062 fprintf (trFd, "this:");
1063 decodeParmString((MonoString *)obj);
1064 } else {
1065 fprintf (trFd, "this:%p[%s.%s], ",
1066 obj, m_class_get_name_space (klass), m_class_get_name (klass));
1068 } else
1069 fprintf (trFd, "vtable:[NULL], ");
1070 } else
1071 fprintf (trFd, "this:[NULL], ");
1072 break;
1073 default :
1074 fprintf (trFd, "this[%s]: %p, ",cvtMonoType(m_class_get_this_arg (method->klass)->type),this_arg);
1076 oParm++;
1079 for (i = 0; i < sig->param_count; ++i) {
1080 ainfo = &cinfo->args[i + oParm];
1081 switch (ainfo->regtype) {
1082 case RegTypeGeneral :
1083 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1084 break;
1085 case RegTypeFP :
1086 case RegTypeFPR4 :
1087 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1088 break;
1089 case RegTypeBase :
1090 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1091 break;
1092 case RegTypeStructByVal :
1093 if (ainfo->reg != STK_BASE) {
1094 int offset = sizeof(glong) - ainfo->size;
1095 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1097 else
1098 curParm = sp+ainfo->offset;
1100 if (retFitsInReg (ainfo->vtsize))
1101 decodeParm(sig->params[i],
1102 curParm,
1103 ainfo->size);
1104 else
1105 decodeParm(sig->params[i],
1106 *((char **) curParm),
1107 ainfo->vtsize);
1108 break;
1109 case RegTypeStructByAddr :
1110 if (ainfo->reg != STK_BASE)
1111 curParm = &(rParm->gr[ainfo->reg-2]);
1112 else
1113 curParm = sp+ainfo->offset;
1115 decodeParm(sig->params[i],
1116 *((char **) curParm),
1117 ainfo->vtsize);
1118 break;
1120 default :
1121 fprintf (trFd, "???, ");
1124 fprintf (trFd, "\n");
1125 g_free(cinfo);
1128 /*========================= End of Function ========================*/
1130 /*------------------------------------------------------------------*/
1131 /* */
1132 /* Name - leave_method */
1133 /* */
1134 /* Function - */
1135 /* */
1136 /*------------------------------------------------------------------*/
1138 static void
1139 leave_method (MonoMethod *method, ...)
1141 MonoType *type;
1142 char *fname;
1143 guint64 ip;
1144 va_list ap;
1146 va_start(ap, method);
1148 fname = mono_method_full_name (method, TRUE);
1149 indent (-1);
1150 fprintf (trFd, "LEAVE: %s", fname);
1151 g_free (fname);
1153 type = mono_method_signature (method)->ret;
1155 handle_enum:
1156 switch (type->type) {
1157 case MONO_TYPE_VOID:
1158 break;
1159 case MONO_TYPE_BOOLEAN: {
1160 int val = va_arg (ap, int);
1161 if (val)
1162 fprintf (trFd, "[TRUE:%d]", val);
1163 else
1164 fprintf (trFd, "[FALSE]");
1166 break;
1168 case MONO_TYPE_CHAR: {
1169 int val = va_arg (ap, int);
1170 fprintf (trFd, "[CHAR:%d]", val);
1171 break;
1173 case MONO_TYPE_I1: {
1174 int val = va_arg (ap, int);
1175 fprintf (trFd, "[INT1:%d]", val);
1176 break;
1178 case MONO_TYPE_U1: {
1179 int val = va_arg (ap, int);
1180 fprintf (trFd, "[UINT1:%d]", val);
1181 break;
1183 case MONO_TYPE_I2: {
1184 int val = va_arg (ap, int);
1185 fprintf (trFd, "[INT2:%d]", val);
1186 break;
1188 case MONO_TYPE_U2: {
1189 int val = va_arg (ap, int);
1190 fprintf (trFd, "[UINT2:%d]", val);
1191 break;
1193 case MONO_TYPE_I4: {
1194 int val = va_arg (ap, int);
1195 fprintf (trFd, "[INT4:%d]", val);
1196 break;
1198 case MONO_TYPE_U4: {
1199 int val = va_arg (ap, int);
1200 fprintf (trFd, "[UINT4:%d]", val);
1201 break;
1203 case MONO_TYPE_I: {
1204 gint64 val = va_arg (ap, gint64);
1205 fprintf (trFd, "[INT:%ld]", val);
1206 fprintf (trFd, "]");
1207 break;
1209 case MONO_TYPE_U: {
1210 gint64 val = va_arg (ap, gint64);
1211 fprintf (trFd, "[UINT:%lu]", val);
1212 fprintf (trFd, "]");
1213 break;
1215 case MONO_TYPE_STRING: {
1216 MonoString *s = va_arg (ap, MonoString *);
1218 if (s) {
1219 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1220 decodeParmString (s);
1221 } else
1222 fprintf (trFd, "[STRING:null], ");
1223 break;
1225 case MONO_TYPE_CLASS:
1226 case MONO_TYPE_OBJECT: {
1227 MonoObject *o = va_arg (ap, MonoObject *);
1229 if ((o) && (o->vtable)) {
1230 if (o->vtable->klass == mono_defaults.boolean_class) {
1231 fprintf (trFd, "[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1232 } else if (o->vtable->klass == mono_defaults.int32_class) {
1233 fprintf (trFd, "[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1234 } else if (o->vtable->klass == mono_defaults.int64_class) {
1235 fprintf (trFd, "[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1236 } else
1237 fprintf (trFd, "[%s.%s:%p]", m_class_get_name_space (o->vtable->klass), m_class_get_name (o->vtable->klass), o);
1238 } else
1239 fprintf (trFd, "[OBJECT:%p]", o);
1241 break;
1243 case MONO_TYPE_PTR:
1244 case MONO_TYPE_FNPTR:
1245 case MONO_TYPE_ARRAY:
1246 case MONO_TYPE_SZARRAY: {
1247 gpointer p = va_arg (ap, gpointer);
1248 fprintf (trFd, "[result=%p]", p);
1249 break;
1251 case MONO_TYPE_I8: {
1252 gint64 l = va_arg (ap, gint64);
1253 fprintf (trFd, "[LONG:%ld]", l);
1254 break;
1256 case MONO_TYPE_U8: {
1257 guint64 l = va_arg (ap, guint64);
1258 fprintf (trFd, "[ULONG:%lu]", l);
1259 break;
1261 case MONO_TYPE_R4: {
1262 double f = va_arg (ap, double);
1263 fprintf (trFd, "[FLOAT4:%g]\n", f);
1264 break;
1266 case MONO_TYPE_R8: {
1267 double f = va_arg (ap, double);
1268 fprintf (trFd, "[FLOAT8:%g]\n", f);
1269 break;
1271 case MONO_TYPE_VALUETYPE: {
1272 MonoMarshalType *info;
1273 if (m_class_is_enumtype (type->data.klass)) {
1274 type = mono_class_enum_basetype (type->data.klass);
1275 goto handle_enum;
1276 } else {
1277 int size, align;
1279 info = mono_marshal_load_type_info (type->data.klass);
1281 if ((info->native_size == sizeof(float)) &&
1282 (info->num_fields == 1) &&
1283 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1284 double f = va_arg (ap, double);
1285 fprintf (trFd, "[FLOAT4:%g]\n", (double) f);
1286 break;
1289 if ((info->native_size == sizeof(double)) &&
1290 (info->num_fields == 1) &&
1291 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1292 double f = va_arg (ap, double);
1293 fprintf (trFd, "[FLOAT8:%g]\n", f);
1294 break;
1297 size = mono_type_size (type, &align);
1298 switch (size) {
1299 case 1: {
1300 guint32 p = va_arg (ap, guint32);
1301 fprintf (trFd, "[%02x]\n",p);
1302 break;
1304 case 2: {
1305 guint32 p = va_arg (ap, guint32);
1306 fprintf (trFd, "[%04x]\n",p);
1307 break;
1309 case 4: {
1310 guint32 p = va_arg (ap, guint32);
1311 fprintf (trFd, "[%08x]\n",p);
1312 break;
1314 case 8: {
1315 guint64 p = va_arg (ap, guint64);
1316 fprintf (trFd, "[%016lx]\n",p);
1317 break;
1319 default: {
1320 gpointer p = va_arg (ap, gpointer);
1321 fprintf (trFd, "[VALUETYPE] %p\n",p);
1325 break;
1327 case MONO_TYPE_TYPEDBYREF: {
1328 guint8 *p = va_arg (ap, gpointer);
1329 int j, size, align;
1330 size = mono_type_size (type, &align);
1331 switch (size) {
1332 case 1:
1333 case 2:
1334 case 4:
1335 case 8:
1336 fprintf (trFd, "[");
1337 for (j = 0; p && j < size; j++)
1338 fprintf (trFd, "%02x,", p [j]);
1339 fprintf (trFd, "]\n");
1340 break;
1341 default:
1342 fprintf (trFd, "[TYPEDBYREF]\n");
1345 break;
1346 case MONO_TYPE_GENERICINST: {
1347 fprintf (trFd, "[GENERICINST]\n");
1349 break;
1350 case MONO_TYPE_MVAR: {
1351 fprintf (trFd, "[MVAR]\n");
1353 break;
1354 case MONO_TYPE_CMOD_REQD: {
1355 fprintf (trFd, "[CMOD_REQD]\n");
1357 break;
1358 case MONO_TYPE_CMOD_OPT: {
1359 fprintf (trFd, "[CMOD_OPT]\n");
1361 break;
1362 case MONO_TYPE_INTERNAL: {
1363 fprintf (trFd, "[INTERNAL]\n");
1365 break;
1366 default:
1367 fprintf (trFd, "(unknown return type %x)",
1368 mono_method_signature (method)->ret->type);
1371 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1372 fprintf (trFd, " ip: %p\n", (gpointer) ip);
1373 va_end (ap);
1376 /*========================= End of Function ========================*/
1378 /*------------------------------------------------------------------*/
1379 /* */
1380 /* Name - mono_arch_cpu_init */
1381 /* */
1382 /* Function - Perform CPU specific initialization to execute */
1383 /* managed code. */
1384 /* */
1385 /*------------------------------------------------------------------*/
1387 void
1388 mono_arch_cpu_init (void)
1392 /*========================= End of Function ========================*/
1394 /*------------------------------------------------------------------*/
1395 /* */
1396 /* Name - mono_arch_init. */
1397 /* */
1398 /* Function - Initialize architecture specific code. */
1399 /* */
1400 /*------------------------------------------------------------------*/
1402 void
1403 mono_arch_init (void)
1405 guint8 *code;
1407 mono_set_partial_sharing_supported (FALSE);
1408 mono_os_mutex_init_recursive (&mini_arch_mutex);
1410 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1411 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1412 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1414 code = (guint8 *) &breakpointCode;
1415 s390_basr(code, s390_r13, 0);
1416 s390_j(code, 6);
1417 s390_llong(code, 0);
1418 s390_lg(code, s390_r13, 0, s390_r13, 4);
1419 s390_lg(code, s390_r0, 0, s390_r13, 0);
1422 /*========================= End of Function ========================*/
1424 /*------------------------------------------------------------------*/
1425 /* */
1426 /* Name - mono_arch_cleanup. */
1427 /* */
1428 /* Function - Cleanup architecture specific code . */
1429 /* */
1430 /*------------------------------------------------------------------*/
1432 void
1433 mono_arch_cleanup (void)
1435 if (ss_trigger_page)
1436 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1437 if (bp_trigger_page)
1438 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1439 mono_os_mutex_destroy (&mini_arch_mutex);
1442 /*========================= End of Function ========================*/
1444 /*------------------------------------------------------------------*/
1445 /* */
1446 /* Name - mono_arch_have_fast_tls */
1447 /* */
1448 /* Function - Returns whether we use fast inlined thread local */
1449 /* storage managed access, instead of falling back */
1450 /* to native code. */
1451 /* */
1452 /*------------------------------------------------------------------*/
1454 gboolean
1455 mono_arch_have_fast_tls (void)
1457 return TRUE;
1460 /*========================= End of Function ========================*/
1462 /*------------------------------------------------------------------*/
1463 /* */
1464 /* Name - mono_arch_cpu_optimizations */
1465 /* */
1466 /* Function - Returns the optimizations supported on this CPU */
1467 /* */
1468 /*------------------------------------------------------------------*/
1470 guint32
1471 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1473 guint32 opts = 0;
1475 /*----------------------------------------------------------*/
1476 /* No s390-specific optimizations yet */
1477 /*----------------------------------------------------------*/
1478 *exclude_mask = MONO_OPT_LINEARS;
1479 return opts;
1482 /*========================= End of Function ========================*/
1484 /*------------------------------------------------------------------*/
1485 /* */
1486 /* Name - mono_arch_get_allocatable_int_vars */
1487 /* */
1488 /* Function - */
1489 /* */
1490 /*------------------------------------------------------------------*/
1492 GList *
1493 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1495 GList *vars = NULL;
1496 int i;
1498 for (i = 0; i < cfg->num_varinfo; i++) {
1499 MonoInst *ins = cfg->varinfo [i];
1500 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1502 /* unused vars */
1503 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1504 continue;
1506 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1507 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1508 continue;
1510 /* we can only allocate 32 bit values */
1511 if (mono_is_regsize_var(ins->inst_vtype)) {
1512 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1513 g_assert (i == vmv->idx);
1514 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1518 return vars;
1521 /*========================= End of Function ========================*/
1523 /*------------------------------------------------------------------*/
1524 /* */
1525 /* Name - mono_arch_global_int_regs */
1526 /* */
1527 /* Function - Return a list of usable integer registers. */
1528 /* */
1529 /*------------------------------------------------------------------*/
1531 GList *
1532 mono_arch_get_global_int_regs (MonoCompile *cfg)
1534 GList *regs = NULL;
1535 MonoMethodHeader *header;
1536 int i, top = 13;
1538 header = cfg->header;
1539 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1540 cfg->frame_reg = s390_r11;
1543 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1544 top = 12;
1545 for (i = 8; i < top; ++i) {
1546 if ((cfg->frame_reg != i) &&
1547 //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
1548 (i != MONO_ARCH_IMT_REG))
1549 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1552 return regs;
1555 /*========================= End of Function ========================*/
1557 /*------------------------------------------------------------------*/
1558 /* */
1559 /* Name - mono_arch_flush_icache */
1560 /* */
1561 /* Function - Flush the CPU icache. */
1562 /* */
1563 /*------------------------------------------------------------------*/
1565 void
1566 mono_arch_flush_icache (guint8 *code, gint size)
1570 /*========================= End of Function ========================*/
1572 /*------------------------------------------------------------------*/
1573 /* */
1574 /* Name - add_general */
1575 /* */
1576 /* Function - Determine code and stack size incremements for a */
1577 /* parameter. */
1578 /* */
1579 /*------------------------------------------------------------------*/
1581 static void inline
1582 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1584 if (*gr > S390_LAST_ARG_REG) {
1585 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1586 ainfo->offset = sz->stack_size;
1587 ainfo->reg = STK_BASE;
1588 ainfo->regtype = RegTypeBase;
1589 sz->stack_size += sizeof(long);
1590 sz->local_size += sizeof(long);
1591 sz->offStruct += sizeof(long);
1592 sz->code_size += 12;
1593 } else {
1594 ainfo->reg = *gr;
1595 sz->code_size += 8;
1597 (*gr) ++;
1600 /*========================= End of Function ========================*/
1602 /*------------------------------------------------------------------*/
1603 /* */
1604 /* Name - add_stackParm */
1605 /* */
1606 /* Function - Determine code and stack size incremements for a */
1607 /* parameter. */
1608 /* */
1609 /*------------------------------------------------------------------*/
1611 static void inline
1612 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1614 if (*gr > S390_LAST_ARG_REG) {
1615 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1616 ainfo->reg = STK_BASE;
1617 ainfo->offset = sz->stack_size;
1618 ainfo->regtype = RegTypeStructByAddrOnStack;
1619 sz->stack_size += sizeof (gpointer);
1620 sz->parm_size += sizeof(gpointer);
1621 sz->offStruct += sizeof(gpointer);
1622 } else {
1623 ainfo->reg = *gr;
1624 ainfo->offset = sz->stack_size;
1625 ainfo->regtype = RegTypeStructByAddr;
1627 (*gr) ++;
1628 ainfo->offparm = sz->offset;
1629 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1630 ainfo->size = size;
1631 ainfo->vtsize = size;
1632 sz->parm_size += size;
1635 /*========================= End of Function ========================*/
1637 /*------------------------------------------------------------------*/
1638 /* */
1639 /* Name - add_float */
1640 /* */
1641 /* Function - Determine code and stack size incremements for a */
1642 /* float parameter. */
1643 /* */
1644 /*------------------------------------------------------------------*/
1646 static void inline
1647 add_float (guint *fr, size_data *sz, ArgInfo *ainfo, gboolean isDouble)
1649 if ((*fr) <= S390_LAST_FPARG_REG) {
1650 if (isDouble)
1651 ainfo->regtype = RegTypeFP;
1652 else
1653 ainfo->regtype = RegTypeFPR4;
1654 ainfo->reg = *fr;
1655 sz->code_size += 4;
1656 (*fr) += 2;
1658 else {
1659 ainfo->offset = sz->stack_size;
1660 ainfo->reg = STK_BASE;
1661 sz->code_size += 4;
1662 sz->stack_size += sizeof(double);
1663 sz->local_size += sizeof(double);
1664 sz->offStruct += sizeof(double);
1665 ainfo->regtype = RegTypeBase;
1669 /*========================= End of Function ========================*/
1671 /*------------------------------------------------------------------*/
1672 /* */
1673 /* Name - get_call_info */
1674 /* */
1675 /* Function - Determine the amount of space required for code */
1676 /* and stack. In addition determine starting points */
1677 /* for stack-based parameters, and area for struct- */
1678 /* ures being returned on the stack. */
1679 /* */
1680 /*------------------------------------------------------------------*/
1682 static CallInfo *
1683 get_call_info (MonoMemPool *mp, MonoMethodSignature *sig)
1685 guint i, fr, gr, size, pstart;
1686 int nParm = sig->hasthis + sig->param_count;
1687 MonoType *ret_type;
1688 guint32 simpleType, align;
1689 gboolean is_pinvoke = sig->pinvoke;
1690 CallInfo *cinfo;
1691 size_data *sz;
1693 if (mp)
1694 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1695 else
1696 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1698 fr = 0;
1699 gr = s390_r2;
1700 nParm = 0;
1701 cinfo->struct_ret = 0;
1702 cinfo->sig = sig;
1703 sz = &cinfo->sz;
1704 sz->retStruct = 0;
1705 sz->offset = 0;
1706 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1707 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1708 sz->code_size = 0;
1709 sz->parm_size = 0;
1710 sz->local_size = 0;
1711 align = 0;
1712 size = 0;
1714 /*----------------------------------------------------------*/
1715 /* We determine the size of the return code/stack in case we*/
1716 /* need to reserve a register to be used to address a stack */
1717 /* area that the callee will use. */
1718 /*----------------------------------------------------------*/
1720 ret_type = mini_get_underlying_type (sig->ret);
1721 simpleType = ret_type->type;
1722 enum_retvalue:
1723 switch (simpleType) {
1724 case MONO_TYPE_I1:
1725 case MONO_TYPE_U1:
1726 case MONO_TYPE_I2:
1727 case MONO_TYPE_U2:
1728 case MONO_TYPE_I4:
1729 case MONO_TYPE_U4:
1730 case MONO_TYPE_I:
1731 case MONO_TYPE_U:
1732 case MONO_TYPE_OBJECT:
1733 case MONO_TYPE_PTR:
1734 case MONO_TYPE_FNPTR:
1735 cinfo->ret.reg = s390_r2;
1736 sz->code_size += 4;
1737 break;
1738 case MONO_TYPE_R4:
1739 case MONO_TYPE_R8:
1740 cinfo->ret.reg = s390_f0;
1741 sz->code_size += 4;
1742 break;
1743 case MONO_TYPE_I8:
1744 case MONO_TYPE_U8:
1745 cinfo->ret.reg = s390_r2;
1746 sz->code_size += 4;
1747 break;
1748 case MONO_TYPE_GENERICINST:
1749 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1750 cinfo->ret.reg = s390_r2;
1751 sz->code_size += 4;
1752 break;
1754 /* Fall through */
1755 case MONO_TYPE_VALUETYPE: {
1756 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1757 if (m_class_is_enumtype (klass)) {
1758 simpleType = mono_class_enum_basetype (klass)->type;
1759 goto enum_retvalue;
1761 size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke);
1763 cinfo->struct_ret = 1;
1764 cinfo->ret.size = size;
1765 cinfo->ret.vtsize = size;
1766 break;
1768 case MONO_TYPE_TYPEDBYREF:
1769 size = sizeof (MonoTypedRef);
1770 cinfo->struct_ret = 1;
1771 cinfo->ret.size = size;
1772 cinfo->ret.vtsize = size;
1773 break;
1774 case MONO_TYPE_VOID:
1775 break;
1776 default:
1777 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1781 pstart = 0;
1783 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1784 * the first argument, allowing 'this' to be always passed in the first arg reg.
1785 * Also do this if the first argument is a reference type, since virtual calls
1786 * are sometimes made using calli without sig->hasthis set, like in the delegate
1787 * invoke wrappers.
1789 if (cinfo->struct_ret && !is_pinvoke &&
1790 (sig->hasthis ||
1791 (sig->param_count > 0 &&
1792 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1793 if (sig->hasthis) {
1794 cinfo->args[nParm].size = sizeof (gpointer);
1795 add_general (&gr, sz, cinfo->args + nParm);
1796 } else {
1797 cinfo->args[nParm].size = sizeof (gpointer);
1798 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1799 pstart = 1;
1801 nParm ++;
1802 cinfo->vret_arg_index = 1;
1803 cinfo->ret.reg = gr;
1804 gr ++;
1805 } else {
1806 /* this */
1807 if (sig->hasthis) {
1808 cinfo->args[nParm].size = sizeof (gpointer);
1809 add_general (&gr, sz, cinfo->args + nParm);
1810 nParm ++;
1813 if (cinfo->struct_ret) {
1814 cinfo->ret.reg = gr;
1815 gr ++;
1819 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1820 gr = S390_LAST_ARG_REG + 1;
1821 fr = S390_LAST_FPARG_REG + 1;
1823 /* Emit the signature cookie just before the implicit arguments */
1824 add_general (&gr, sz, &cinfo->sigCookie);
1827 /*----------------------------------------------------------*/
1828 /* We determine the size of the parameter code and stack */
1829 /* requirements by checking the types and sizes of the */
1830 /* parameters. */
1831 /*----------------------------------------------------------*/
1833 for (i = pstart; i < sig->param_count; ++i) {
1834 MonoType *ptype;
1836 /*--------------------------------------------------*/
1837 /* Handle vararg type calls. All args are put on */
1838 /* the stack. */
1839 /*--------------------------------------------------*/
1840 if ((sig->call_convention == MONO_CALL_VARARG) &&
1841 (i == sig->sentinelpos)) {
1842 gr = S390_LAST_ARG_REG + 1;
1843 fr = S390_LAST_FPARG_REG + 1;
1844 add_general (&gr, sz, &cinfo->sigCookie);
1847 if (sig->params [i]->byref) {
1848 add_general (&gr, sz, cinfo->args+nParm);
1849 cinfo->args[nParm].size = sizeof(gpointer);
1850 nParm++;
1851 continue;
1854 ptype = mini_get_underlying_type (sig->params [i]);
1855 simpleType = ptype->type;
1856 cinfo->args[nParm].type = simpleType;
1857 switch (simpleType) {
1858 case MONO_TYPE_I1:
1859 case MONO_TYPE_U1:
1860 cinfo->args[nParm].size = sizeof(char);
1861 add_general (&gr, sz, cinfo->args+nParm);
1862 nParm++;
1863 break;
1864 case MONO_TYPE_I2:
1865 case MONO_TYPE_U2:
1866 cinfo->args[nParm].size = sizeof(short);
1867 add_general (&gr, sz, cinfo->args+nParm);
1868 nParm++;
1869 break;
1870 case MONO_TYPE_I4:
1871 case MONO_TYPE_U4:
1872 cinfo->args[nParm].size = sizeof(int);
1873 add_general (&gr, sz, cinfo->args+nParm);
1874 nParm++;
1875 break;
1876 case MONO_TYPE_I:
1877 case MONO_TYPE_U:
1878 case MONO_TYPE_PTR:
1879 case MONO_TYPE_FNPTR:
1880 case MONO_TYPE_OBJECT:
1881 cinfo->args[nParm].size = sizeof(gpointer);
1882 add_general (&gr, sz, cinfo->args+nParm);
1883 nParm++;
1884 break;
1885 case MONO_TYPE_I8:
1886 case MONO_TYPE_U8:
1887 cinfo->args[nParm].size = sizeof(long long);
1888 add_general (&gr, sz, cinfo->args+nParm);
1889 nParm++;
1890 break;
1891 case MONO_TYPE_R4:
1892 cinfo->args[nParm].size = sizeof(float);
1893 add_float (&fr, sz, cinfo->args+nParm, FALSE);
1894 nParm++;
1895 break;
1896 case MONO_TYPE_R8:
1897 cinfo->args[nParm].size = sizeof(double);
1898 add_float (&fr, sz, cinfo->args+nParm, TRUE);
1899 nParm++;
1900 break;
1901 case MONO_TYPE_GENERICINST:
1902 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1903 cinfo->args[nParm].size = sizeof(gpointer);
1904 add_general (&gr, sz, cinfo->args+nParm);
1905 nParm++;
1906 break;
1908 /* Fall through */
1909 case MONO_TYPE_VALUETYPE: {
1910 MonoMarshalType *info;
1911 MonoClass *klass = mono_class_from_mono_type (ptype);
1913 if (sig->pinvoke)
1914 size = mono_class_native_size(klass, NULL);
1915 else
1916 size = mono_class_value_size(klass, NULL);
1918 if (simpleType != MONO_TYPE_GENERICINST) {
1919 info = mono_marshal_load_type_info(klass);
1921 if ((info->native_size == sizeof(float)) &&
1922 (info->num_fields == 1) &&
1923 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1924 cinfo->args[nParm].size = sizeof(float);
1925 add_float(&fr, sz, cinfo->args+nParm, FALSE);
1926 nParm ++;
1927 break;
1930 if ((info->native_size == sizeof(double)) &&
1931 (info->num_fields == 1) &&
1932 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1933 cinfo->args[nParm].size = sizeof(double);
1934 add_float(&fr, sz, cinfo->args+nParm, TRUE);
1935 nParm ++;
1936 break;
1940 cinfo->args[nParm].vtsize = 0;
1941 cinfo->args[nParm].size = 0;
1943 switch (size) {
1944 /*----------------------------------*/
1945 /* On S/390, structures of size 1, */
1946 /* 2, 4, and 8 bytes are passed in */
1947 /* (a) register(s). */
1948 /*----------------------------------*/
1949 case 0:
1950 case 1:
1951 case 2:
1952 case 4:
1953 case 8:
1954 add_general(&gr, sz, cinfo->args+nParm);
1955 cinfo->args[nParm].size = size;
1956 cinfo->args[nParm].regtype = RegTypeStructByVal;
1957 nParm++;
1958 sz->local_size += sizeof(long);
1959 break;
1960 default:
1961 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1962 nParm++;
1965 break;
1966 case MONO_TYPE_TYPEDBYREF: {
1967 int size = sizeof (MonoTypedRef);
1969 cinfo->args[nParm].vtsize = 0;
1970 cinfo->args[nParm].size = 0;
1972 switch (size) {
1973 /*----------------------------------*/
1974 /* On S/390, structures of size 1, */
1975 /* 2, 4, and 8 bytes are passed in */
1976 /* (a) register(s). */
1977 /*----------------------------------*/
1978 case 0:
1979 case 1:
1980 case 2:
1981 case 4:
1982 case 8:
1983 add_general(&gr, sz, cinfo->args+nParm);
1984 cinfo->args[nParm].size = size;
1985 cinfo->args[nParm].regtype = RegTypeStructByVal;
1986 nParm++;
1987 sz->local_size += sizeof(long);
1988 break;
1989 default:
1990 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1991 nParm++;
1994 break;
1995 default:
1996 g_error ("Can't trampoline 0x%x", ptype);
2000 /*----------------------------------------------------------*/
2001 /* Handle the case where there are no implicit arguments */
2002 /*----------------------------------------------------------*/
2003 if ((sig->call_convention == MONO_CALL_VARARG) &&
2004 (nParm > 0) &&
2005 (!sig->pinvoke) &&
2006 (sig->param_count == sig->sentinelpos)) {
2007 gr = S390_LAST_ARG_REG + 1;
2008 fr = S390_LAST_FPARG_REG + 1;
2009 add_general (&gr, sz, &cinfo->sigCookie);
2012 /*----------------------------------------------------------*/
2013 /* If we are passing a structure back then if it won't be */
2014 /* in a register(s) then we make room at the end of the */
2015 /* parameters that may have been placed on the stack */
2016 /*----------------------------------------------------------*/
2017 if (cinfo->struct_ret) {
2018 cinfo->ret.offset = sz->stack_size;
2019 switch (cinfo->ret.size) {
2020 case 0:
2021 case 1:
2022 case 2:
2023 case 4:
2024 case 8:
2025 break;
2026 default:
2027 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
2031 cinfo->lastgr = gr;
2032 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
2033 sz->offset;
2034 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
2036 return (cinfo);
2039 /*========================= End of Function ========================*/
2041 /*------------------------------------------------------------------*/
2042 /* */
2043 /* Name - mono_arch_allocate_vars */
2044 /* */
2045 /* Function - Set var information according to the calling */
2046 /* convention for S/390. The local var stuff should */
2047 /* most likely be split in another method. */
2048 /* */
2049 /* Parameter - @m - Compile unit. */
2050 /* */
2051 /*------------------------------------------------------------------*/
2053 void
2054 mono_arch_allocate_vars (MonoCompile *cfg)
2056 MonoMethodSignature *sig;
2057 MonoMethodHeader *header;
2058 MonoInst *inst;
2059 CallInfo *cinfo;
2060 int iParm, iVar, offset, align, size, curinst;
2061 int frame_reg = STK_BASE;
2062 int sArg, eArg;
2064 header = cfg->header;
2066 cfg->flags |= MONO_CFG_HAS_SPILLUP;
2068 /*---------------------------------------------------------*/
2069 /* We use the frame register also for any method that has */
2070 /* filter clauses. This way, when the handlers are called, */
2071 /* the code will reference local variables using the frame */
2072 /* reg instead of the stack pointer: if we had to restore */
2073 /* the stack pointer, we'd corrupt the method frames that */
2074 /* are already on the stack (since filters get called */
2075 /* before stack unwinding happens) when the filter code */
2076 /* would call any method. */
2077 /*---------------------------------------------------------*/
2078 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2079 frame_reg = s390_r11;
2081 cfg->frame_reg = frame_reg;
2083 cfg->arch.bkchain_reg = -1;
2085 if (frame_reg != STK_BASE)
2086 cfg->used_int_regs |= (1LL << frame_reg);
2088 sig = mono_method_signature (cfg->method);
2090 cinfo = get_call_info (cfg->mempool, sig);
2092 if (!cinfo->struct_ret) {
2093 switch (mini_get_underlying_type (sig->ret)->type) {
2094 case MONO_TYPE_VOID:
2095 break;
2096 default:
2097 cfg->ret->opcode = OP_REGVAR;
2098 cfg->ret->dreg = s390_r2;
2099 break;
2103 /*--------------------------------------------------------------*/
2104 /* local vars are at a positive offset from the stack pointer */
2105 /* also note that if the function uses alloca, we use s390_r11 */
2106 /* to point at the local variables. */
2107 /* add parameter area size for called functions */
2108 /*--------------------------------------------------------------*/
2109 if (cfg->param_area == 0)
2110 offset = S390_MINIMAL_STACK_SIZE;
2111 else
2112 offset = cfg->param_area;
2114 cfg->sig_cookie = 0;
2116 if (cinfo->struct_ret) {
2117 inst = cfg->vret_addr;
2118 offset = S390_ALIGN(offset, sizeof(gpointer));
2119 inst->inst_offset = offset;
2120 inst->opcode = OP_REGOFFSET;
2121 inst->inst_basereg = frame_reg;
2122 offset += sizeof(gpointer);
2123 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2124 printf ("vret_addr =");
2125 mono_print_ins (cfg->vret_addr);
2129 if (sig->hasthis) {
2130 inst = cfg->args [0];
2131 if (inst->opcode != OP_REGVAR) {
2132 inst->opcode = OP_REGOFFSET;
2133 inst->inst_basereg = frame_reg;
2134 offset = S390_ALIGN(offset, sizeof(gpointer));
2135 inst->inst_offset = offset;
2136 offset += sizeof (gpointer);
2138 curinst = sArg = 1;
2139 } else {
2140 curinst = sArg = 0;
2143 eArg = sig->param_count + sArg;
2145 if (sig->call_convention == MONO_CALL_VARARG)
2146 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2148 for (iParm = sArg; iParm < eArg; ++iParm) {
2149 inst = cfg->args [curinst];
2150 if (inst->opcode != OP_REGVAR) {
2151 switch (cinfo->args[iParm].regtype) {
2152 case RegTypeStructByAddr : {
2153 MonoInst *indir;
2155 size = sizeof (gpointer);
2157 inst->opcode = OP_REGOFFSET;
2158 inst->inst_basereg = frame_reg;
2159 offset = S390_ALIGN (offset, sizeof (gpointer));
2160 inst->inst_offset = offset;
2162 /* Add a level of indirection */
2163 MONO_INST_NEW (cfg, indir, 0);
2164 *indir = *inst;
2165 inst->opcode = OP_VTARG_ADDR;
2166 inst->inst_left = indir;
2168 break;
2169 case RegTypeStructByAddrOnStack : {
2170 MonoInst *indir;
2172 size = sizeof (gpointer);
2174 /* Similar to the == STK_BASE case below */
2175 cfg->arch.bkchain_reg = s390_r12;
2176 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2178 inst->opcode = OP_REGOFFSET;
2179 inst->dreg = mono_alloc_preg (cfg);
2180 inst->inst_basereg = cfg->arch.bkchain_reg;
2181 inst->inst_offset = cinfo->args [iParm].offset;
2183 /* Add a level of indirection */
2184 MONO_INST_NEW (cfg, indir, 0);
2185 *indir = *inst;
2186 inst->opcode = OP_VTARG_ADDR;
2187 inst->inst_left = indir;
2188 break;
2190 case RegTypeStructByVal :
2191 size = cinfo->args[iParm].size;
2192 offset = S390_ALIGN(offset, size);
2193 inst->opcode = OP_REGOFFSET;
2194 inst->inst_basereg = frame_reg;
2195 inst->inst_offset = offset;
2196 break;
2197 default :
2198 if (cinfo->args [iParm].reg == STK_BASE) {
2200 * These arguments are in the previous frame, so we can't
2201 * compute their offset from the current frame pointer right
2202 * now, since cfg->stack_offset is not yet known, so dedicate a
2203 * register holding the previous frame pointer.
2205 cfg->arch.bkchain_reg = s390_r12;
2206 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2208 inst->opcode = OP_REGOFFSET;
2209 inst->inst_basereg = cfg->arch.bkchain_reg;
2210 size = (cinfo->args[iParm].size < 8
2211 ? 8 - cinfo->args[iParm].size
2212 : 0);
2213 inst->inst_offset = cinfo->args [iParm].offset + size;
2214 size = sizeof (long);
2215 } else {
2216 inst->opcode = OP_REGOFFSET;
2217 inst->inst_basereg = frame_reg;
2218 size = (cinfo->args[iParm].size < 8
2219 ? sizeof(int)
2220 : sizeof(long));
2221 offset = S390_ALIGN(offset, size);
2222 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2223 inst->inst_offset = offset;
2224 else
2225 inst->inst_offset = offset + (8 - size);
2227 break;
2229 offset += MAX(size, 8);
2231 curinst++;
2234 cfg->locals_min_stack_offset = offset;
2236 curinst = cfg->locals_start;
2237 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2238 inst = cfg->varinfo [iVar];
2239 if ((inst->flags & MONO_INST_IS_DEAD) ||
2240 (inst->opcode == OP_REGVAR))
2241 continue;
2243 /*--------------------------------------------------*/
2244 /* inst->backend.is_pinvoke indicates native sized */
2245 /* value typs this is used by the pinvoke wrappers */
2246 /* when they call functions returning structure */
2247 /*--------------------------------------------------*/
2248 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2249 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2250 (guint32 *) &align);
2251 else
2252 size = mono_type_size (inst->inst_vtype, &align);
2254 offset = S390_ALIGN(offset, align);
2255 inst->inst_offset = offset;
2256 inst->opcode = OP_REGOFFSET;
2257 inst->inst_basereg = frame_reg;
2258 offset += size;
2259 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2260 iVar, inst->inst_offset, size));
2263 cfg->locals_max_stack_offset = offset;
2265 /*------------------------------------------------------*/
2266 /* Allow space for the trace method stack area if needed*/
2267 /*------------------------------------------------------*/
2268 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2269 offset += S390_TRACE_STACK_SIZE;
2271 /*------------------------------------------------------*/
2272 /* Reserve space to save LMF and caller saved registers */
2273 /*------------------------------------------------------*/
2274 if (cfg->method->save_lmf)
2275 offset += sizeof (MonoLMF);
2277 /*------------------------------------------------------*/
2278 /* align the offset */
2279 /*------------------------------------------------------*/
2280 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2282 /*------------------------------------------------------*/
2283 /* Fix offsets for args whose value is in parent frame */
2284 /*------------------------------------------------------*/
2285 for (iParm = sArg; iParm < eArg; ++iParm) {
2286 inst = cfg->args [iParm];
2288 if (inst->opcode == OP_S390_STKARG) {
2289 inst->opcode = OP_REGOFFSET;
2290 inst->inst_offset += cfg->stack_offset;
2295 /*========================= End of Function ========================*/
2297 /*------------------------------------------------------------------*/
2298 /* */
2299 /* Name - mono_arch_create_vars */
2300 /* */
2301 /*------------------------------------------------------------------*/
2303 void
2304 mono_arch_create_vars (MonoCompile *cfg)
2306 MonoMethodSignature *sig;
2307 CallInfo *cinfo;
2309 sig = mono_method_signature (cfg->method);
2311 cinfo = get_call_info (cfg->mempool, sig);
2313 if (cinfo->struct_ret) {
2314 cfg->vret_addr = mono_compile_create_var (cfg, mono_get_int_type (), OP_ARG);
2315 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2316 printf ("vret_addr = ");
2317 mono_print_ins (cfg->vret_addr);
2322 /*========================= End of Function ========================*/
2324 /*------------------------------------------------------------------*/
2325 /* */
2326 /* Name - add_outarg_reg2. */
2327 /* */
2328 /*------------------------------------------------------------------*/
2330 static void
2331 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2333 MonoInst *ins;
2335 switch (storage) {
2336 case RegTypeGeneral:
2337 MONO_INST_NEW (cfg, ins, OP_MOVE);
2338 ins->dreg = mono_alloc_ireg (cfg);
2339 ins->sreg1 = tree->dreg;
2340 MONO_ADD_INS (cfg->cbb, ins);
2341 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2342 break;
2343 case RegTypeFP:
2344 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2345 ins->dreg = mono_alloc_freg (cfg);
2346 ins->sreg1 = tree->dreg;
2347 MONO_ADD_INS (cfg->cbb, ins);
2348 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2349 break;
2350 case RegTypeFPR4:
2351 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2352 ins->dreg = mono_alloc_freg (cfg);
2353 ins->sreg1 = tree->dreg;
2354 MONO_ADD_INS (cfg->cbb, ins);
2355 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2356 break;
2357 default:
2358 g_assert_not_reached ();
2362 /*========================= End of Function ========================*/
2364 /*------------------------------------------------------------------*/
2365 /* */
2366 /* Name - emit_sig_cookie. */
2367 /* */
2368 /*------------------------------------------------------------------*/
2370 static void
2371 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2373 MonoMethodSignature *tmpSig;
2374 MonoInst *sig_arg;
2376 cfg->disable_aot = TRUE;
2378 /*----------------------------------------------------------*/
2379 /* mono_ArgIterator_Setup assumes the signature cookie is */
2380 /* passed first and all the arguments which were before it */
2381 /* passed on the stack after the signature. So compensate */
2382 /* by passing a different signature. */
2383 /*----------------------------------------------------------*/
2384 tmpSig = mono_metadata_signature_dup (call->signature);
2385 tmpSig->param_count -= call->signature->sentinelpos;
2386 tmpSig->sentinelpos = 0;
2387 if (tmpSig->param_count > 0)
2388 memcpy (tmpSig->params,
2389 call->signature->params + call->signature->sentinelpos,
2390 tmpSig->param_count * sizeof(MonoType *));
2392 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2393 sig_arg->dreg = mono_alloc_ireg (cfg);
2394 sig_arg->inst_p0 = tmpSig;
2395 MONO_ADD_INS (cfg->cbb, sig_arg);
2397 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2398 cinfo->sigCookie.offset, sig_arg->dreg);
2401 /*========================= End of Function ========================*/
2403 /*------------------------------------------------------------------*/
2404 /* */
2405 /* Name - mono_arch_emit_call */
2406 /* */
2407 /*------------------------------------------------------------------*/
2409 void
2410 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2412 MonoInst *in;
2413 MonoMethodSignature *sig;
2414 MonoInst *ins;
2415 int i, n, lParamArea;
2416 CallInfo *cinfo;
2417 ArgInfo *ainfo = NULL;
2418 int stackSize;
2419 MonoMethodHeader *header;
2420 int frmReg;
2422 sig = call->signature;
2423 n = sig->param_count + sig->hasthis;
2424 DEBUG (g_print ("Call requires: %d parameters\n",n));
2426 cinfo = get_call_info (cfg->mempool, sig);
2428 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2429 cinfo->sz.parm_size + cinfo->sz.offset;
2430 call->stack_usage = MAX(stackSize, call->stack_usage);
2431 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2432 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2433 cfg->flags |= MONO_CFG_HAS_CALLS;
2435 if (cinfo->struct_ret) {
2436 MONO_INST_NEW (cfg, ins, OP_MOVE);
2437 ins->sreg1 = call->vret_var->dreg;
2438 ins->dreg = mono_alloc_preg (cfg);
2439 MONO_ADD_INS (cfg->cbb, ins);
2440 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2443 header = cfg->header;
2444 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2445 frmReg = s390_r11;
2446 else
2447 frmReg = STK_BASE;
2449 for (i = 0; i < n; ++i) {
2450 MonoType *t;
2452 ainfo = cinfo->args + i;
2453 if (i >= sig->hasthis)
2454 t = sig->params [i - sig->hasthis];
2455 else
2456 t = mono_get_int_type ();
2457 t = mini_get_underlying_type (t);
2459 in = call->args [i];
2461 if ((sig->call_convention == MONO_CALL_VARARG) &&
2462 (!sig->pinvoke) &&
2463 (i == sig->sentinelpos)) {
2464 emit_sig_cookie (cfg, call, cinfo);
2467 switch (ainfo->regtype) {
2468 case RegTypeGeneral :
2469 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2470 break;
2471 case RegTypeFP :
2472 case RegTypeFPR4 :
2473 if (MONO_TYPE_ISSTRUCT (t)) {
2474 /* Valuetype passed in one fp register */
2475 ainfo->regtype = RegTypeStructByValInFP;
2476 /* Fall through */
2477 } else {
2478 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2479 break;
2481 case RegTypeStructByVal :
2482 case RegTypeStructByAddr :
2483 case RegTypeStructByAddrOnStack : {
2484 guint32 align;
2485 guint32 size;
2487 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2488 size = sizeof (MonoTypedRef);
2489 align = sizeof (gpointer);
2491 else
2492 if (sig->pinvoke)
2493 size = mono_type_native_stack_size (m_class_get_byval_arg (in->klass), &align);
2494 else {
2496 * Other backends use mono_type_stack_size (), but that
2497 * aligns the size to 8, which is larger than the size of
2498 * the source, leading to reads of invalid memory if the
2499 * source is at the end of address space.
2501 size = mono_class_value_size (in->klass, &align);
2504 g_assert (in->klass);
2506 ainfo->offparm += cinfo->sz.offStruct;
2508 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2509 ins->sreg1 = in->dreg;
2510 ins->klass = in->klass;
2511 ins->backend.size = ainfo->size;
2512 ins->inst_p0 = call;
2513 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2514 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2516 MONO_ADD_INS (cfg->cbb, ins);
2518 if (ainfo->regtype == RegTypeStructByAddr) {
2520 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2521 * use the normal OUTARG opcodes to pass the address of the location to
2522 * the callee.
2524 int treg = mono_alloc_preg (cfg);
2525 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2526 frmReg, ainfo->offparm);
2527 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2528 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2529 /* The address of the valuetype is passed on the stack */
2530 int treg = mono_alloc_preg (cfg);
2531 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2532 frmReg, ainfo->offparm);
2533 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2534 ainfo->reg, ainfo->offset, treg);
2536 if (cfg->compute_gc_maps) {
2537 MonoInst *def;
2539 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2542 break;
2544 case RegTypeBase :
2545 if (!t->byref && t->type == MONO_TYPE_R4) {
2546 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2547 STK_BASE, ainfo->offset + 4,
2548 in->dreg);
2549 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2550 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2551 STK_BASE, ainfo->offset,
2552 in->dreg);
2553 } else {
2554 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2555 ins->inst_destbasereg = STK_BASE;
2556 ins->inst_offset = ainfo->offset;
2557 ins->sreg1 = in->dreg;
2558 MONO_ADD_INS (cfg->cbb, ins);
2560 break;
2561 default:
2562 g_assert_not_reached ();
2563 break;
2568 * Handle the case where there are no implicit arguments
2570 if ((sig->call_convention == MONO_CALL_VARARG) &&
2571 (!sig->pinvoke) &&
2572 (i == sig->sentinelpos)) {
2573 emit_sig_cookie (cfg, call, cinfo);
2577 /*========================= End of Function ========================*/
2579 /*------------------------------------------------------------------*/
2580 /* */
2581 /* Name - mono_arch_emit_outarg_vt */
2582 /* */
2583 /*------------------------------------------------------------------*/
2585 void
2586 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2588 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2589 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2590 int size = ins->backend.size;
2592 if (ainfo->regtype == RegTypeStructByVal) {
2594 arg->ins.sreg1 = ainfo->reg;
2595 arg->ins.opcode = OP_OUTARG_VT;
2596 arg->size = ainfo->size;
2597 arg->offset = ainfo->offset;
2598 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2600 if (ainfo->reg != STK_BASE) {
2601 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2602 } else {
2603 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2604 src->dreg, 0);
2606 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2607 int dreg = mono_alloc_freg (cfg);
2609 if (ainfo->size == 4) {
2610 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2611 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2612 } else {
2613 g_assert (ainfo->size == 8);
2615 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2618 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2619 } else {
2620 ERROR_DECL (error);
2621 MonoMethodHeader *header;
2622 int srcReg;
2624 header = mono_method_get_header_checked (cfg->method, error);
2625 mono_error_assert_ok (error); /* FIXME don't swallow the error */
2626 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2627 srcReg = s390_r11;
2628 else
2629 srcReg = STK_BASE;
2631 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2632 src->dreg, 0, size);
2634 if (cfg->compute_gc_maps) {
2635 MonoInst *def;
2637 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, m_class_get_byval_arg (ins->klass));
2642 /*========================= End of Function ========================*/
2644 /*------------------------------------------------------------------*/
2645 /* */
2646 /* Name - mono_arch_emit_setret */
2647 /* */
2648 /*------------------------------------------------------------------*/
2650 void
2651 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2653 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2655 if (!ret->byref) {
2656 if (ret->type == MONO_TYPE_R4) {
2657 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2658 return;
2659 } else if (ret->type == MONO_TYPE_R8) {
2660 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2661 return;
2665 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2668 /*========================= End of Function ========================*/
2670 /*------------------------------------------------------------------*/
2671 /* */
2672 /* Name - mono_arch_instrument_prolog */
2673 /* */
2674 /* Function - Create an "instrumented" prolog. */
2675 /* */
2676 /*------------------------------------------------------------------*/
2678 void*
2679 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2680 gboolean enable_arguments)
2682 guchar *code = p;
2683 int parmOffset,
2684 fpOffset,
2685 baseReg;
2687 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE - cfg->arch.fpSize;
2688 if (cfg->method->save_lmf)
2689 parmOffset -= sizeof(MonoLMF);
2690 fpOffset = parmOffset + (5*sizeof(gpointer));
2691 baseReg = STK_BASE;
2693 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2694 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2695 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2696 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2697 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2698 S390_SET (code, s390_r1, func);
2699 S390_SET (code, s390_r2, cfg->method);
2700 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2701 s390_lgr (code, s390_r4, STK_BASE);
2702 s390_aghi (code, s390_r4, cfg->stack_usage);
2703 s390_basr (code, s390_r14, s390_r1);
2704 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2705 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2706 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2707 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2708 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2710 return code;
2713 /*========================= End of Function ========================*/
2715 /*------------------------------------------------------------------*/
2716 /* */
2717 /* Name - mono_arch_instrument_epilog */
2718 /* */
2719 /* Function - Create an epilog that will handle the returned */
2720 /* values used in instrumentation. */
2721 /* */
2722 /*------------------------------------------------------------------*/
2724 void*
2725 mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
2727 guchar *code = p;
2728 int save_mode = SAVE_NONE,
2729 saveOffset;
2730 MonoMethod *method = cfg->method;
2731 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2733 set_code_cursor (cfg, code);
2734 /*-----------------------------------------*/
2735 /* We need about 128 bytes of instructions */
2736 /*-----------------------------------------*/
2737 code = realloc_code (cfg, 128);
2739 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE - cfg->arch.fpSize;
2740 if (method->save_lmf)
2741 saveOffset -= sizeof(MonoLMF);
2743 handle_enum:
2744 switch (rtype) {
2745 case MONO_TYPE_VOID:
2746 /* special case string .ctor icall */
2747 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2748 save_mode = SAVE_ONE;
2749 else
2750 save_mode = SAVE_NONE;
2751 break;
2752 case MONO_TYPE_I8:
2753 case MONO_TYPE_U8:
2754 save_mode = SAVE_ONE;
2755 break;
2756 case MONO_TYPE_R4:
2757 save_mode = SAVE_R4;
2758 break;
2759 case MONO_TYPE_R8:
2760 save_mode = SAVE_R8;
2761 break;
2762 case MONO_TYPE_VALUETYPE:
2763 if (m_class_is_enumtype (mono_method_signature (method)->ret->data.klass)) {
2764 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2765 goto handle_enum;
2767 save_mode = SAVE_STRUCT;
2768 break;
2769 default:
2770 save_mode = SAVE_ONE;
2771 break;
2774 switch (save_mode) {
2775 case SAVE_ONE:
2776 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2777 if (enable_arguments) {
2778 s390_lgr (code, s390_r3, s390_r2);
2780 break;
2781 case SAVE_R4:
2782 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2783 if (enable_arguments) {
2784 s390_ldebr (code, s390_f0, s390_f0);
2786 break;
2787 case SAVE_R8:
2788 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2789 break;
2790 case SAVE_STRUCT:
2791 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2792 if (enable_arguments) {
2793 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2794 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2796 break;
2797 case SAVE_NONE:
2798 default:
2799 break;
2802 S390_SET (code, s390_r1, func);
2803 S390_SET (code, s390_r2, cfg->method);
2804 s390_basr (code, s390_r14, s390_r1);
2806 switch (save_mode) {
2807 case SAVE_ONE:
2808 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2809 break;
2810 case SAVE_R4:
2811 case SAVE_R8:
2812 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2813 break;
2814 case SAVE_STRUCT:
2815 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2816 break;
2817 case SAVE_NONE:
2818 default:
2819 break;
2822 return code;
2825 /*========================= End of Function ========================*/
2827 /*------------------------------------------------------------------*/
2828 /* */
2829 /* Name - compare_and_branch */
2830 /* */
2831 /* Function - Form a peephole pass at the code looking for */
2832 /* simple optimizations. */
2833 /* */
2834 /*------------------------------------------------------------------*/
2836 static void
2837 compare_and_branch(MonoBasicBlock *bb, MonoInst *ins, int cc, gboolean logical)
2839 MonoInst *last;
2841 if (mono_hwcap_s390x_has_gie) {
2842 last = mono_inst_prev (ins, FILTER_IL_SEQ_POINT);
2843 ins->sreg1 = last->sreg1;
2844 ins->sreg2 = last->sreg2;
2845 ins->sreg3 = cc;
2846 switch(last->opcode) {
2847 case OP_ICOMPARE:
2848 if (logical)
2849 ins->opcode = OP_S390_CLRJ;
2850 else
2851 ins->opcode = OP_S390_CRJ;
2852 MONO_DELETE_INS(bb, last);
2853 break;
2854 case OP_COMPARE:
2855 case OP_LCOMPARE:
2856 if (logical)
2857 ins->opcode = OP_S390_CLGRJ;
2858 else
2859 ins->opcode = OP_S390_CGRJ;
2860 MONO_DELETE_INS(bb, last);
2861 break;
2862 case OP_ICOMPARE_IMM:
2863 ins->backend.data = (gpointer) last->inst_imm;
2864 if (logical)
2865 ins->opcode = OP_S390_CLIJ;
2866 else
2867 ins->opcode = OP_S390_CIJ;
2868 MONO_DELETE_INS(bb, last);
2869 break;
2870 case OP_COMPARE_IMM:
2871 case OP_LCOMPARE_IMM:
2872 ins->backend.data = (gpointer) last->inst_imm;
2873 if (logical)
2874 ins->opcode = OP_S390_CLGIJ;
2875 else
2876 ins->opcode = OP_S390_CGIJ;
2877 MONO_DELETE_INS(bb, last);
2878 break;
2883 /*========================= End of Function ========================*/
2885 /*------------------------------------------------------------------*/
2886 /* */
2887 /* Name - mono_arch_peephole_pass_1 */
2888 /* */
2889 /* Function - Form a peephole pass at the code looking for */
2890 /* simple optimizations. */
2891 /* */
2892 /*------------------------------------------------------------------*/
2894 void
2895 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2897 MonoInst *ins, *n;
2899 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2900 switch (ins->opcode) {
2901 case OP_IBEQ:
2902 case OP_LBEQ:
2903 compare_and_branch(bb, ins, S390_CC_EQ, FALSE);
2904 break;
2905 case OP_LBNE_UN:
2906 case OP_IBNE_UN:
2907 compare_and_branch(bb, ins, S390_CC_NE, TRUE);
2908 break;
2909 case OP_LBLT:
2910 case OP_IBLT:
2911 compare_and_branch(bb, ins, S390_CC_LT, FALSE);
2912 break;
2913 case OP_LBLT_UN:
2914 case OP_IBLT_UN:
2915 compare_and_branch(bb, ins, S390_CC_LT, TRUE);
2916 break;
2917 case OP_LBGT:
2918 case OP_IBGT:
2919 compare_and_branch(bb, ins, S390_CC_GT, FALSE);
2920 break;
2921 case OP_LBGT_UN:
2922 case OP_IBGT_UN:
2923 compare_and_branch(bb, ins, S390_CC_GT, TRUE);
2924 break;
2925 case OP_LBGE:
2926 case OP_IBGE:
2927 compare_and_branch(bb, ins, S390_CC_GE, FALSE);
2928 break;
2929 case OP_LBGE_UN:
2930 case OP_IBGE_UN:
2931 compare_and_branch(bb, ins, S390_CC_GE, TRUE);
2932 break;
2933 case OP_LBLE:
2934 case OP_IBLE:
2935 compare_and_branch(bb, ins, S390_CC_LE, FALSE);
2936 break;
2937 case OP_LBLE_UN:
2938 case OP_IBLE_UN:
2939 compare_and_branch(bb, ins, S390_CC_LE, TRUE);
2940 break;
2942 // default:
2943 // mono_peephole_ins (bb, ins);
2948 /*========================= End of Function ========================*/
2950 /*------------------------------------------------------------------*/
2951 /* */
2952 /* Name - mono_arch_peephole_pass_2 */
2953 /* */
2954 /* Function - Form a peephole pass at the code looking for */
2955 /* simple optimizations. */
2956 /* */
2957 /*------------------------------------------------------------------*/
2959 void
2960 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2962 MonoInst *ins, *n, *last_ins = NULL;
2964 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2965 switch (ins->opcode) {
2966 case OP_LOADU4_MEMBASE:
2967 case OP_LOADI4_MEMBASE:
2968 if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG) &&
2969 ins->inst_basereg == last_ins->inst_destbasereg &&
2970 ins->inst_offset == last_ins->inst_offset) {
2971 ins->opcode = (ins->opcode == OP_LOADI4_MEMBASE) ? OP_ICONV_TO_I4 : OP_ICONV_TO_U4;
2972 ins->sreg1 = last_ins->sreg1;
2974 break;
2976 mono_peephole_ins (bb, ins);
2980 /*========================= End of Function ========================*/
2982 /*------------------------------------------------------------------*/
2983 /* */
2984 /* Name - mono_arch_lowering_pass. */
2985 /* */
2986 /*------------------------------------------------------------------*/
2988 void
2989 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2991 MonoInst *ins, *next;
2993 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2994 switch (ins->opcode) {
2995 case OP_DIV_IMM:
2996 case OP_REM_IMM:
2997 case OP_IDIV_IMM:
2998 case OP_IREM_IMM:
2999 case OP_IDIV_UN_IMM:
3000 case OP_IREM_UN_IMM:
3001 case OP_LAND_IMM:
3002 case OP_LOR_IMM:
3003 case OP_LREM_IMM:
3004 case OP_LXOR_IMM:
3005 case OP_LOCALLOC_IMM:
3006 mono_decompose_op_imm (cfg, bb, ins);
3007 break;
3008 case OP_LADD_IMM:
3009 if (!s390_is_imm16 (ins->inst_imm))
3010 /* This is created by the memcpy code which ignores is_inst_imm */
3011 mono_decompose_op_imm (cfg, bb, ins);
3012 break;
3013 default:
3014 break;
3018 bb->max_vreg = cfg->next_vreg;
3021 /*========================= End of Function ========================*/
3023 /*------------------------------------------------------------------*/
3024 /* */
3025 /* Name - emit_float_to_int */
3026 /* */
3027 /* Function - Create instructions which will convert a floating */
3028 /* point value to integer. */
3029 /* */
3030 /*------------------------------------------------------------------*/
3032 static guchar*
3033 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
3035 /* sreg is a float, dreg is an integer reg. */
3036 if (is_signed) {
3037 s390_cgebr (code, dreg, 5, sreg);
3038 switch (size) {
3039 case 1:
3040 s390_ltgr (code, dreg, dreg);
3041 s390_jnl (code, 4);
3042 s390_oill (code, dreg, 0x80);
3043 s390_lghi (code, s390_r0, 0xff);
3044 s390_ngr (code, dreg, s390_r0);
3045 break;
3046 case 2:
3047 s390_ltgr (code, dreg, dreg);
3048 s390_jnl (code, 4);
3049 s390_oill (code, dreg, 0x8000);
3050 s390_llill(code, s390_r0, 0xffff);
3051 s390_ngr (code, dreg, s390_r0);
3052 break;
3054 } else {
3055 short *o[1];
3056 S390_SET (code, s390_r13, 0x4f000000u);
3057 s390_ldgr (code, s390_f14, s390_r13);
3058 s390_ler (code, s390_f15, sreg);
3059 s390_cebr (code, s390_f15, s390_f14);
3060 s390_jl (code, 0); CODEPTR (code, o[0]);
3061 S390_SET (code, s390_r13, 0x4f800000u);
3062 s390_ldgr (code, s390_f14, s390_r13);
3063 s390_sebr (code, s390_f15, s390_f14);
3064 s390_cfebr (code, dreg, 7, s390_f15);
3065 s390_j (code, 4);
3066 PTRSLOT (code, o[0]);
3067 s390_cfebr (code, dreg, 5, sreg);
3068 switch (size) {
3069 case 1:
3070 s390_lghi (code, s390_r0, 0xff);
3071 s390_ngr (code, dreg, s390_r0);
3072 break;
3073 case 2:
3074 s390_llill(code, s390_r0, 0xffff);
3075 s390_ngr (code, dreg, s390_r0);
3076 break;
3079 return code;
3082 /*========================= End of Function ========================*/
3084 /*------------------------------------------------------------------*/
3085 /* */
3086 /* Name - emit_double_to_int */
3087 /* */
3088 /* Function - Create instructions which will convert a floating */
3089 /* point value to integer. */
3090 /* */
3091 /*------------------------------------------------------------------*/
3093 static guchar*
3094 emit_double_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
3096 /* sreg is a float, dreg is an integer reg. */
3097 if (is_signed) {
3098 s390_cgdbr (code, dreg, 5, sreg);
3099 switch (size) {
3100 case 1:
3101 s390_ltgr (code, dreg, dreg);
3102 s390_jnl (code, 4);
3103 s390_oill (code, dreg, 0x80);
3104 s390_lghi (code, s390_r0, 0xff);
3105 s390_ngr (code, dreg, s390_r0);
3106 break;
3107 case 2:
3108 s390_ltgr (code, dreg, dreg);
3109 s390_jnl (code, 4);
3110 s390_oill (code, dreg, 0x8000);
3111 s390_llill(code, s390_r0, 0xffff);
3112 s390_ngr (code, dreg, s390_r0);
3113 break;
3115 } else {
3116 short *o[1];
3117 S390_SET (code, s390_r13, 0x41e0000000000000llu);
3118 s390_ldgr (code, s390_f14, s390_r13);
3119 s390_ldr (code, s390_f15, sreg);
3120 s390_cdbr (code, s390_f15, s390_f14);
3121 s390_jl (code, 0); CODEPTR (code, o[0]);
3122 S390_SET (code, s390_r13, 0x41f0000000000000llu);
3123 s390_ldgr (code, s390_f14, s390_r13);
3124 s390_sdbr (code, s390_f15, s390_f14);
3125 s390_cfdbr (code, dreg, 7, s390_f15);
3126 s390_j (code, 4);
3127 PTRSLOT (code, o[0]);
3128 s390_cfdbr (code, dreg, 5, sreg);
3129 switch (size) {
3130 case 1:
3131 s390_lghi (code, s390_r0, 0xff);
3132 s390_ngr (code, dreg, s390_r0);
3133 break;
3134 case 2:
3135 s390_llill(code, s390_r0, 0xffff);
3136 s390_ngr (code, dreg, s390_r0);
3137 break;
3140 return code;
3143 /*========================= End of Function ========================*/
3145 /*------------------------------------------------------------------*/
3146 /* */
3147 /* Name - is_unsigned. */
3148 /* */
3149 /* Function - Return TRUE if next opcode is checking for un- */
3150 /* signed value. */
3151 /* */
3152 /*------------------------------------------------------------------*/
3154 static gboolean
3155 is_unsigned (MonoInst *next)
3157 if ((next) &&
3158 (((next->opcode >= OP_IBNE_UN) &&
3159 (next->opcode <= OP_IBLT_UN)) ||
3160 ((next->opcode >= OP_LBNE_UN) &&
3161 (next->opcode <= OP_LBLT_UN)) ||
3162 ((next->opcode >= OP_COND_EXC_NE_UN) &&
3163 (next->opcode <= OP_COND_EXC_LT_UN)) ||
3164 ((next->opcode >= OP_COND_EXC_INE_UN) &&
3165 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
3166 ((next->opcode == OP_CLT_UN) ||
3167 (next->opcode == OP_CGT_UN) ||
3168 (next->opcode == OP_ICGE_UN) ||
3169 (next->opcode == OP_ICLE_UN)) ||
3170 ((next->opcode == OP_ICLT_UN) ||
3171 (next->opcode == OP_ICGT_UN) ||
3172 (next->opcode == OP_LCLT_UN) ||
3173 (next->opcode == OP_LCGT_UN))))
3174 return TRUE;
3175 else
3176 return FALSE;
3179 /*========================= End of Function ========================*/
3181 /*------------------------------------------------------------------*/
3182 /* */
3183 /* Name - mono_arch_output_basic_block */
3184 /* */
3185 /* Function - Perform the "real" work of emitting instructions */
3186 /* that will do the work of in the basic block. */
3187 /* */
3188 /*------------------------------------------------------------------*/
3190 void
3191 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
3193 MonoInst *ins;
3194 MonoCallInst *call;
3195 guint8 *code = cfg->native_code + cfg->code_len;
3196 int src2;
3198 /* we don't align basic blocks of loops on s390 */
3200 if (cfg->verbose_level > 2)
3201 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3203 MONO_BB_FOR_EACH_INS (bb, ins) {
3204 const guint offset = code - cfg->native_code;
3205 set_code_cursor (cfg, code);
3206 int max_len = ins_get_size (ins->opcode);
3207 code = realloc_code (cfg, max_len);
3209 mono_debug_record_line_number (cfg, ins, offset);
3211 switch (ins->opcode) {
3212 case OP_STOREI1_MEMBASE_IMM: {
3213 s390_lghi (code, s390_r0, ins->inst_imm);
3214 S390_LONG (code, stcy, stc, s390_r0, 0,
3215 ins->inst_destbasereg, ins->inst_offset);
3217 break;
3218 case OP_STOREI2_MEMBASE_IMM: {
3219 s390_lghi (code, s390_r0, ins->inst_imm);
3220 S390_LONG (code, sthy, sth, s390_r0, 0,
3221 ins->inst_destbasereg, ins->inst_offset);
3223 break;
3224 case OP_STOREI4_MEMBASE_IMM: {
3225 s390_lgfi (code, s390_r0, ins->inst_imm);
3226 S390_LONG (code, sty, st, s390_r0, 0,
3227 ins->inst_destbasereg, ins->inst_offset);
3229 break;
3230 case OP_STORE_MEMBASE_IMM:
3231 case OP_STOREI8_MEMBASE_IMM: {
3232 S390_SET (code, s390_r0, ins->inst_imm);
3233 S390_LONG (code, stg, stg, s390_r0, 0,
3234 ins->inst_destbasereg, ins->inst_offset);
3236 break;
3237 case OP_STOREI1_MEMBASE_REG: {
3238 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3239 ins->inst_destbasereg, ins->inst_offset);
3241 break;
3242 case OP_STOREI2_MEMBASE_REG: {
3243 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3244 ins->inst_destbasereg, ins->inst_offset);
3246 break;
3247 case OP_STOREI4_MEMBASE_REG: {
3248 S390_LONG (code, sty, st, ins->sreg1, 0,
3249 ins->inst_destbasereg, ins->inst_offset);
3251 break;
3252 case OP_STORE_MEMBASE_REG:
3253 case OP_STOREI8_MEMBASE_REG: {
3254 S390_LONG (code, stg, stg, ins->sreg1, 0,
3255 ins->inst_destbasereg, ins->inst_offset);
3257 break;
3258 case OP_LOADU4_MEM:
3259 g_assert_not_reached ();
3260 break;
3261 case OP_LOAD_MEMBASE:
3262 case OP_LOADI8_MEMBASE: {
3263 S390_LONG (code, lg, lg, ins->dreg, 0,
3264 ins->inst_basereg, ins->inst_offset);
3266 break;
3267 case OP_LOADI4_MEMBASE: {
3268 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3269 ins->inst_basereg, ins->inst_offset);
3271 break;
3272 case OP_LOADU4_MEMBASE: {
3273 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3274 ins->inst_basereg, ins->inst_offset);
3276 break;
3277 case OP_LOADU1_MEMBASE: {
3278 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3279 ins->inst_basereg, ins->inst_offset);
3281 break;
3282 case OP_LOADI1_MEMBASE: {
3283 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3284 ins->inst_basereg, ins->inst_offset);
3286 break;
3287 case OP_LOADU2_MEMBASE: {
3288 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3289 ins->inst_basereg, ins->inst_offset);
3291 break;
3292 case OP_LOADI2_MEMBASE: {
3293 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3294 ins->inst_basereg, ins->inst_offset);
3296 break;
3297 case OP_LCONV_TO_I1: {
3298 s390_lgbr (code, ins->dreg, ins->sreg1);
3300 break;
3301 case OP_LCONV_TO_I2: {
3302 s390_lghr (code, ins->dreg, ins->sreg1);
3304 break;
3305 case OP_LCONV_TO_U1: {
3306 s390_llgcr (code, ins->dreg, ins->sreg1);
3308 break;
3309 case OP_LCONV_TO_U2: {
3310 s390_llghr (code, ins->dreg, ins->sreg1);
3312 break;
3313 case OP_ICONV_TO_I1: {
3314 s390_lgbr (code, ins->dreg, ins->sreg1);
3316 break;
3317 case OP_ICONV_TO_I2: {
3318 s390_lghr (code, ins->dreg, ins->sreg1);
3320 break;
3321 case OP_ICONV_TO_U1: {
3322 s390_llgcr (code, ins->dreg, ins->sreg1);
3324 break;
3325 case OP_ICONV_TO_U2: {
3326 s390_llghr (code, ins->dreg, ins->sreg1);
3328 break;
3329 case OP_ICONV_TO_U4: {
3330 s390_llgfr (code, ins->dreg, ins->sreg1);
3332 break;
3333 case OP_ICONV_TO_I4: {
3334 s390_lgfr (code, ins->dreg, ins->sreg1);
3336 break;
3337 case OP_COMPARE:
3338 case OP_LCOMPARE: {
3339 if (is_unsigned (ins->next))
3340 s390_clgr (code, ins->sreg1, ins->sreg2);
3341 else
3342 s390_cgr (code, ins->sreg1, ins->sreg2);
3344 break;
3345 case OP_ICOMPARE: {
3346 if (is_unsigned (ins->next))
3347 s390_clr (code, ins->sreg1, ins->sreg2);
3348 else
3349 s390_cr (code, ins->sreg1, ins->sreg2);
3351 break;
3352 case OP_COMPARE_IMM:
3353 case OP_LCOMPARE_IMM: {
3354 gboolean branchUn = is_unsigned (ins->next);
3355 if ((ins->inst_imm == 0) && (!branchUn)) {
3356 s390_ltgr (code, ins->sreg1, ins->sreg1);
3357 } else {
3358 S390_SET (code, s390_r0, ins->inst_imm);
3359 if (branchUn)
3360 s390_clgr (code, ins->sreg1, s390_r0);
3361 else
3362 s390_cgr (code, ins->sreg1, s390_r0);
3365 break;
3366 case OP_ICOMPARE_IMM: {
3367 gboolean branchUn = is_unsigned (ins->next);
3368 if ((ins->inst_imm == 0) && (!branchUn)) {
3369 s390_ltr (code, ins->sreg1, ins->sreg1);
3370 } else {
3371 S390_SET (code, s390_r0, ins->inst_imm);
3372 if (branchUn)
3373 s390_clr (code, ins->sreg1, s390_r0);
3374 else
3375 s390_cr (code, ins->sreg1, s390_r0);
3378 break;
3379 case OP_BREAK: {
3380 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3381 mono_break);
3382 S390_CALL_TEMPLATE (code, s390_r14);
3384 break;
3385 case OP_ADDCC: {
3386 if (mono_hwcap_s390x_has_mlt) {
3387 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3388 } else {
3389 CHECK_SRCDST_COM;
3390 s390_agr (code, ins->dreg, src2);
3393 break;
3394 case OP_LADD: {
3395 if (mono_hwcap_s390x_has_mlt) {
3396 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3397 } else {
3398 CHECK_SRCDST_COM;
3399 s390_agr (code, ins->dreg, src2);
3402 break;
3403 case OP_ADC: {
3404 CHECK_SRCDST_COM;
3405 s390_alcgr (code, ins->dreg, src2);
3407 break;
3408 case OP_ADD_IMM: {
3409 if (mono_hwcap_s390x_has_mlt) {
3410 if (s390_is_imm16 (ins->inst_imm)) {
3411 s390_aghik(code, ins->dreg, ins->sreg1, ins->inst_imm);
3412 } else {
3413 S390_SET (code, s390_r0, ins->inst_imm);
3414 s390_agrk (code, ins->dreg, ins->sreg1, s390_r0);
3416 } else {
3417 if (ins->dreg != ins->sreg1) {
3418 s390_lgr (code, ins->dreg, ins->sreg1);
3420 if (s390_is_imm16 (ins->inst_imm)) {
3421 s390_aghi (code, ins->dreg, ins->inst_imm);
3422 } else if (s390_is_imm32 (ins->inst_imm)) {
3423 s390_agfi (code, ins->dreg, ins->inst_imm);
3424 } else {
3425 S390_SET (code, s390_r0, ins->inst_imm);
3426 s390_agr (code, ins->dreg, s390_r0);
3430 break;
3431 case OP_LADD_IMM: {
3432 if (ins->dreg != ins->sreg1) {
3433 s390_lgr (code, ins->dreg, ins->sreg1);
3435 if (s390_is_imm32 (ins->inst_imm)) {
3436 s390_agfi (code, ins->dreg, ins->inst_imm);
3437 } else {
3438 S390_SET (code, s390_r0, ins->inst_imm);
3439 s390_agr (code, ins->dreg, s390_r0);
3442 break;
3443 case OP_ADC_IMM: {
3444 if (ins->dreg != ins->sreg1) {
3445 s390_lgr (code, ins->dreg, ins->sreg1);
3447 if (s390_is_imm16 (ins->inst_imm)) {
3448 s390_lghi (code, s390_r0, ins->inst_imm);
3449 s390_alcgr (code, ins->dreg, s390_r0);
3450 } else {
3451 S390_SET (code, s390_r0, ins->inst_imm);
3452 s390_alcgr (code, ins->dreg, s390_r0);
3455 break;
3456 case OP_IADD_OVF:
3457 case OP_S390_IADD_OVF: {
3458 CHECK_SRCDST_COM;
3459 s390_ar (code, ins->dreg, src2);
3460 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3461 s390_lgfr (code, ins->dreg, ins->dreg);
3463 break;
3464 case OP_IADD_OVF_UN:
3465 case OP_S390_IADD_OVF_UN: {
3466 CHECK_SRCDST_COM;
3467 s390_algr (code, ins->dreg, src2);
3468 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3469 s390_llgfr (code, ins->dreg, ins->dreg);
3471 break;
3472 case OP_ADD_OVF_CARRY: {
3473 CHECK_SRCDST_COM;
3474 s390_lghi (code, s390_r0, 0);
3475 s390_lgr (code, s390_r1, s390_r0);
3476 s390_alcgr (code, s390_r0, s390_r1);
3477 s390_agr (code, ins->dreg, src2);
3478 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3479 s390_agr (code, ins->dreg, s390_r0);
3480 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3482 break;
3483 case OP_ADD_OVF_UN_CARRY: {
3484 CHECK_SRCDST_COM;
3485 s390_alcgr (code, ins->dreg, src2);
3486 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3488 break;
3489 case OP_SUBCC: {
3490 if (mono_hwcap_s390x_has_mlt) {
3491 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3492 } else {
3493 CHECK_SRCDST_NCOM;
3494 s390_sgr (code, ins->dreg, src2);
3497 break;
3498 case OP_LSUB: {
3499 if (mono_hwcap_s390x_has_mlt) {
3500 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3501 } else {
3502 CHECK_SRCDST_NCOM;
3503 s390_sgr (code, ins->dreg, src2);
3506 break;
3507 case OP_SBB: {
3508 CHECK_SRCDST_NCOM;
3509 s390_slbgr(code, ins->dreg, src2);
3511 break;
3512 case OP_SUB_IMM: {
3513 if (ins->dreg != ins->sreg1) {
3514 s390_lgr (code, ins->dreg, ins->sreg1);
3516 if (s390_is_imm16 (-ins->inst_imm)) {
3517 s390_aghi (code, ins->dreg, -ins->inst_imm);
3518 } else if (s390_is_imm32 (-ins->inst_imm)) {
3519 s390_slgfi (code, ins->dreg, ins->inst_imm);
3520 } else {
3521 S390_SET (code, s390_r0, ins->inst_imm);
3522 s390_slgr (code, ins->dreg, s390_r0);
3525 break;
3526 case OP_LSUB_IMM: {
3527 if (ins->dreg != ins->sreg1) {
3528 s390_lgr (code, ins->dreg, ins->sreg1);
3530 if (s390_is_imm16 (-ins->inst_imm)) {
3531 s390_aghi (code, ins->dreg, -ins->inst_imm);
3532 } else if (s390_is_imm32 (-ins->inst_imm)) {
3533 s390_slgfi (code, ins->dreg, ins->inst_imm);
3534 } else {
3535 S390_SET (code, s390_r0, ins->inst_imm);
3536 s390_slgr (code, ins->dreg, s390_r0);
3539 break;
3540 case OP_SBB_IMM: {
3541 if (ins->dreg != ins->sreg1) {
3542 s390_lgr (code, ins->dreg, ins->sreg1);
3544 if (s390_is_imm16 (-ins->inst_imm)) {
3545 s390_lghi (code, s390_r0, ins->inst_imm);
3546 s390_slbgr (code, ins->dreg, s390_r0);
3547 } else {
3548 S390_SET (code, s390_r0, ins->inst_imm);
3549 s390_slbgr(code, ins->dreg, s390_r0);
3552 break;
3553 case OP_SUB_OVF_CARRY: {
3554 CHECK_SRCDST_NCOM;
3555 s390_lghi (code, s390_r0, 0);
3556 s390_lgr (code, s390_r1, s390_r0);
3557 s390_slbgr (code, s390_r0, s390_r1);
3558 s390_sgr (code, ins->dreg, src2);
3559 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3560 s390_agr (code, ins->dreg, s390_r0);
3561 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3563 break;
3564 case OP_SUB_OVF_UN_CARRY: {
3565 CHECK_SRCDST_NCOM;
3566 s390_slbgr (code, ins->dreg, src2);
3567 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3569 break;
3570 case OP_LAND: {
3571 if (mono_hwcap_s390x_has_mlt) {
3572 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3573 } else {
3574 if (ins->sreg1 == ins->dreg) {
3575 s390_ngr (code, ins->dreg, ins->sreg2);
3576 } else {
3577 if (ins->sreg2 == ins->dreg) {
3578 s390_ngr (code, ins->dreg, ins->sreg1);
3579 } else {
3580 s390_lgr (code, ins->dreg, ins->sreg1);
3581 s390_ngr (code, ins->dreg, ins->sreg2);
3586 break;
3587 case OP_AND_IMM: {
3588 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3589 if (mono_hwcap_s390x_has_mlt) {
3590 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3591 } else {
3592 if (ins->dreg != ins->sreg1) {
3593 s390_lgr (code, ins->dreg, ins->sreg1);
3595 s390_ngr (code, ins->dreg, s390_r0);
3598 break;
3599 case OP_LDIV: {
3600 s390_lgr (code, s390_r1, ins->sreg1);
3601 s390_dsgr (code, s390_r0, ins->sreg2);
3602 s390_lgr (code, ins->dreg, s390_r1);
3604 break;
3605 case OP_LDIV_UN: {
3606 s390_lgr (code, s390_r1, ins->sreg1);
3607 s390_lghi (code, s390_r0, 0);
3608 s390_dlgr (code, s390_r0, ins->sreg2);
3609 s390_lgr (code, ins->dreg, s390_r1);
3611 break;
3612 case OP_LREM: {
3613 s390_lgr (code, s390_r1, ins->sreg1);
3614 s390_dsgr (code, s390_r0, ins->sreg2);
3615 s390_lgr (code, ins->dreg, s390_r0);
3616 break;
3618 case OP_LREM_IMM: {
3619 if (s390_is_imm16 (ins->inst_imm)) {
3620 s390_lghi (code, s390_r13, ins->inst_imm);
3621 } else {
3622 s390_lgfi (code, s390_r13, ins->inst_imm);
3624 s390_lgr (code, s390_r0, ins->sreg1);
3625 s390_dsgr (code, s390_r0, s390_r13);
3626 s390_lgfr (code, ins->dreg, s390_r0);
3628 break;
3629 case OP_LREM_UN: {
3630 s390_lgr (code, s390_r1, ins->sreg1);
3631 s390_lghi (code, s390_r0, 0);
3632 s390_dlgr (code, s390_r0, ins->sreg2);
3633 s390_lgr (code, ins->dreg, s390_r0);
3635 break;
3636 case OP_LOR: {
3637 if (mono_hwcap_s390x_has_mlt) {
3638 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3639 } else {
3640 if (ins->sreg1 == ins->dreg) {
3641 s390_ogr (code, ins->dreg, ins->sreg2);
3642 } else {
3643 if (ins->sreg2 == ins->dreg) {
3644 s390_ogr (code, ins->dreg, ins->sreg1);
3645 } else {
3646 s390_lgr (code, ins->dreg, ins->sreg1);
3647 s390_ogr (code, ins->dreg, ins->sreg2);
3652 break;
3653 case OP_OR_IMM: {
3654 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3655 if (mono_hwcap_s390x_has_mlt) {
3656 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3657 } else {
3658 if (ins->dreg != ins->sreg1) {
3659 s390_lgr (code, ins->dreg, ins->sreg1);
3661 s390_ogr (code, ins->dreg, s390_r0);
3664 break;
3665 case OP_LXOR: {
3666 if (mono_hwcap_s390x_has_mlt) {
3667 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3668 } else {
3669 if (ins->sreg1 == ins->dreg) {
3670 s390_xgr (code, ins->dreg, ins->sreg2);
3672 else {
3673 if (ins->sreg2 == ins->dreg) {
3674 s390_xgr (code, ins->dreg, ins->sreg1);
3676 else {
3677 s390_lgr (code, ins->dreg, ins->sreg1);
3678 s390_xgr (code, ins->dreg, ins->sreg2);
3683 break;
3684 case OP_XOR_IMM: {
3685 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3686 if (mono_hwcap_s390x_has_mlt) {
3687 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3688 } else {
3689 if (ins->dreg != ins->sreg1) {
3690 s390_lgr (code, ins->dreg, ins->sreg1);
3692 s390_xgr (code, ins->dreg, s390_r0);
3695 break;
3696 case OP_LSHL: {
3697 CHECK_SRCDST_NCOM;
3698 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3700 break;
3701 case OP_SHL_IMM:
3702 case OP_LSHL_IMM: {
3703 if (ins->sreg1 != ins->dreg) {
3704 s390_lgr (code, ins->dreg, ins->sreg1);
3706 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3708 break;
3709 case OP_LSHR: {
3710 CHECK_SRCDST_NCOM;
3711 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3713 break;
3714 case OP_SHR_IMM:
3715 case OP_LSHR_IMM: {
3716 if (ins->sreg1 != ins->dreg) {
3717 s390_lgr (code, ins->dreg, ins->sreg1);
3719 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3721 break;
3722 case OP_SHR_UN_IMM:
3723 case OP_LSHR_UN_IMM: {
3724 if (ins->sreg1 != ins->dreg) {
3725 s390_lgr (code, ins->dreg, ins->sreg1);
3727 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3729 break;
3730 case OP_LSHR_UN: {
3731 CHECK_SRCDST_NCOM;
3732 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3734 break;
3735 case OP_LNOT: {
3736 if (ins->sreg1 != ins->dreg) {
3737 s390_lgr (code, ins->dreg, ins->sreg1);
3739 s390_lghi (code, s390_r0, -1);
3740 s390_xgr (code, ins->dreg, s390_r0);
3742 break;
3743 case OP_LNEG: {
3744 s390_lcgr (code, ins->dreg, ins->sreg1);
3746 break;
3747 case OP_LMUL: {
3748 CHECK_SRCDST_COM;
3749 s390_msgr (code, ins->dreg, src2);
3751 break;
3752 case OP_MUL_IMM:
3753 case OP_LMUL_IMM: {
3754 if (ins->dreg != ins->sreg1) {
3755 s390_lgr (code, ins->dreg, ins->sreg1);
3757 if ((mono_hwcap_s390x_has_gie) &&
3758 (s390_is_imm32 (ins->inst_imm))) {
3759 s390_msgfi (code, ins->dreg, ins->inst_imm);
3760 } else {
3761 if (s390_is_imm16 (ins->inst_imm)) {
3762 s390_lghi (code, s390_r13, ins->inst_imm);
3763 } else if (s390_is_imm32 (ins->inst_imm)) {
3764 s390_lgfi (code, s390_r13, ins->inst_imm);
3765 } else {
3766 S390_SET (code, s390_r13, ins->inst_imm);
3768 s390_msgr (code, ins->dreg, s390_r13);
3771 break;
3772 case OP_LMUL_OVF: {
3773 short int *o[2];
3774 if (mono_hwcap_s390x_has_mie2) {
3775 s390_msgrkc (code, ins->dreg, ins->sreg1, ins->sreg2);
3776 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3777 } else {
3778 s390_ltgr (code, s390_r1, ins->sreg1);
3779 s390_jz (code, 0); CODEPTR(code, o[0]);
3780 s390_ltgr (code, s390_r0, ins->sreg2);
3781 s390_jnz (code, 6);
3782 s390_lghi (code, s390_r1, 0);
3783 s390_j (code, 0); CODEPTR(code, o[1]);
3784 s390_xgr (code, s390_r0, s390_r1);
3785 s390_msgr (code, s390_r1, ins->sreg2);
3786 s390_xgr (code, s390_r0, s390_r1);
3787 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3788 s390_ltgr (code, s390_r0, s390_r0);
3789 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3790 PTRSLOT (code, o[0]);
3791 PTRSLOT (code, o[1]);
3792 s390_lgr (code, ins->dreg, s390_r1);
3795 break;
3796 case OP_LMUL_OVF_UN: {
3797 s390_lghi (code, s390_r0, 0);
3798 s390_lgr (code, s390_r1, ins->sreg1);
3799 s390_mlgr (code, s390_r0, ins->sreg2);
3800 s390_ltgr (code, s390_r0, s390_r0);
3801 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3802 s390_lgr (code, ins->dreg, s390_r1);
3804 break;
3805 case OP_IADDCC: {
3806 g_assert_not_reached ();
3807 CHECK_SRCDST_COM_I;
3808 s390_algr (code, ins->dreg, src2);
3810 break;
3811 case OP_IADD: {
3812 CHECK_SRCDST_COM_I;
3813 s390_agr (code, ins->dreg, src2);
3815 break;
3816 case OP_IADC: {
3817 g_assert_not_reached ();
3818 CHECK_SRCDST_COM_I;
3819 s390_alcgr (code, ins->dreg, src2);
3821 break;
3822 case OP_IADD_IMM: {
3823 if (ins->dreg != ins->sreg1) {
3824 s390_lgfr (code, ins->dreg, ins->sreg1);
3826 if (s390_is_imm16 (ins->inst_imm)) {
3827 s390_aghi (code, ins->dreg, ins->inst_imm);
3828 } else {
3829 s390_afi (code, ins->dreg, ins->inst_imm);
3832 break;
3833 case OP_IADC_IMM: {
3834 if (ins->dreg != ins->sreg1) {
3835 s390_lgfr (code, ins->dreg, ins->sreg1);
3837 if (s390_is_imm16 (ins->inst_imm)) {
3838 s390_lghi (code, s390_r0, ins->inst_imm);
3839 s390_alcgr (code, ins->dreg, s390_r0);
3840 } else {
3841 S390_SET (code, s390_r0, ins->inst_imm);
3842 s390_alcgr (code, ins->dreg, s390_r0);
3845 break;
3846 case OP_LADD_OVF:
3847 case OP_S390_LADD_OVF: {
3848 if (mono_hwcap_s390x_has_mlt) {
3849 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3850 } else {
3851 CHECK_SRCDST_COM;
3852 s390_agr (code, ins->dreg, src2);
3854 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3856 break;
3857 case OP_LADD_OVF_UN:
3858 case OP_S390_LADD_OVF_UN: {
3859 if (mono_hwcap_s390x_has_mlt) {
3860 s390_algrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3861 } else {
3862 CHECK_SRCDST_COM;
3863 s390_algr (code, ins->dreg, src2);
3865 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3867 break;
3868 case OP_ISUBCC: {
3869 if (mono_hwcap_s390x_has_mlt) {
3870 s390_slgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3871 } else {
3872 CHECK_SRCDST_NCOM_I;
3873 s390_slgr (code, ins->dreg, src2);
3876 break;
3877 case OP_ISUB: {
3878 if (mono_hwcap_s390x_has_mlt) {
3879 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3880 } else {
3881 CHECK_SRCDST_NCOM_I;
3882 s390_sgr (code, ins->dreg, src2);
3885 break;
3886 case OP_ISBB: {
3887 CHECK_SRCDST_NCOM_I;
3888 s390_slbgr (code, ins->dreg, src2);
3890 break;
3891 case OP_ISUB_IMM: {
3892 if (ins->dreg != ins->sreg1) {
3893 s390_lgfr (code, ins->dreg, ins->sreg1);
3895 if (s390_is_imm16 (-ins->inst_imm)) {
3896 s390_aghi (code, ins->dreg, -ins->inst_imm);
3897 } else {
3898 s390_agfi (code, ins->dreg, -ins->inst_imm);
3901 break;
3902 case OP_ISBB_IMM: {
3903 S390_SET (code, s390_r0, ins->inst_imm);
3904 s390_slgfr (code, ins->dreg, s390_r0);
3906 break;
3907 case OP_ISUB_OVF:
3908 case OP_S390_ISUB_OVF: {
3909 if (mono_hwcap_s390x_has_mlt) {
3910 s390_srk (code, ins->dreg, ins->sreg1, ins->sreg2);
3911 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3912 } else {
3913 CHECK_SRCDST_NCOM;
3914 s390_sr (code, ins->dreg, src2);
3915 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3916 s390_lgfr (code, ins->dreg, ins->dreg);
3919 break;
3920 case OP_ISUB_OVF_UN:
3921 case OP_S390_ISUB_OVF_UN: {
3922 if (mono_hwcap_s390x_has_mlt) {
3923 s390_slrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3924 } else {
3925 CHECK_SRCDST_NCOM;
3926 s390_slr (code, ins->dreg, src2);
3928 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3929 s390_llgfr(code, ins->dreg, ins->dreg);
3931 break;
3932 case OP_LSUB_OVF:
3933 case OP_S390_LSUB_OVF: {
3934 if (mono_hwcap_s390x_has_mlt) {
3935 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3936 } else {
3937 CHECK_SRCDST_NCOM;
3938 s390_sgr (code, ins->dreg, src2);
3940 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3942 break;
3943 case OP_LSUB_OVF_UN:
3944 case OP_S390_LSUB_OVF_UN: {
3945 CHECK_SRCDST_NCOM;
3946 s390_slgr (code, ins->dreg, src2);
3947 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3949 break;
3950 case OP_IAND: {
3951 if (mono_hwcap_s390x_has_mlt) {
3952 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3953 } else {
3954 CHECK_SRCDST_NCOM_I;
3955 s390_ngr (code, ins->dreg, src2);
3958 break;
3959 case OP_IAND_IMM: {
3960 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3961 if (mono_hwcap_s390x_has_mlt) {
3962 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3963 } else {
3964 if (ins->dreg != ins->sreg1) {
3965 s390_lgfr (code, ins->dreg, ins->sreg1);
3967 s390_ngr (code, ins->dreg, s390_r0);
3970 break;
3971 case OP_IDIV: {
3972 s390_lgfr (code, s390_r0, ins->sreg1);
3973 s390_srda (code, s390_r0, 0, 32);
3974 s390_dr (code, s390_r0, ins->sreg2);
3975 s390_lgfr (code, ins->dreg, s390_r1);
3977 break;
3978 case OP_IDIV_UN: {
3979 s390_lgfr (code, s390_r0, ins->sreg1);
3980 s390_srdl (code, s390_r0, 0, 32);
3981 s390_dlr (code, s390_r0, ins->sreg2);
3982 s390_lgfr (code, ins->dreg, s390_r1);
3984 break;
3985 case OP_IDIV_IMM: {
3986 if (s390_is_imm16 (ins->inst_imm)) {
3987 s390_lghi (code, s390_r13, ins->inst_imm);
3988 } else {
3989 s390_lgfi (code, s390_r13, ins->inst_imm);
3991 s390_lgfr (code, s390_r0, ins->sreg1);
3992 s390_srda (code, s390_r0, 0, 32);
3993 s390_dr (code, s390_r0, ins->sreg2);
3994 s390_lgfr (code, ins->dreg, s390_r1);
3996 break;
3997 case OP_IREM: {
3998 s390_lgfr (code, s390_r0, ins->sreg1);
3999 s390_srda (code, s390_r0, 0, 32);
4000 s390_dr (code, s390_r0, ins->sreg2);
4001 s390_lgfr (code, ins->dreg, s390_r0);
4002 break;
4003 case OP_IREM_UN:
4004 s390_lgfr (code, s390_r0, ins->sreg1);
4005 s390_srdl (code, s390_r0, 0, 32);
4006 s390_dlr (code, s390_r0, ins->sreg2);
4007 s390_lgfr (code, ins->dreg, s390_r0);
4009 break;
4010 case OP_IREM_IMM: {
4011 if (s390_is_imm16 (ins->inst_imm)) {
4012 s390_lghi (code, s390_r13, ins->inst_imm);
4013 } else {
4014 s390_lgfi (code, s390_r13, ins->inst_imm);
4016 s390_lgfr (code, s390_r0, ins->sreg1);
4017 s390_srda (code, s390_r0, 0, 32);
4018 s390_dr (code, s390_r0, ins->sreg2);
4019 s390_lgfr (code, ins->dreg, s390_r0);
4021 break;
4022 case OP_IOR: {
4023 if (mono_hwcap_s390x_has_mlt) {
4024 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
4025 } else {
4026 CHECK_SRCDST_COM_I;
4027 s390_ogr (code, ins->dreg, src2);
4030 break;
4031 case OP_IOR_IMM: {
4032 S390_SET_MASK (code, s390_r0, ins->inst_imm);
4033 if (mono_hwcap_s390x_has_mlt) {
4034 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
4035 } else {
4036 if (ins->dreg != ins->sreg1) {
4037 s390_lgfr (code, ins->dreg, ins->sreg1);
4039 s390_ogr (code, ins->dreg, s390_r0);
4042 break;
4043 case OP_IXOR: {
4044 if (mono_hwcap_s390x_has_mlt) {
4045 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
4046 } else {
4047 CHECK_SRCDST_COM_I;
4048 s390_xgr (code, ins->dreg, src2);
4051 break;
4052 case OP_IXOR_IMM: {
4053 S390_SET_MASK (code, s390_r0, ins->inst_imm);
4054 if (mono_hwcap_s390x_has_mlt) {
4055 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
4056 } else {
4057 if (ins->dreg != ins->sreg1) {
4058 s390_lgfr (code, ins->dreg, ins->sreg1);
4060 s390_xgr (code, ins->dreg, s390_r0);
4063 break;
4064 case OP_ISHL: {
4065 CHECK_SRCDST_NCOM;
4066 s390_sll (code, ins->dreg, src2, 0);
4068 break;
4069 case OP_ISHL_IMM: {
4070 if (ins->sreg1 != ins->dreg) {
4071 s390_lgfr (code, ins->dreg, ins->sreg1);
4073 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4075 break;
4076 case OP_ISHR: {
4077 CHECK_SRCDST_NCOM;
4078 s390_sra (code, ins->dreg, src2, 0);
4080 break;
4081 case OP_ISHR_IMM: {
4082 if (ins->sreg1 != ins->dreg) {
4083 s390_lgfr (code, ins->dreg, ins->sreg1);
4085 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4087 break;
4088 case OP_ISHR_UN_IMM: {
4089 if (ins->sreg1 != ins->dreg) {
4090 s390_lgfr (code, ins->dreg, ins->sreg1);
4092 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4094 break;
4095 case OP_ISHR_UN: {
4096 CHECK_SRCDST_NCOM;
4097 s390_srl (code, ins->dreg, src2, 0);
4099 break;
4100 case OP_INOT: {
4101 if (ins->sreg1 != ins->dreg) {
4102 s390_lgfr (code, ins->dreg, ins->sreg1);
4104 s390_lghi (code, s390_r0, -1);
4105 s390_xgr (code, ins->dreg, s390_r0);
4107 break;
4108 case OP_INEG: {
4109 s390_lcgr (code, ins->dreg, ins->sreg1);
4111 break;
4112 case OP_IMUL: {
4113 CHECK_SRCDST_COM_I;
4114 s390_msr (code, ins->dreg, src2);
4116 break;
4117 case OP_IMUL_IMM: {
4118 if (ins->dreg != ins->sreg1) {
4119 s390_lgfr (code, ins->dreg, ins->sreg1);
4121 if (s390_is_imm16 (ins->inst_imm)) {
4122 s390_lghi (code, s390_r0, ins->inst_imm);
4123 } else {
4124 s390_lgfi (code, s390_r0, ins->inst_imm);
4126 s390_msr (code, ins->dreg, s390_r0);
4128 break;
4129 case OP_IMUL_OVF: {
4130 short int *o[2];
4131 s390_ltr (code, s390_r1, ins->sreg1);
4132 s390_jz (code, 0); CODEPTR(code, o[0]);
4133 s390_ltr (code, s390_r0, ins->sreg2);
4134 s390_jnz (code, 6);
4135 s390_lhi (code, s390_r1, 0);
4136 s390_j (code, 0); CODEPTR(code, o[1]);
4137 s390_xr (code, s390_r0, s390_r1);
4138 s390_msr (code, s390_r1, ins->sreg2);
4139 s390_xr (code, s390_r0, s390_r1);
4140 s390_srl (code, s390_r0, 0, 31);
4141 s390_ltr (code, s390_r0, s390_r0);
4142 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4143 PTRSLOT (code, o[0]);
4144 PTRSLOT (code, o[1]);
4145 s390_lgfr (code, ins->dreg, s390_r1);
4147 break;
4148 case OP_IMUL_OVF_UN: {
4149 s390_lhi (code, s390_r0, 0);
4150 s390_lr (code, s390_r1, ins->sreg1);
4151 s390_mlr (code, s390_r0, ins->sreg2);
4152 s390_ltr (code, s390_r0, s390_r0);
4153 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4154 s390_lgfr (code, ins->dreg, s390_r1);
4156 break;
4157 case OP_ICONST:
4158 case OP_I8CONST: {
4159 S390_SET (code, ins->dreg, ins->inst_c0);
4161 break;
4162 case OP_AOTCONST: {
4163 mono_add_patch_info (cfg, code - cfg->native_code,
4164 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4165 S390_LOAD_TEMPLATE (code, ins->dreg);
4167 break;
4168 case OP_JUMP_TABLE: {
4169 mono_add_patch_info (cfg, code - cfg->native_code,
4170 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4171 S390_LOAD_TEMPLATE (code, ins->dreg);
4173 break;
4174 case OP_MOVE:
4175 if (ins->dreg != ins->sreg1) {
4176 s390_lgr (code, ins->dreg, ins->sreg1);
4178 break;
4179 case OP_LCONV_TO_I:
4180 case OP_LCONV_TO_I8:
4181 case OP_SEXT_I4:
4182 s390_lgfr (code, ins->dreg, ins->sreg1);
4183 break;
4184 case OP_LCONV_TO_I4:
4185 s390_lgfr (code, ins->dreg, ins->sreg1);
4186 break;
4187 case OP_LCONV_TO_U:
4188 case OP_LCONV_TO_U8:
4189 case OP_LCONV_TO_U4:
4190 case OP_ZEXT_I4:
4191 s390_llgfr (code, ins->dreg, ins->sreg1);
4192 break;
4193 case OP_LCONV_TO_OVF_U4:
4194 S390_SET (code, s390_r0, 4294967295);
4195 s390_clgr (code, ins->sreg1, s390_r0);
4196 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4197 s390_ltgr (code, ins->sreg1, ins->sreg1);
4198 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4199 s390_llgfr(code, ins->dreg, ins->sreg1);
4200 break;
4201 case OP_LCONV_TO_OVF_I4_UN:
4202 S390_SET (code, s390_r0, 2147483647);
4203 s390_cgr (code, ins->sreg1, s390_r0);
4204 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4205 s390_ltgr (code, ins->sreg1, ins->sreg1);
4206 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4207 s390_lgfr (code, ins->dreg, ins->sreg1);
4208 break;
4209 case OP_FMOVE:
4210 if (ins->dreg != ins->sreg1) {
4211 s390_ldr (code, ins->dreg, ins->sreg1);
4213 break;
4214 case OP_MOVE_F_TO_I8:
4215 s390_lgdr (code, ins->dreg, ins->sreg1);
4216 break;
4217 case OP_MOVE_I8_TO_F:
4218 s390_ldgr (code, ins->dreg, ins->sreg1);
4219 break;
4220 case OP_MOVE_F_TO_I4:
4221 s390_ledbr (code, s390_f0, ins->sreg1);
4222 s390_lgdr (code, ins->dreg, s390_f0);
4223 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
4224 break;
4225 case OP_MOVE_I4_TO_F:
4226 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
4227 s390_ldgr (code, ins->dreg, s390_r0);
4228 if (!cfg->r4fp)
4229 s390_ldebr (code, ins->dreg, ins->dreg);
4230 break;
4231 case OP_FCONV_TO_R4:
4232 s390_ledbr (code, ins->dreg, ins->sreg1);
4233 if (!cfg->r4fp)
4234 s390_ldebr (code, ins->dreg, ins->dreg);
4235 break;
4236 case OP_S390_SETF4RET:
4237 if (!cfg->r4fp)
4238 s390_ledbr (code, ins->dreg, ins->sreg1);
4239 break;
4240 case OP_TLS_GET: {
4241 if (s390_is_imm16 (ins->inst_offset)) {
4242 s390_lghi (code, s390_r13, ins->inst_offset);
4243 } else if (s390_is_imm32 (ins->inst_offset)) {
4244 s390_lgfi (code, s390_r13, ins->inst_offset);
4245 } else {
4246 S390_SET (code, s390_r13, ins->inst_offset);
4248 s390_ear (code, s390_r1, 0);
4249 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4250 s390_ear (code, s390_r1, 1);
4251 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
4253 break;
4254 case OP_TLS_SET: {
4255 if (s390_is_imm16 (ins->inst_offset)) {
4256 s390_lghi (code, s390_r13, ins->inst_offset);
4257 } else if (s390_is_imm32 (ins->inst_offset)) {
4258 s390_lgfi (code, s390_r13, ins->inst_offset);
4259 } else {
4260 S390_SET (code, s390_r13, ins->inst_offset);
4262 s390_ear (code, s390_r1, 0);
4263 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4264 s390_ear (code, s390_r1, 1);
4265 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
4267 break;
4268 case OP_TAILCALL :
4269 case OP_TAILCALL_MEMBASE : {
4270 MonoCallInst *call = (MonoCallInst *) ins;
4271 MonoMethod *method = call->method;
4272 MonoMethodSignature *sig = mono_method_signature(method);
4273 CallInfo *cinfo = get_call_info (NULL, sig);
4274 int32_t stackUsage = (cinfo->sz.stack_size - S390_MINIMAL_STACK_SIZE),
4275 stackOffset = S390_MINIMAL_STACK_SIZE;
4277 if (cfg->method->save_lmf)
4278 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4280 s390_lgr (code, s390_r12, cfg->frame_reg);
4281 code = backUpStackPtr(cfg, code);
4283 while (stackUsage > 256) {
4284 s390_mvc (code, 256, STK_BASE, stackOffset,
4285 s390_r12, stackOffset);
4286 stackUsage -= 256;
4287 stackOffset += 256;
4290 if (stackUsage > 0)
4291 s390_mvc (code, stackUsage, STK_BASE, stackOffset,
4292 s390_r12, stackOffset);
4294 s390_lmg (code, s390_r6, s390_r13, STK_BASE, S390_REG_SAVE_OFFSET);
4296 if (cfg->arch.used_fp_regs != 0) {
4297 int32_t fpOffset = sizeof(double);
4298 for (int i=8; i<16; i++) {
4299 if (cfg->arch.used_fp_regs & (1 << i)) {
4300 s390_ld (code, i, cfg->arch.fpSize, STK_BASE, fpOffset);
4301 fpOffset += sizeof(double);
4306 s390_lg (code, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET);
4307 if (ins->opcode == OP_TAILCALL_MEMBASE) {
4308 if (mono_hwcap_s390x_has_mie2) {
4309 s390_bi (code, 0, ins->sreg1, ins->inst_offset);
4310 } else {
4311 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4312 s390_br (code, s390_r1);
4314 } else {
4315 mono_add_patch_info (cfg, code - cfg->native_code,
4316 MONO_PATCH_INFO_METHOD_JUMP,
4317 call->method);
4318 s390_jcl (code, S390_CC_UN, 0);
4321 if (mono_jit_trace_calls != NULL && mono_trace_eval(cfg->method))
4322 indent_level--;
4324 g_free (cinfo);
4326 break;
4327 case OP_CHECK_THIS: {
4328 /* ensure ins->sreg1 is not NULL */
4329 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
4330 s390_ltgr (code, s390_r0, s390_r0);
4331 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4333 break;
4334 case OP_ARGLIST: {
4335 const int offset = cfg->sig_cookie + cfg->stack_usage;
4337 if (s390_is_imm16 (offset)) {
4338 s390_lghi (code, s390_r0, offset);
4339 } else if (s390_is_imm32 (offset)) {
4340 s390_lgfi (code, s390_r0, offset);
4341 } else {
4342 S390_SET (code, s390_r0, offset);
4344 s390_agr (code, s390_r0, cfg->frame_reg);
4345 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
4347 break;
4348 case OP_FCALL: {
4349 call = (MonoCallInst*)ins;
4350 if (ins->flags & MONO_INST_HAS_METHOD)
4351 mono_add_patch_info (cfg, code-cfg->native_code,
4352 MONO_PATCH_INFO_METHOD,
4353 call->method);
4354 else
4355 mono_add_patch_info (cfg, code-cfg->native_code,
4356 MONO_PATCH_INFO_ABS,
4357 call->fptr);
4358 S390_CALL_TEMPLATE (code, s390_r14);
4359 if (!cfg->r4fp && call->signature->ret->type == MONO_TYPE_R4)
4360 s390_ldebr (code, s390_f0, s390_f0);
4362 break;
4363 case OP_LCALL:
4364 case OP_VCALL:
4365 case OP_VCALL2:
4366 case OP_VOIDCALL:
4367 case OP_RCALL:
4368 case OP_CALL: {
4369 call = (MonoCallInst*)ins;
4370 if (ins->flags & MONO_INST_HAS_METHOD)
4371 mono_add_patch_info (cfg, code-cfg->native_code,
4372 MONO_PATCH_INFO_METHOD,
4373 call->method);
4374 else
4375 mono_add_patch_info (cfg, code-cfg->native_code,
4376 MONO_PATCH_INFO_ABS,
4377 call->fptr);
4378 S390_CALL_TEMPLATE (code, s390_r14);
4380 break;
4381 case OP_FCALL_REG: {
4382 call = (MonoCallInst*)ins;
4383 s390_lgr (code, s390_r1, ins->sreg1);
4384 s390_basr (code, s390_r14, s390_r1);
4385 if (!cfg->r4fp && call->signature->ret->type == MONO_TYPE_R4)
4386 s390_ldebr (code, s390_f0, s390_f0);
4388 break;
4389 case OP_LCALL_REG:
4390 case OP_VCALL_REG:
4391 case OP_VCALL2_REG:
4392 case OP_VOIDCALL_REG:
4393 case OP_RCALL_REG:
4394 case OP_CALL_REG: {
4395 s390_lgr (code, s390_r1, ins->sreg1);
4396 s390_basr (code, s390_r14, s390_r1);
4398 break;
4399 case OP_FCALL_MEMBASE: {
4400 call = (MonoCallInst*)ins;
4401 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4402 s390_basr (code, s390_r14, s390_r1);
4403 if (!cfg->r4fp && call->signature->ret->type == MONO_TYPE_R4)
4404 s390_ldebr (code, s390_f0, s390_f0);
4406 break;
4407 case OP_LCALL_MEMBASE:
4408 case OP_VCALL_MEMBASE:
4409 case OP_VCALL2_MEMBASE:
4410 case OP_VOIDCALL_MEMBASE:
4411 case OP_RCALL_MEMBASE:
4412 case OP_CALL_MEMBASE: {
4413 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4414 s390_basr (code, s390_r14, s390_r1);
4416 break;
4417 case OP_LOCALLOC: {
4418 int alloca_skip;
4419 int area_offset;
4421 if (cfg->param_area == 0)
4422 alloca_skip = S390_MINIMAL_STACK_SIZE;
4423 else
4424 alloca_skip = cfg->param_area;
4426 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4427 s390_lgr (code, s390_r1, ins->sreg1);
4428 if (ins->flags & MONO_INST_INIT)
4429 s390_lgr (code, s390_r0, ins->sreg1);
4430 s390_aghi (code, s390_r1, 14);
4431 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4432 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4433 if (cfg->method->save_lmf) {
4434 /*----------------------------------*/
4435 /* we have to adjust lmf ebp value */
4436 /*----------------------------------*/
4437 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4439 s390_lgr (code, s390_r13, cfg->frame_reg);
4440 if (s390_is_imm16(lmfOffset)) {
4441 s390_aghi (code, s390_r13, lmfOffset);
4442 } else if (s390_is_imm32(lmfOffset)) {
4443 s390_agfi (code, s390_r13, lmfOffset);
4444 } else {
4445 S390_SET (code, s390_r13, lmfOffset);
4447 s390_lgr (code, s390_r14, STK_BASE);
4448 s390_sgr (code, s390_r14, s390_r1);
4449 s390_stg (code, s390_r14, 0, s390_r13,
4450 G_STRUCT_OFFSET(MonoLMF, ebp));
4452 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4453 s390_sgr (code, STK_BASE, s390_r1);
4454 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4455 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4456 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4457 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4458 if (ins->flags & MONO_INST_INIT) {
4459 s390_lgr (code, s390_r1, s390_r0);
4460 s390_lgr (code, s390_r0, ins->dreg);
4461 s390_lgr (code, s390_r14, s390_r12);
4462 s390_lghi (code, s390_r13, 0);
4463 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4464 s390_jo (code, -2);
4465 s390_lgr (code, s390_r12, s390_r14);
4468 break;
4469 case OP_THROW: {
4470 s390_lgr (code, s390_r2, ins->sreg1);
4471 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4472 (gpointer) "mono_arch_throw_exception");
4473 S390_CALL_TEMPLATE(code, s390_r14);
4475 break;
4476 case OP_RETHROW: {
4477 s390_lgr (code, s390_r2, ins->sreg1);
4478 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4479 (gpointer) "mono_arch_rethrow_exception");
4480 S390_CALL_TEMPLATE(code, s390_r14);
4482 break;
4483 case OP_START_HANDLER: {
4484 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4486 S390_LONG (code, stg, stg, s390_r14, 0,
4487 spvar->inst_basereg,
4488 spvar->inst_offset);
4490 break;
4491 case OP_ENDFILTER: {
4492 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4494 if (ins->sreg1 != s390_r2)
4495 s390_lgr(code, s390_r2, ins->sreg1);
4496 S390_LONG (code, lg, lg, s390_r14, 0,
4497 spvar->inst_basereg,
4498 spvar->inst_offset);
4499 s390_br (code, s390_r14);
4501 break;
4502 case OP_ENDFINALLY: {
4503 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4505 S390_LONG (code, lg, lg, s390_r14, 0,
4506 spvar->inst_basereg,
4507 spvar->inst_offset);
4508 s390_br (code, s390_r14);
4510 break;
4511 case OP_CALL_HANDLER: {
4512 mono_add_patch_info (cfg, code-cfg->native_code,
4513 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4514 s390_brasl (code, s390_r14, 0);
4515 for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
4516 mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb);
4518 break;
4519 case OP_LABEL: {
4520 ins->inst_c0 = code - cfg->native_code;
4522 break;
4523 case OP_RELAXED_NOP:
4524 case OP_NOP:
4525 case OP_DUMMY_USE:
4526 case OP_DUMMY_ICONST:
4527 case OP_DUMMY_I8CONST:
4528 case OP_DUMMY_R8CONST:
4529 case OP_DUMMY_R4CONST:
4530 case OP_NOT_REACHED:
4531 case OP_NOT_NULL: {
4533 break;
4534 case OP_IL_SEQ_POINT:
4535 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4536 break;
4537 case OP_SEQ_POINT: {
4538 int i;
4540 if (cfg->compile_aot)
4541 NOT_IMPLEMENTED;
4544 * Read from the single stepping trigger page. This will cause a
4545 * SIGSEGV when single stepping is enabled.
4546 * We do this _before_ the breakpoint, so single stepping after
4547 * a breakpoint is hit will step to the next IL offset.
4549 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4550 breakpointCode.pTrigger = ss_trigger_page;
4551 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4552 code += BREAKPOINT_SIZE;
4555 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4558 * A placeholder for a possible breakpoint inserted by
4559 * mono_arch_set_breakpoint ().
4561 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4562 s390_nop (code);
4565 * Add an additional nop so skipping the bp doesn't cause the ip to point
4566 * to another IL offset.
4568 s390_nop (code);
4570 break;
4572 case OP_GENERIC_CLASS_INIT: {
4573 static int byte_offset = -1;
4574 static guint8 bitmask;
4575 short int *jump;
4577 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4579 if (byte_offset < 0)
4580 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4582 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4583 s390_jo (code, 0); CODEPTR(code, jump);
4585 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4586 "mono_generic_class_init");
4587 S390_CALL_TEMPLATE(code, s390_r14);
4589 PTRSLOT (code, jump);
4591 ins->flags |= MONO_INST_GC_CALLSITE;
4592 ins->backend.pc_offset = code - cfg->native_code;
4593 break;
4595 case OP_BR:
4596 EMIT_UNCOND_BRANCH(ins);
4597 break;
4598 case OP_BR_REG: {
4599 s390_br (code, ins->sreg1);
4601 break;
4602 case OP_CEQ:
4603 case OP_ICEQ:
4604 case OP_LCEQ: {
4605 s390_lghi(code, ins->dreg, 1);
4606 s390_jz (code, 4);
4607 s390_lghi(code, ins->dreg, 0);
4609 break;
4610 case OP_CLT:
4611 case OP_ICLT:
4612 case OP_LCLT: {
4613 s390_lghi(code, ins->dreg, 1);
4614 s390_jl (code, 4);
4615 s390_lghi(code, ins->dreg, 0);
4617 break;
4618 case OP_CLT_UN:
4619 case OP_ICLT_UN:
4620 case OP_LCLT_UN: {
4621 s390_lghi(code, ins->dreg, 1);
4622 s390_jlo (code, 4);
4623 s390_lghi(code, ins->dreg, 0);
4625 break;
4626 case OP_CGT:
4627 case OP_ICGT:
4628 case OP_LCGT: {
4629 s390_lghi(code, ins->dreg, 1);
4630 s390_jh (code, 4);
4631 s390_lghi(code, ins->dreg, 0);
4633 break;
4634 case OP_CGT_UN:
4635 case OP_ICGT_UN:
4636 case OP_LCGT_UN: {
4637 s390_lghi(code, ins->dreg, 1);
4638 s390_jho (code, 4);
4639 s390_lghi(code, ins->dreg, 0);
4641 break;
4642 case OP_ICNEQ: {
4643 s390_lghi(code, ins->dreg, 1);
4644 s390_jne (code, 4);
4645 s390_lghi(code, ins->dreg, 0);
4647 break;
4648 case OP_ICGE: {
4649 s390_lghi(code, ins->dreg, 1);
4650 s390_jhe (code, 4);
4651 s390_lghi(code, ins->dreg, 0);
4653 break;
4654 case OP_ICLE: {
4655 s390_lghi(code, ins->dreg, 1);
4656 s390_jle (code, 4);
4657 s390_lghi(code, ins->dreg, 0);
4659 break;
4660 case OP_ICGE_UN: {
4661 s390_lghi(code, ins->dreg, 1);
4662 s390_jhe (code, 4);
4663 s390_lghi(code, ins->dreg, 0);
4665 break;
4666 case OP_ICLE_UN: {
4667 s390_lghi(code, ins->dreg, 1);
4668 s390_jle (code, 4);
4669 s390_lghi(code, ins->dreg, 0);
4671 break;
4672 case OP_COND_EXC_EQ:
4673 case OP_COND_EXC_IEQ:
4674 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4675 break;
4676 case OP_COND_EXC_NE_UN:
4677 case OP_COND_EXC_INE_UN:
4678 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4679 break;
4680 case OP_COND_EXC_LT:
4681 case OP_COND_EXC_ILT:
4682 case OP_COND_EXC_LT_UN:
4683 case OP_COND_EXC_ILT_UN:
4684 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4685 break;
4686 case OP_COND_EXC_GT:
4687 case OP_COND_EXC_IGT:
4688 case OP_COND_EXC_GT_UN:
4689 case OP_COND_EXC_IGT_UN:
4690 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4691 break;
4692 case OP_COND_EXC_GE:
4693 case OP_COND_EXC_IGE:
4694 case OP_COND_EXC_GE_UN:
4695 case OP_COND_EXC_IGE_UN:
4696 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4697 break;
4698 case OP_COND_EXC_LE:
4699 case OP_COND_EXC_ILE:
4700 case OP_COND_EXC_LE_UN:
4701 case OP_COND_EXC_ILE_UN:
4702 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4703 break;
4704 case OP_COND_EXC_OV:
4705 case OP_COND_EXC_IOV:
4706 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4707 break;
4708 case OP_COND_EXC_NO:
4709 case OP_COND_EXC_INO:
4710 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4711 break;
4712 case OP_COND_EXC_C:
4713 case OP_COND_EXC_IC:
4714 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4715 break;
4716 case OP_COND_EXC_NC:
4717 case OP_COND_EXC_INC:
4718 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4719 break;
4720 case OP_LBEQ:
4721 case OP_IBEQ:
4722 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4723 break;
4724 case OP_LBNE_UN:
4725 case OP_IBNE_UN:
4726 EMIT_COND_BRANCH (ins, S390_CC_NE);
4727 break;
4728 case OP_LBLT:
4729 case OP_LBLT_UN:
4730 case OP_IBLT:
4731 case OP_IBLT_UN:
4732 EMIT_COND_BRANCH (ins, S390_CC_LT);
4733 break;
4734 case OP_LBGT:
4735 case OP_LBGT_UN:
4736 case OP_IBGT:
4737 case OP_IBGT_UN:
4738 EMIT_COND_BRANCH (ins, S390_CC_GT);
4739 break;
4740 case OP_LBGE:
4741 case OP_LBGE_UN:
4742 case OP_IBGE:
4743 case OP_IBGE_UN:
4744 EMIT_COND_BRANCH (ins, S390_CC_GE);
4745 break;
4746 case OP_LBLE:
4747 case OP_LBLE_UN:
4748 case OP_IBLE:
4749 case OP_IBLE_UN:
4750 EMIT_COND_BRANCH (ins, S390_CC_LE);
4751 break;
4753 case OP_S390_CRJ:
4754 EMIT_COMP_AND_BRANCH(ins, crj, cr);
4755 break;
4757 case OP_S390_CLRJ:
4758 EMIT_COMP_AND_BRANCH(ins, clrj, clr);
4759 break;
4761 case OP_S390_CGRJ:
4762 EMIT_COMP_AND_BRANCH(ins, cgrj, cgr);
4763 break;
4765 case OP_S390_CLGRJ:
4766 EMIT_COMP_AND_BRANCH(ins, clgrj, clgr);
4767 break;
4769 case OP_S390_CIJ:
4770 EMIT_COMP_AND_BRANCH_IMM(ins, crj, cr, ltr, FALSE);
4771 break;
4773 case OP_S390_CLIJ:
4774 EMIT_COMP_AND_BRANCH_IMM(ins, clrj, clr, ltr, TRUE);
4775 break;
4777 case OP_S390_CGIJ:
4778 EMIT_COMP_AND_BRANCH_IMM(ins, cgrj, cgr, ltgr, FALSE);
4779 break;
4781 case OP_S390_CLGIJ:
4782 EMIT_COMP_AND_BRANCH_IMM(ins, clgrj, clgr, ltgr, TRUE);
4783 break;
4785 /* floating point opcodes */
4786 case OP_R8CONST: {
4787 if (*((double *) ins->inst_p0) == 0) {
4788 s390_lzdr (code, ins->dreg);
4789 } else {
4790 S390_SET (code, s390_r13, ins->inst_p0);
4791 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4794 break;
4795 case OP_R4CONST: {
4796 if (*((float *) ins->inst_p0) == 0) {
4797 if (cfg->r4fp)
4798 s390_lzer (code, ins->dreg);
4799 else
4800 s390_lzdr (code, ins->dreg);
4801 } else {
4802 S390_SET (code, s390_r13, ins->inst_p0);
4803 if (cfg->r4fp) {
4804 S390_LONG (code, ley, le, ins->dreg, 0, s390_r13, 0);
4805 } else {
4806 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4810 break;
4811 case OP_STORER8_MEMBASE_REG: {
4812 S390_LONG (code, stdy, std, ins->sreg1, 0,
4813 ins->inst_destbasereg, ins->inst_offset);
4815 break;
4816 case OP_LOADR8_MEMBASE: {
4817 S390_LONG (code, ldy, ld, ins->dreg, 0,
4818 ins->inst_basereg, ins->inst_offset);
4820 break;
4821 case OP_STORER4_MEMBASE_REG: {
4822 if (cfg->r4fp) {
4823 S390_LONG (code, stey, ste, ins->sreg1, 0,
4824 ins->inst_destbasereg, ins->inst_offset);
4825 } else {
4826 s390_ledbr (code, s390_f15, ins->sreg1);
4827 S390_LONG (code, stey, ste, s390_f15, 0,
4828 ins->inst_destbasereg, ins->inst_offset);
4831 break;
4832 case OP_LOADR4_MEMBASE: {
4833 if (cfg->r4fp) {
4834 S390_LONG (code, ley, le, ins->dreg, 0,
4835 ins->inst_basereg, ins->inst_offset);
4836 } else {
4837 S390_LONG (code, ley, le, s390_f15, 0,
4838 ins->inst_basereg, ins->inst_offset);
4839 s390_ldebr (code, ins->dreg, s390_f15);
4842 break;
4843 case OP_ICONV_TO_R_UN: {
4844 if (mono_hwcap_s390x_has_fpe) {
4845 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4846 } else {
4847 s390_llgfr (code, s390_r0, ins->sreg1);
4848 s390_cdgbr (code, ins->dreg, s390_r0);
4851 break;
4852 case OP_LCONV_TO_R_UN: {
4853 if (mono_hwcap_s390x_has_fpe) {
4854 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4855 } else {
4856 short int *jump;
4857 s390_cxgbr (code, s390_f12, ins->sreg1);
4858 s390_ltgr (code, ins->sreg1, ins->sreg1);
4859 s390_jnl (code, 0); CODEPTR(code, jump);
4860 S390_SET (code, s390_r13, 0x403f000000000000llu);
4861 s390_lgdr (code, s390_f13, s390_r13);
4862 s390_lzdr (code, s390_f15);
4863 s390_axbr (code, s390_f12, s390_f13);
4864 PTRSLOT(code, jump);
4865 s390_ldxbr (code, s390_f13, s390_f12);
4866 s390_ldr (code, ins->dreg, s390_f13);
4869 break;
4870 case OP_LCONV_TO_R4:
4871 case OP_ICONV_TO_R4: {
4872 s390_cegbr (code, ins->dreg, ins->sreg1);
4873 if (!cfg->r4fp)
4874 s390_ldebr (code, ins->dreg, ins->dreg);
4876 break;
4877 case OP_LCONV_TO_R8:
4878 case OP_ICONV_TO_R8: {
4879 s390_cdgbr (code, ins->dreg, ins->sreg1);
4881 break;
4882 case OP_FCONV_TO_I1:
4883 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4884 s390_ltgr (code, ins->dreg, ins->dreg);
4885 s390_jnl (code, 4);
4886 s390_oill (code, ins->dreg, 0x80);
4887 s390_lghi (code, s390_r0, 0xff);
4888 s390_ngr (code, ins->dreg, s390_r0);
4889 break;
4890 case OP_FCONV_TO_U1:
4891 if (mono_hwcap_s390x_has_fpe) {
4892 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4893 s390_lghi (code, s390_r0, 0xff);
4894 s390_ngr (code, ins->dreg, s390_r0);
4895 } else {
4896 code = emit_double_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4898 break;
4899 case OP_FCONV_TO_I2:
4900 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4901 s390_ltgr (code, ins->dreg, ins->dreg);
4902 s390_jnl (code, 4);
4903 s390_oill (code, ins->dreg, 0x8000);
4904 s390_llill (code, s390_r0, 0xffff);
4905 s390_ngr (code, ins->dreg, s390_r0);
4906 break;
4907 case OP_FCONV_TO_U2:
4908 if (mono_hwcap_s390x_has_fpe) {
4909 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4910 s390_llill (code, s390_r0, 0xffff);
4911 s390_ngr (code, ins->dreg, s390_r0);
4912 } else {
4913 code = emit_double_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4915 break;
4916 case OP_FCONV_TO_I4:
4917 case OP_FCONV_TO_I:
4918 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4919 break;
4920 case OP_FCONV_TO_U4:
4921 case OP_FCONV_TO_U:
4922 if (mono_hwcap_s390x_has_fpe) {
4923 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4924 } else {
4925 code = emit_double_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4927 break;
4928 case OP_FCONV_TO_I8:
4929 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4930 break;
4931 case OP_FCONV_TO_U8:
4932 if (mono_hwcap_s390x_has_fpe) {
4933 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4934 } else {
4935 code = emit_double_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4937 break;
4938 case OP_RCONV_TO_I1:
4939 s390_cgebr (code, ins->dreg, 5, ins->sreg1);
4940 s390_ltgr (code, ins->dreg, ins->dreg);
4941 s390_jnl (code, 4);
4942 s390_oill (code, ins->dreg, 0x80);
4943 s390_lghi (code, s390_r0, 0xff);
4944 s390_ngr (code, ins->dreg, s390_r0);
4945 break;
4946 case OP_RCONV_TO_U1:
4947 if (mono_hwcap_s390x_has_fpe) {
4948 s390_clgebr (code, ins->dreg, 5, ins->sreg1, 0);
4949 s390_lghi (code, s390_r0, 0xff);
4950 s390_ngr (code, ins->dreg, s390_r0);
4951 } else {
4952 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4954 break;
4955 case OP_RCONV_TO_I2:
4956 s390_cgebr (code, ins->dreg, 5, ins->sreg1);
4957 s390_ltgr (code, ins->dreg, ins->dreg);
4958 s390_jnl (code, 4);
4959 s390_oill (code, ins->dreg, 0x8000);
4960 s390_llill (code, s390_r0, 0xffff);
4961 s390_ngr (code, ins->dreg, s390_r0);
4962 break;
4963 case OP_RCONV_TO_U2:
4964 if (mono_hwcap_s390x_has_fpe) {
4965 s390_clgebr (code, ins->dreg, 5, ins->sreg1, 0);
4966 s390_llill (code, s390_r0, 0xffff);
4967 s390_ngr (code, ins->dreg, s390_r0);
4968 } else {
4969 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4971 break;
4972 case OP_RCONV_TO_I4:
4973 case OP_RCONV_TO_I:
4974 s390_cfebr (code, ins->dreg, 5, ins->sreg1);
4975 break;
4976 case OP_RCONV_TO_U4:
4977 if (mono_hwcap_s390x_has_fpe) {
4978 s390_clfebr (code, ins->dreg, 5, ins->sreg1, 0);
4979 } else {
4980 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4982 break;
4983 case OP_RCONV_TO_I8:
4984 s390_cgebr (code, ins->dreg, 5, ins->sreg1);
4985 break;
4986 case OP_RCONV_TO_U8:
4987 if (mono_hwcap_s390x_has_fpe) {
4988 s390_clgebr (code, ins->dreg, 5, ins->sreg1, 0);
4989 } else {
4990 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4992 break;
4993 case OP_LCONV_TO_OVF_I: {
4994 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4995 short int *o[5];
4996 s390_ltgr (code, ins->sreg2, ins->sreg2);
4997 s390_jnl (code, 0); CODEPTR(code, o[0]);
4998 s390_ltgr (code, ins->sreg1, ins->sreg1);
4999 s390_jnl (code, 0); CODEPTR(code, o[1]);
5000 s390_lhi (code, s390_r13, -1);
5001 s390_cgr (code, ins->sreg1, s390_r13);
5002 s390_jnz (code, 0); CODEPTR(code, o[2]);
5003 if (ins->dreg != ins->sreg2)
5004 s390_lgr (code, ins->dreg, ins->sreg2);
5005 s390_j (code, 0); CODEPTR(code, o[3]);
5006 PTRSLOT(code, o[0]);
5007 s390_jz (code, 0); CODEPTR(code, o[4]);
5008 PTRSLOT(code, o[1]);
5009 PTRSLOT(code, o[2]);
5010 mono_add_patch_info (cfg, code - cfg->native_code,
5011 MONO_PATCH_INFO_EXC, "OverflowException");
5012 s390_brasl (code, s390_r14, 0);
5013 PTRSLOT(code, o[3]);
5014 PTRSLOT(code, o[4]);
5016 break;
5017 case OP_ABS: {
5018 s390_lpdbr (code, ins->dreg, ins->sreg1);
5020 break;
5021 case OP_SQRT: {
5022 s390_sqdbr (code, ins->dreg, ins->sreg1);
5024 break;
5025 case OP_FADD: {
5026 CHECK_SRCDST_COM_F;
5027 s390_adbr (code, ins->dreg, src2);
5029 break;
5030 case OP_RADD: {
5031 CHECK_SRCDST_COM_F;
5032 s390_aebr (code, ins->dreg, src2);
5034 break;
5035 case OP_FSUB: {
5036 CHECK_SRCDST_NCOM_F;
5037 s390_sdbr (code, ins->dreg, src2);
5039 break;
5040 case OP_RSUB: {
5041 CHECK_SRCDST_NCOM_F;
5042 s390_sebr (code, ins->dreg, src2);
5044 break;
5045 case OP_FMUL: {
5046 CHECK_SRCDST_COM_F;
5047 s390_mdbr (code, ins->dreg, src2);
5049 break;
5050 case OP_RMUL: {
5051 CHECK_SRCDST_COM_F;
5052 s390_meer (code, ins->dreg, src2);
5054 break;
5055 case OP_FDIV: {
5056 CHECK_SRCDST_NCOM_F;
5057 s390_ddbr (code, ins->dreg, src2);
5059 break;
5060 case OP_RDIV: {
5061 CHECK_SRCDST_NCOM_F;
5062 s390_debr (code, ins->dreg, src2);
5064 break;
5065 case OP_FNEG: {
5066 s390_lcdbr (code, ins->dreg, ins->sreg1);
5068 break;
5069 case OP_RNEG: {
5070 s390_lcebr (code, ins->dreg, ins->sreg1);
5072 break;
5073 case OP_FREM: {
5074 CHECK_SRCDST_NCOM_F;
5075 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
5077 break;
5078 case OP_RREM: {
5079 CHECK_SRCDST_NCOM_F;
5080 s390_diebr (code, ins->dreg, src2, 5, s390_f15);
5082 break;
5083 case OP_FCOMPARE: {
5084 s390_cdbr (code, ins->sreg1, ins->sreg2);
5086 break;
5087 case OP_RCOMPARE: {
5088 s390_cebr (code, ins->sreg1, ins->sreg2);
5090 break;
5091 case OP_FCEQ: {
5092 s390_cdbr (code, ins->sreg1, ins->sreg2);
5093 s390_lghi (code, ins->dreg, 1);
5094 s390_je (code, 4);
5095 s390_lghi (code, ins->dreg, 0);
5097 break;
5098 case OP_FCLT: {
5099 s390_cdbr (code, ins->sreg1, ins->sreg2);
5100 s390_lghi (code, ins->dreg, 1);
5101 s390_jl (code, 4);
5102 s390_lghi (code, ins->dreg, 0);
5104 break;
5105 case OP_FCLT_UN: {
5106 s390_cdbr (code, ins->sreg1, ins->sreg2);
5107 s390_lghi (code, ins->dreg, 1);
5108 s390_jlo (code, 4);
5109 s390_lghi (code, ins->dreg, 0);
5111 break;
5112 case OP_FCGT: {
5113 s390_cdbr (code, ins->sreg1, ins->sreg2);
5114 s390_lghi (code, ins->dreg, 1);
5115 s390_jh (code, 4);
5116 s390_lghi (code, ins->dreg, 0);
5118 break;
5119 case OP_FCGT_UN: {
5120 s390_cdbr (code, ins->sreg1, ins->sreg2);
5121 s390_lghi (code, ins->dreg, 1);
5122 s390_jho (code, 4);
5123 s390_lghi (code, ins->dreg, 0);
5125 break;
5126 case OP_FCNEQ: {
5127 s390_cdbr (code, ins->sreg1, ins->sreg2);
5128 s390_lghi (code, ins->dreg, 1);
5129 s390_jne (code, 4);
5130 s390_lghi (code, ins->dreg, 0);
5132 break;
5133 case OP_FCGE: {
5134 s390_cdbr (code, ins->sreg1, ins->sreg2);
5135 s390_lghi (code, ins->dreg, 1);
5136 s390_jhe (code, 4);
5137 s390_lghi (code, ins->dreg, 0);
5139 break;
5140 case OP_FCLE: {
5141 s390_cdbr (code, ins->sreg1, ins->sreg2);
5142 s390_lghi (code, ins->dreg, 1);
5143 s390_jle (code, 4);
5144 s390_lghi (code, ins->dreg, 0);
5146 break;
5147 case OP_RCEQ: {
5148 s390_cdbr (code, ins->sreg1, ins->sreg2);
5149 s390_lghi (code, ins->dreg, 1);
5150 s390_je (code, 4);
5151 s390_lghi (code, ins->dreg, 0);
5153 break;
5154 case OP_RCLT: {
5155 s390_cdbr (code, ins->sreg1, ins->sreg2);
5156 s390_lghi (code, ins->dreg, 1);
5157 s390_jl (code, 4);
5158 s390_lghi (code, ins->dreg, 0);
5160 break;
5161 case OP_RCLT_UN: {
5162 s390_cdbr (code, ins->sreg1, ins->sreg2);
5163 s390_lghi (code, ins->dreg, 1);
5164 s390_jlo (code, 4);
5165 s390_lghi (code, ins->dreg, 0);
5167 break;
5168 case OP_RCGT: {
5169 s390_cdbr (code, ins->sreg1, ins->sreg2);
5170 s390_lghi (code, ins->dreg, 1);
5171 s390_jh (code, 4);
5172 s390_lghi (code, ins->dreg, 0);
5174 break;
5175 case OP_RCGT_UN: {
5176 s390_cdbr (code, ins->sreg1, ins->sreg2);
5177 s390_lghi (code, ins->dreg, 1);
5178 s390_jho (code, 4);
5179 s390_lghi (code, ins->dreg, 0);
5181 break;
5182 case OP_RCNEQ: {
5183 s390_cdbr (code, ins->sreg1, ins->sreg2);
5184 s390_lghi (code, ins->dreg, 1);
5185 s390_jne (code, 4);
5186 s390_lghi (code, ins->dreg, 0);
5188 break;
5189 case OP_RCGE: {
5190 s390_cdbr (code, ins->sreg1, ins->sreg2);
5191 s390_lghi (code, ins->dreg, 1);
5192 s390_jhe (code, 4);
5193 s390_lghi (code, ins->dreg, 0);
5195 break;
5196 case OP_RCLE: {
5197 s390_cebr (code, ins->sreg1, ins->sreg2);
5198 s390_lghi (code, ins->dreg, 1);
5199 s390_jle (code, 4);
5200 s390_lghi (code, ins->dreg, 0);
5202 break;
5203 case OP_FBEQ: {
5204 short *o;
5205 s390_jo (code, 0); CODEPTR(code, o);
5206 EMIT_COND_BRANCH (ins, S390_CC_EQ);
5207 PTRSLOT (code, o);
5209 break;
5210 case OP_FBNE_UN:
5211 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
5212 break;
5213 case OP_FBLT: {
5214 short *o;
5215 s390_jo (code, 0); CODEPTR(code, o);
5216 EMIT_COND_BRANCH (ins, S390_CC_LT);
5217 PTRSLOT (code, o);
5219 break;
5220 case OP_FBLT_UN:
5221 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
5222 break;
5223 case OP_FBGT: {
5224 short *o;
5225 s390_jo (code, 0); CODEPTR(code, o);
5226 EMIT_COND_BRANCH (ins, S390_CC_GT);
5227 PTRSLOT (code, o);
5229 break;
5230 case OP_FBGT_UN:
5231 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
5232 break;
5233 case OP_FBGE: {
5234 short *o;
5235 s390_jo (code, 0); CODEPTR(code, o);
5236 EMIT_COND_BRANCH (ins, S390_CC_GE);
5237 PTRSLOT (code, o);
5239 break;
5240 case OP_FBGE_UN:
5241 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
5242 break;
5243 case OP_FBLE: {
5244 short *o;
5245 s390_jo (code, 0); CODEPTR(code, o);
5246 EMIT_COND_BRANCH (ins, S390_CC_LE);
5247 PTRSLOT (code, o);
5249 break;
5250 case OP_FBLE_UN:
5251 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
5252 break;
5253 case OP_CKFINITE: {
5254 short *o;
5255 s390_lhi (code, s390_r13, 0x7f);
5256 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
5257 s390_jz (code, 0); CODEPTR(code, o);
5258 mono_add_patch_info (cfg, code - cfg->native_code,
5259 MONO_PATCH_INFO_EXC, "OverflowException");
5260 s390_brasl (code, s390_r14,0);
5261 PTRSLOT(code, o);
5263 break;
5264 case OP_S390_MOVE: {
5265 if (ins->backend.size > 0) {
5266 if (ins->backend.size <= 256) {
5267 s390_mvc (code, ins->backend.size, ins->dreg,
5268 ins->inst_offset, ins->sreg1, ins->inst_imm);
5269 } else {
5270 s390_lgr (code, s390_r0, ins->dreg);
5271 if (ins->inst_offset > 0) {
5272 if (s390_is_imm16 (ins->inst_offset)) {
5273 s390_aghi (code, s390_r0, ins->inst_offset);
5274 } else if (s390_is_imm32 (ins->inst_offset)) {
5275 s390_agfi (code, s390_r0, ins->inst_offset);
5276 } else {
5277 S390_SET (code, s390_r13, ins->inst_offset);
5278 s390_agr (code, s390_r0, s390_r13);
5281 s390_lgr (code, s390_r12, ins->sreg1);
5282 if (ins->inst_imm > 0) {
5283 if (s390_is_imm16 (ins->inst_imm)) {
5284 s390_aghi (code, s390_r12, ins->inst_imm);
5285 } else if (s390_is_imm32 (ins->inst_imm)) {
5286 s390_agfi (code, s390_r12, ins->inst_imm);
5287 } else {
5288 S390_SET (code, s390_r13, ins->inst_imm);
5289 s390_agr (code, s390_r12, s390_r13);
5292 if (s390_is_imm16 (ins->backend.size)) {
5293 s390_lghi (code, s390_r1, ins->backend.size);
5294 } else if (s390_is_imm32 (ins->inst_offset)) {
5295 s390_agfi (code, s390_r1, ins->backend.size);
5296 } else {
5297 S390_SET (code, s390_r13, ins->backend.size);
5298 s390_agr (code, s390_r1, s390_r13);
5300 s390_lgr (code, s390_r13, s390_r1);
5301 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
5302 s390_jo (code, -2);
5306 break;
5307 case OP_ATOMIC_ADD_I8: {
5308 if (mono_hwcap_s390x_has_ia) {
5309 s390_laag (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5310 s390_agr (code, ins->dreg, ins->sreg2);
5311 } else {
5312 s390_lgr (code, s390_r1, ins->sreg2);
5313 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5314 s390_agr (code, s390_r1, s390_r0);
5315 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5316 s390_jnz (code, -10);
5317 s390_lgr (code, ins->dreg, s390_r1);
5320 break;
5321 case OP_ATOMIC_EXCHANGE_I8: {
5322 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5323 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5324 s390_jnz (code, -6);
5325 s390_lgr (code, ins->dreg, s390_r0);
5327 break;
5328 case OP_ATOMIC_ADD_I4: {
5329 if (mono_hwcap_s390x_has_ia) {
5330 s390_laa (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5331 s390_ar (code, ins->dreg, ins->sreg2);
5332 } else {
5333 s390_lgfr(code, s390_r1, ins->sreg2);
5334 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5335 s390_agr (code, s390_r1, s390_r0);
5336 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5337 s390_jnz (code, -9);
5338 s390_lgfr(code, ins->dreg, s390_r1);
5341 break;
5342 case OP_ATOMIC_EXCHANGE_I4: {
5343 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5344 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5345 s390_jnz (code, -4);
5346 s390_lgfr(code, ins->dreg, s390_r0);
5348 break;
5349 case OP_S390_BKCHAIN: {
5350 s390_lgr (code, ins->dreg, ins->sreg1);
5351 if (s390_is_imm16 (cfg->stack_offset)) {
5352 s390_aghi (code, ins->dreg, cfg->stack_offset);
5353 } else if (s390_is_imm32 (cfg->stack_offset)) {
5354 s390_agfi (code, ins->dreg, cfg->stack_offset);
5355 } else {
5356 S390_SET (code, s390_r13, cfg->stack_offset);
5357 s390_agr (code, ins->dreg, s390_r13);
5360 break;
5361 case OP_MEMORY_BARRIER:
5362 s390_mem (code);
5363 break;
5364 case OP_LIVERANGE_START: {
5365 if (cfg->verbose_level > 1)
5366 printf ("R%d START=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
5367 MONO_VARINFO (cfg, ins->inst_c0)->live_range_start = code - cfg->native_code;
5368 break;
5370 case OP_LIVERANGE_END: {
5371 if (cfg->verbose_level > 1)
5372 printf ("R%d END=0x%x\n", MONO_VARINFO (cfg, ins->inst_c0)->vreg, (int)(code - cfg->native_code));
5373 MONO_VARINFO (cfg, ins->inst_c0)->live_range_end = code - cfg->native_code;
5374 break;
5376 case OP_GC_SAFE_POINT: {
5377 short *br;
5379 g_assert (mono_threads_are_safepoints_enabled ());
5381 s390_ltg (code, s390_r0, 0, ins->sreg1, 0);
5382 s390_jz (code, 0); CODEPTR(code, br);
5383 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
5384 mono_threads_state_poll);
5385 S390_CALL_TEMPLATE (code, s390_r14);
5386 PTRSLOT (code, br);
5387 break;
5389 case OP_GC_LIVENESS_DEF:
5390 case OP_GC_LIVENESS_USE:
5391 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
5392 ins->backend.pc_offset = code - cfg->native_code;
5393 break;
5394 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
5395 ins->backend.pc_offset = code - cfg->native_code;
5396 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
5397 break;
5398 #ifdef MONO_ARCH_SIMD_INTRINSICS
5399 case OP_ADDPS:
5400 s390x_addps (code, ins->sreg1, ins->sreg2);
5401 break;
5402 case OP_DIVPS:
5403 s390x_divps (code, ins->sreg1, ins->sreg2);
5404 break;
5405 case OP_MULPS:
5406 s390x_mulps (code, ins->sreg1, ins->sreg2);
5407 break;
5408 case OP_SUBPS:
5409 s390x_subps (code, ins->sreg1, ins->sreg2);
5410 break;
5411 case OP_MAXPS:
5412 s390x_maxps (code, ins->sreg1, ins->sreg2);
5413 break;
5414 case OP_MINPS:
5415 s390x_minps (code, ins->sreg1, ins->sreg2);
5416 break;
5417 case OP_COMPPS:
5418 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5419 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5420 break;
5421 case OP_ANDPS:
5422 s390x_andps (code, ins->sreg1, ins->sreg2);
5423 break;
5424 case OP_ANDNPS:
5425 s390x_andnps (code, ins->sreg1, ins->sreg2);
5426 break;
5427 case OP_ORPS:
5428 s390x_orps (code, ins->sreg1, ins->sreg2);
5429 break;
5430 case OP_XORPS:
5431 s390x_xorps (code, ins->sreg1, ins->sreg2);
5432 break;
5433 case OP_SQRTPS:
5434 s390x_sqrtps (code, ins->dreg, ins->sreg1);
5435 break;
5436 case OP_RSQRTPS:
5437 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
5438 break;
5439 case OP_RCPPS:
5440 s390x_rcpps (code, ins->dreg, ins->sreg1);
5441 break;
5442 case OP_ADDSUBPS:
5443 s390x_addsubps (code, ins->sreg1, ins->sreg2);
5444 break;
5445 case OP_HADDPS:
5446 s390x_haddps (code, ins->sreg1, ins->sreg2);
5447 break;
5448 case OP_HSUBPS:
5449 s390x_hsubps (code, ins->sreg1, ins->sreg2);
5450 break;
5451 case OP_DUPPS_HIGH:
5452 s390x_movshdup (code, ins->dreg, ins->sreg1);
5453 break;
5454 case OP_DUPPS_LOW:
5455 s390x_movsldup (code, ins->dreg, ins->sreg1);
5456 break;
5458 case OP_PSHUFLEW_HIGH:
5459 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5460 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5461 break;
5462 case OP_PSHUFLEW_LOW:
5463 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5464 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5465 break;
5466 case OP_PSHUFLED:
5467 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5468 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5469 break;
5470 case OP_SHUFPS:
5471 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5472 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5473 break;
5474 case OP_SHUFPD:
5475 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
5476 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5477 break;
5479 case OP_ADDPD:
5480 s390x_addpd (code, ins->sreg1, ins->sreg2);
5481 break;
5482 case OP_DIVPD:
5483 s390x_divpd (code, ins->sreg1, ins->sreg2);
5484 break;
5485 case OP_MULPD:
5486 s390x_mulpd (code, ins->sreg1, ins->sreg2);
5487 break;
5488 case OP_SUBPD:
5489 s390x_subpd (code, ins->sreg1, ins->sreg2);
5490 break;
5491 case OP_MAXPD:
5492 s390x_maxpd (code, ins->sreg1, ins->sreg2);
5493 break;
5494 case OP_MINPD:
5495 s390x_minpd (code, ins->sreg1, ins->sreg2);
5496 break;
5497 case OP_COMPPD:
5498 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5499 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5500 break;
5501 case OP_ANDPD:
5502 s390x_andpd (code, ins->sreg1, ins->sreg2);
5503 break;
5504 case OP_ANDNPD:
5505 s390x_andnpd (code, ins->sreg1, ins->sreg2);
5506 break;
5507 case OP_ORPD:
5508 s390x_orpd (code, ins->sreg1, ins->sreg2);
5509 break;
5510 case OP_XORPD:
5511 s390x_xorpd (code, ins->sreg1, ins->sreg2);
5512 break;
5513 case OP_SQRTPD:
5514 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
5515 break;
5516 case OP_ADDSUBPD:
5517 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
5518 break;
5519 case OP_HADDPD:
5520 s390x_haddpd (code, ins->sreg1, ins->sreg2);
5521 break;
5522 case OP_HSUBPD:
5523 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
5524 break;
5525 case OP_DUPPD:
5526 s390x_movddup (code, ins->dreg, ins->sreg1);
5527 break;
5529 case OP_EXTRACT_MASK:
5530 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
5531 break;
5533 case OP_PAND:
5534 s390x_pand (code, ins->sreg1, ins->sreg2);
5535 break;
5536 case OP_POR:
5537 s390x_por (code, ins->sreg1, ins->sreg2);
5538 break;
5539 case OP_PXOR:
5540 s390x_pxor (code, ins->sreg1, ins->sreg2);
5541 break;
5543 case OP_PADDB:
5544 s390x_paddb (code, ins->sreg1, ins->sreg2);
5545 break;
5546 case OP_PADDW:
5547 s390x_paddw (code, ins->sreg1, ins->sreg2);
5548 break;
5549 case OP_PADDD:
5550 s390x_paddd (code, ins->sreg1, ins->sreg2);
5551 break;
5552 case OP_PADDQ:
5553 s390x_paddq (code, ins->sreg1, ins->sreg2);
5554 break;
5556 case OP_PSUBB:
5557 s390x_psubb (code, ins->sreg1, ins->sreg2);
5558 break;
5559 case OP_PSUBW:
5560 s390x_psubw (code, ins->sreg1, ins->sreg2);
5561 break;
5562 case OP_PSUBD:
5563 s390x_psubd (code, ins->sreg1, ins->sreg2);
5564 break;
5565 case OP_PSUBQ:
5566 s390x_psubq (code, ins->sreg1, ins->sreg2);
5567 break;
5569 case OP_PMAXB_UN:
5570 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
5571 break;
5572 case OP_PMAXW_UN:
5573 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
5574 break;
5575 case OP_PMAXD_UN:
5576 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
5577 break;
5579 case OP_PMAXB:
5580 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
5581 break;
5582 case OP_PMAXW:
5583 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
5584 break;
5585 case OP_PMAXD:
5586 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
5587 break;
5589 case OP_PAVGB_UN:
5590 s390x_pavgb (code, ins->sreg1, ins->sreg2);
5591 break;
5592 case OP_PAVGW_UN:
5593 s390x_pavgw (code, ins->sreg1, ins->sreg2);
5594 break;
5596 case OP_PMINB_UN:
5597 s390x_pminub (code, ins->sreg1, ins->sreg2);
5598 break;
5599 case OP_PMINW_UN:
5600 s390x_pminuw (code, ins->sreg1, ins->sreg2);
5601 break;
5602 case OP_PMIND_UN:
5603 s390x_pminud (code, ins->sreg1, ins->sreg2);
5604 break;
5606 case OP_PMINB:
5607 s390x_pminsb (code, ins->sreg1, ins->sreg2);
5608 break;
5609 case OP_PMINW:
5610 s390x_pminsw (code, ins->sreg1, ins->sreg2);
5611 break;
5612 case OP_PMIND:
5613 s390x_pminsd (code, ins->sreg1, ins->sreg2);
5614 break;
5616 case OP_PCMPEQB:
5617 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
5618 break;
5619 case OP_PCMPEQW:
5620 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
5621 break;
5622 case OP_PCMPEQD:
5623 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
5624 break;
5625 case OP_PCMPEQQ:
5626 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
5627 break;
5629 case OP_PCMPGTB:
5630 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
5631 break;
5632 case OP_PCMPGTW:
5633 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5634 break;
5635 case OP_PCMPGTD:
5636 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5637 break;
5638 case OP_PCMPGTQ:
5639 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5640 break;
5642 case OP_PSUM_ABS_DIFF:
5643 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5644 break;
5646 case OP_UNPACK_LOWB:
5647 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5648 break;
5649 case OP_UNPACK_LOWW:
5650 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5651 break;
5652 case OP_UNPACK_LOWD:
5653 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5654 break;
5655 case OP_UNPACK_LOWQ:
5656 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5657 break;
5658 case OP_UNPACK_LOWPS:
5659 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5660 break;
5661 case OP_UNPACK_LOWPD:
5662 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5663 break;
5665 case OP_UNPACK_HIGHB:
5666 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5667 break;
5668 case OP_UNPACK_HIGHW:
5669 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5670 break;
5671 case OP_UNPACK_HIGHD:
5672 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5673 break;
5674 case OP_UNPACK_HIGHQ:
5675 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5676 break;
5677 case OP_UNPACK_HIGHPS:
5678 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5679 break;
5680 case OP_UNPACK_HIGHPD:
5681 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5682 break;
5684 case OP_PACKW:
5685 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5686 break;
5687 case OP_PACKD:
5688 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5689 break;
5690 case OP_PACKW_UN:
5691 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5692 break;
5693 case OP_PACKD_UN:
5694 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5695 break;
5697 case OP_PADDB_SAT_UN:
5698 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5699 break;
5700 case OP_PSUBB_SAT_UN:
5701 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5702 break;
5703 case OP_PADDW_SAT_UN:
5704 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5705 break;
5706 case OP_PSUBW_SAT_UN:
5707 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5708 break;
5710 case OP_PADDB_SAT:
5711 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5712 break;
5713 case OP_PSUBB_SAT:
5714 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5715 break;
5716 case OP_PADDW_SAT:
5717 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5718 break;
5719 case OP_PSUBW_SAT:
5720 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5721 break;
5723 case OP_PMULW:
5724 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5725 break;
5726 case OP_PMULD:
5727 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5728 break;
5729 case OP_PMULQ:
5730 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5731 break;
5732 case OP_PMULW_HIGH_UN:
5733 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5734 break;
5735 case OP_PMULW_HIGH:
5736 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5737 break;
5739 case OP_PSHRW:
5740 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5741 break;
5742 case OP_PSHRW_REG:
5743 s390x_psrlw (code, ins->dreg, ins->sreg2);
5744 break;
5746 case OP_PSARW:
5747 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5748 break;
5749 case OP_PSARW_REG:
5750 s390x_psraw (code, ins->dreg, ins->sreg2);
5751 break;
5753 case OP_PSHLW:
5754 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5755 break;
5756 case OP_PSHLW_REG:
5757 s390x_psllw (code, ins->dreg, ins->sreg2);
5758 break;
5760 case OP_PSHRD:
5761 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5762 break;
5763 case OP_PSHRD_REG:
5764 s390x_psrld (code, ins->dreg, ins->sreg2);
5765 break;
5767 case OP_PSARD:
5768 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5769 break;
5770 case OP_PSARD_REG:
5771 s390x_psrad (code, ins->dreg, ins->sreg2);
5772 break;
5774 case OP_PSHLD:
5775 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5776 break;
5777 case OP_PSHLD_REG:
5778 s390x_pslld (code, ins->dreg, ins->sreg2);
5779 break;
5781 case OP_PSHRQ:
5782 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5783 break;
5784 case OP_PSHRQ_REG:
5785 s390x_psrlq (code, ins->dreg, ins->sreg2);
5786 break;
5788 /*TODO: This is appart of the sse spec but not added
5789 case OP_PSARQ:
5790 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5791 break;
5792 case OP_PSARQ_REG:
5793 s390x_psraq (code, ins->dreg, ins->sreg2);
5794 break;
5797 case OP_PSHLQ:
5798 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5799 break;
5800 case OP_PSHLQ_REG:
5801 s390x_psllq (code, ins->dreg, ins->sreg2);
5802 break;
5803 case OP_CVTDQ2PD:
5804 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5805 break;
5806 case OP_CVTDQ2PS:
5807 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5808 break;
5809 case OP_CVTPD2DQ:
5810 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5811 break;
5812 case OP_CVTPD2PS:
5813 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5814 break;
5815 case OP_CVTPS2DQ:
5816 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5817 break;
5818 case OP_CVTPS2PD:
5819 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5820 break;
5821 case OP_CVTTPD2DQ:
5822 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5823 break;
5824 case OP_CVTTPS2DQ:
5825 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5826 break;
5828 case OP_ICONV_TO_X:
5829 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5830 break;
5831 case OP_EXTRACT_I4:
5832 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5833 break;
5834 case OP_EXTRACT_I8:
5835 if (ins->inst_c0) {
5836 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5837 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5838 } else {
5839 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5841 break;
5842 case OP_EXTRACT_I1:
5843 case OP_EXTRACT_U1:
5844 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5845 if (ins->inst_c0)
5846 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5847 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5848 break;
5849 case OP_EXTRACT_I2:
5850 case OP_EXTRACT_U2:
5851 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5852 if (ins->inst_c0)
5853 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5854 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5855 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5856 break;
5857 case OP_EXTRACT_R8:
5858 if (ins->inst_c0)
5859 amd64_movhlps (code, ins->dreg, ins->sreg1);
5860 else
5861 s390x_movsd (code, ins->dreg, ins->sreg1);
5862 break;
5863 case OP_INSERT_I2:
5864 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5865 break;
5866 case OP_EXTRACTX_U2:
5867 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5868 break;
5869 case OP_INSERTX_U1_SLOW:
5870 /*sreg1 is the extracted ireg (scratch)
5871 /sreg2 is the to be inserted ireg (scratch)
5872 /dreg is the xreg to receive the value*/
5874 /*clear the bits from the extracted word*/
5875 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5876 /*shift the value to insert if needed*/
5877 if (ins->inst_c0 & 1)
5878 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5879 /*join them together*/
5880 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5881 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5882 break;
5883 case OP_INSERTX_I4_SLOW:
5884 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5885 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5886 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5887 break;
5888 case OP_INSERTX_I8_SLOW:
5889 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5890 if (ins->inst_c0)
5891 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5892 else
5893 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5894 break;
5896 case OP_INSERTX_R4_SLOW:
5897 switch (ins->inst_c0) {
5898 case 0:
5899 if (cfg->r4fp)
5900 s390x_movss (code, ins->dreg, ins->sreg2);
5901 else
5902 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5903 break;
5904 case 1:
5905 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5906 if (cfg->r4fp)
5907 s390x_movss (code, ins->dreg, ins->sreg2);
5908 else
5909 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5910 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5911 break;
5912 case 2:
5913 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5914 if (cfg->r4fp)
5915 s390x_movss (code, ins->dreg, ins->sreg2);
5916 else
5917 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5918 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5919 break;
5920 case 3:
5921 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5922 if (cfg->r4fp)
5923 s390x_movss (code, ins->dreg, ins->sreg2);
5924 else
5925 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5926 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5927 break;
5929 break;
5930 case OP_INSERTX_R8_SLOW:
5931 if (ins->inst_c0)
5932 amd64_movlhps (code, ins->dreg, ins->sreg2);
5933 else
5934 s390x_movsd (code, ins->dreg, ins->sreg2);
5935 break;
5936 case OP_STOREX_MEMBASE_REG:
5937 case OP_STOREX_MEMBASE:
5938 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5939 break;
5940 case OP_LOADX_MEMBASE:
5941 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5942 break;
5943 case OP_LOADX_ALIGNED_MEMBASE:
5944 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5945 break;
5946 case OP_STOREX_ALIGNED_MEMBASE_REG:
5947 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5948 break;
5949 case OP_STOREX_NTA_MEMBASE_REG:
5950 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5951 break;
5952 case OP_PREFETCH_MEMBASE:
5953 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5954 break;
5956 case OP_XMOVE:
5957 /*FIXME the peephole pass should have killed this*/
5958 if (ins->dreg != ins->sreg1)
5959 s390x_movaps (code, ins->dreg, ins->sreg1);
5960 break;
5961 case OP_XZERO:
5962 s390x_pxor (code, ins->dreg, ins->dreg);
5963 break;
5964 case OP_ICONV_TO_R4_RAW:
5965 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5966 break;
5968 case OP_FCONV_TO_R8_X:
5969 s390x_movsd (code, ins->dreg, ins->sreg1);
5970 break;
5972 case OP_XCONV_R8_TO_I4:
5973 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5974 switch (ins->backend.source_opcode) {
5975 case OP_FCONV_TO_I1:
5976 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5977 break;
5978 case OP_FCONV_TO_U1:
5979 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5980 break;
5981 case OP_FCONV_TO_I2:
5982 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5983 break;
5984 case OP_FCONV_TO_U2:
5985 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5986 break;
5988 break;
5990 case OP_EXPAND_I2:
5991 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5992 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5993 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5994 break;
5995 case OP_EXPAND_I4:
5996 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5997 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5998 break;
5999 case OP_EXPAND_I8:
6000 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
6001 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
6002 break;
6003 case OP_EXPAND_R4:
6004 if (cfg->r4fp) {
6005 s390x_movsd (code, ins->dreg, ins->sreg1);
6006 } else {
6007 s390x_movsd (code, ins->dreg, ins->sreg1);
6008 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
6010 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
6011 break;
6012 case OP_EXPAND_R8:
6013 s390x_movsd (code, ins->dreg, ins->sreg1);
6014 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
6015 break;
6016 #endif
6017 default:
6018 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
6019 g_assert_not_reached ();
6022 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
6023 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
6024 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
6025 g_assert_not_reached ();
6029 set_code_cursor (cfg, code);
6032 /*========================= End of Function ========================*/
6034 /*------------------------------------------------------------------*/
6035 /* */
6036 /* Name - mono_arch_register_lowlevel_calls */
6037 /* */
6038 /* Function - Register routines to help with --trace operation. */
6039 /* */
6040 /*------------------------------------------------------------------*/
6042 void
6043 mono_arch_register_lowlevel_calls (void)
6047 /*========================= End of Function ========================*/
6049 /*------------------------------------------------------------------*/
6050 /* */
6051 /* Name - mono_arch_patch_code */
6052 /* */
6053 /* Function - Process the patch data created during the */
6054 /* instruction build process. This resolves jumps, */
6055 /* calls, variables etc. */
6056 /* */
6057 /*------------------------------------------------------------------*/
6059 void
6060 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
6061 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
6062 MonoError *error)
6064 MonoJumpInfo *patch_info;
6066 error_init (error);
6068 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
6069 unsigned char *ip = patch_info->ip.i + code;
6070 gconstpointer target = NULL;
6072 target = mono_resolve_patch_target (method, domain, code,
6073 patch_info, run_cctors, error);
6074 return_if_nok (error);
6076 switch (patch_info->type) {
6077 case MONO_PATCH_INFO_IP:
6078 case MONO_PATCH_INFO_LDSTR:
6079 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
6080 case MONO_PATCH_INFO_LDTOKEN:
6081 case MONO_PATCH_INFO_EXC:
6082 s390_patch_addr (ip, (guint64) target);
6083 continue;
6084 case MONO_PATCH_INFO_METHOD:
6085 case MONO_PATCH_INFO_INTERNAL_METHOD:
6086 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
6087 case MONO_PATCH_INFO_RGCTX_FETCH:
6088 case MONO_PATCH_INFO_ABS: {
6089 S390_EMIT_CALL (ip, target);
6090 continue;
6092 case MONO_PATCH_INFO_SWITCH:
6093 /*----------------------------------*/
6094 /* ip points at the basr r13,0/j +4 */
6095 /* instruction the vtable value */
6096 /* follows this (i.e. ip+6) */
6097 /*----------------------------------*/
6098 S390_EMIT_LOAD (ip, target);
6099 continue;
6100 case MONO_PATCH_INFO_METHODCONST:
6101 case MONO_PATCH_INFO_CLASS:
6102 case MONO_PATCH_INFO_IMAGE:
6103 case MONO_PATCH_INFO_FIELD:
6104 case MONO_PATCH_INFO_IID:
6105 case MONO_PATCH_INFO_EXC_NAME:
6106 target = S390_RELATIVE(target, ip);
6107 s390_patch_rel (ip, (guint64) target);
6108 continue;
6109 case MONO_PATCH_INFO_R4:
6110 case MONO_PATCH_INFO_R8:
6111 case MONO_PATCH_INFO_METHOD_REL:
6112 g_assert_not_reached ();
6113 continue;
6114 default:
6115 target = S390_RELATIVE(target, ip);
6116 ip += 2;
6117 s390_patch_rel (ip, (guint64) target);
6122 /*========================= End of Function ========================*/
6124 /*------------------------------------------------------------------*/
6125 /* */
6126 /* Name - mono_arch_emit_prolog */
6127 /* */
6128 /* Function - Create the instruction sequence for a function */
6129 /* prolog. */
6130 /* */
6131 /*------------------------------------------------------------------*/
6133 guint8 *
6134 mono_arch_emit_prolog (MonoCompile *cfg)
6136 MonoMethod *method = cfg->method;
6137 MonoBasicBlock *bb;
6138 MonoMethodSignature *sig;
6139 MonoInst *inst;
6140 long alloc_size, pos, max_offset, i, cfa_offset = 0;
6141 guint8 *code;
6142 guint32 size;
6143 CallInfo *cinfo;
6144 int tracing = 0,
6145 argsClobbered = 0,
6146 lmfOffset,
6147 fpOffset = 0,
6148 traceSize = 0;
6150 cfg->code_size = 512;
6152 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6153 tracing = 1;
6154 traceSize = S390_TRACE_STACK_SIZE;
6155 cfg->code_size += 256;
6158 if (method->save_lmf)
6159 cfg->code_size += 200;
6161 cfg->native_code = code = g_malloc (cfg->code_size);
6163 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
6164 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
6165 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6166 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
6167 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
6168 if (cfg->arch.bkchain_reg != -1)
6169 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
6171 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6172 cfg->used_int_regs |= 1 << s390_r11;
6175 if ((cfg->arch.used_fp_regs & S390_FP_SAVE_MASK) != 0) {
6176 for (int i=8; i<16; i++) {
6177 if (cfg->arch.used_fp_regs & (1 << i))
6178 fpOffset += sizeof(double);
6180 fpOffset = S390_ALIGN(fpOffset, 16);
6182 cfg->arch.fpSize = fpOffset;
6184 alloc_size = cfg->stack_offset + fpOffset + traceSize;
6186 cfg->stack_usage = cfa_offset = alloc_size;
6187 s390_lgr (code, s390_r11, STK_BASE);
6188 if (s390_is_imm16 (alloc_size)) {
6189 s390_aghi (code, STK_BASE, -alloc_size);
6190 } else if (s390_is_imm32 (alloc_size)) {
6191 s390_agfi (code, STK_BASE, -alloc_size);
6192 } else {
6193 int stackSize = alloc_size;
6194 while (stackSize > INT_MAX) {
6195 s390_agfi (code, STK_BASE, -INT_MAX);
6196 stackSize -= INT_MAX;
6198 s390_agfi (code, STK_BASE, -stackSize);
6200 s390_stg (code, s390_r11, 0, STK_BASE, 0);
6202 if (fpOffset > 0) {
6203 int stkOffset = 0;
6205 s390_lgr (code, s390_r1, s390_r11);
6206 s390_aghi (code, s390_r1, -fpOffset);
6207 for (int i=8; i<16; i++) {
6208 if (cfg->arch.used_fp_regs & (1 << i)) {
6209 emit_unwind_regs(cfg, code, 16+i, 16+i, stkOffset+fpOffset);
6210 s390_std (code, i, 0, s390_r1, stkOffset);
6211 stkOffset += sizeof(double);
6216 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
6218 if (cfg->frame_reg != STK_BASE)
6219 s390_lgr (code, s390_r11, STK_BASE);
6221 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
6223 /* store runtime generic context */
6224 if (cfg->rgctx_var) {
6225 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
6227 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
6228 cfg->rgctx_var->inst_basereg,
6229 cfg->rgctx_var->inst_offset);
6232 /* compute max_offset in order to use short forward jumps
6233 * we always do it on s390 because the immediate displacement
6234 * for jumps is too small
6236 max_offset = 0;
6237 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6238 MonoInst *ins;
6239 bb->max_offset = max_offset;
6241 MONO_BB_FOR_EACH_INS (bb, ins)
6242 max_offset += ins_get_size (ins->opcode);
6245 /* load arguments allocated to register from the stack */
6246 sig = mono_method_signature (method);
6247 pos = 0;
6249 cinfo = get_call_info (cfg->mempool, sig);
6251 if (cinfo->struct_ret) {
6252 ArgInfo *ainfo = &cinfo->ret;
6253 inst = cfg->vret_addr;
6254 inst->backend.size = ainfo->vtsize;
6255 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6258 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6259 ArgInfo *ainfo = cinfo->args + i;
6260 inst = cfg->args [pos];
6262 if (inst->opcode == OP_VTARG_ADDR)
6263 inst = inst->inst_left;
6265 if (inst->opcode == OP_REGVAR) {
6266 if (ainfo->regtype == RegTypeGeneral)
6267 s390_lgr (code, inst->dreg, ainfo->reg);
6268 else if (ainfo->regtype == RegTypeFP) {
6269 if (inst->dreg != ainfo->reg) {
6270 s390_ldr (code, inst->dreg, ainfo->reg);
6272 } else if (ainfo->regtype == RegTypeFPR4) {
6273 if (!cfg->r4fp)
6274 s390_ledbr (code, inst->dreg, ainfo->reg);
6275 } else if (ainfo->regtype == RegTypeBase) {
6276 s390_lgr (code, s390_r13, STK_BASE);
6277 s390_aghi (code, s390_r13, alloc_size);
6278 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
6279 } else
6280 g_assert_not_reached ();
6282 if (cfg->verbose_level > 2)
6283 g_print ("Argument %d assigned to register %s\n",
6284 pos, mono_arch_regname (inst->dreg));
6285 } else {
6286 if (ainfo->regtype == RegTypeGeneral) {
6287 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
6288 g_assert_not_reached();
6289 switch (ainfo->size) {
6290 case 1:
6291 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6292 break;
6293 case 2:
6294 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6295 break;
6296 case 4:
6297 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6298 break;
6299 case 8:
6300 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6301 break;
6303 } else if (ainfo->regtype == RegTypeBase) {
6304 } else if (ainfo->regtype == RegTypeFP) {
6305 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6306 } else if (ainfo->regtype == RegTypeFPR4) {
6307 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6308 } else if (ainfo->regtype == RegTypeStructByVal) {
6309 int doffset = inst->inst_offset;
6310 int reg;
6311 if (ainfo->reg != STK_BASE)
6312 reg = ainfo->reg;
6313 else {
6314 reg = s390_r0;
6315 s390_lgr (code, s390_r13, STK_BASE);
6316 s390_aghi (code, s390_r13, alloc_size);
6319 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
6320 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
6321 : ainfo->size);
6323 switch (size) {
6324 case 1:
6325 if (ainfo->reg == STK_BASE)
6326 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
6327 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
6328 break;
6329 case 2:
6330 if (ainfo->reg == STK_BASE)
6331 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
6332 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
6333 break;
6334 case 4:
6335 if (ainfo->reg == STK_BASE)
6336 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
6337 s390_st (code, reg, 0, inst->inst_basereg, doffset);
6338 break;
6339 case 8:
6340 if (ainfo->reg == STK_BASE)
6341 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
6342 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
6343 break;
6345 } else if (ainfo->regtype == RegTypeStructByAddr) {
6346 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6347 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
6348 } else
6349 g_assert_not_reached ();
6351 pos++;
6354 if (method->save_lmf) {
6355 /*---------------------------------------------------------------*/
6356 /* build the MonoLMF structure on the stack - see mini-s390x.h */
6357 /*---------------------------------------------------------------*/
6358 lmfOffset = alloc_size - sizeof(MonoLMF);
6360 s390_lgr (code, s390_r13, cfg->frame_reg);
6361 s390_aghi (code, s390_r13, lmfOffset);
6363 /*---------------------------------------------------------------*/
6364 /* Preserve the parameter registers while we fix up the lmf */
6365 /*---------------------------------------------------------------*/
6366 s390_stmg (code, s390_r2, s390_r6, s390_r13,
6367 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6369 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
6370 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
6371 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
6372 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
6373 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
6375 /*---------------------------------------------------------------*/
6376 /* On return from this call r2 have the address of the &lmf */
6377 /*---------------------------------------------------------------*/
6378 mono_add_patch_info (cfg, code - cfg->native_code,
6379 MONO_PATCH_INFO_INTERNAL_METHOD,
6380 (gpointer)"mono_tls_get_lmf_addr");
6381 S390_CALL_TEMPLATE(code, s390_r1);
6383 /*---------------------------------------------------------------*/
6384 /* Set lmf.lmf_addr = jit_tls->lmf */
6385 /*---------------------------------------------------------------*/
6386 s390_stg (code, s390_r2, 0, s390_r13,
6387 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
6388 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
6390 /*---------------------------------------------------------------*/
6391 /* Get current lmf */
6392 /*---------------------------------------------------------------*/
6393 s390_lg (code, s390_r0, 0, s390_r2, 0);
6395 /*---------------------------------------------------------------*/
6396 /* Set our lmf as the current lmf */
6397 /*---------------------------------------------------------------*/
6398 s390_stg (code, s390_r13, 0, s390_r2, 0);
6400 /*---------------------------------------------------------------*/
6401 /* Have our lmf.previous_lmf point to the last lmf */
6402 /*---------------------------------------------------------------*/
6403 s390_stg (code, s390_r0, 0, s390_r13,
6404 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
6405 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
6407 /*---------------------------------------------------------------*/
6408 /* save method info */
6409 /*---------------------------------------------------------------*/
6410 S390_SET (code, s390_r1, method);
6411 s390_stg (code, s390_r1, 0, s390_r13,
6412 G_STRUCT_OFFSET(MonoLMF, method));
6413 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
6415 /*---------------------------------------------------------------*/
6416 /* save the current IP */
6417 /*---------------------------------------------------------------*/
6418 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
6419 s390_basr (code, s390_r1, 0);
6420 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
6421 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
6422 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
6424 /*---------------------------------------------------------------*/
6425 /* Save general and floating point registers */
6426 /*---------------------------------------------------------------*/
6427 s390_stmg (code, s390_r2, s390_r12, s390_r13,
6428 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
6429 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
6430 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
6431 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
6432 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
6433 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
6434 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
6435 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
6436 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
6437 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
6438 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
6439 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
6441 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
6442 for (i = 0; i < 16; i++) {
6443 s390_std (code, i, 0, s390_r13,
6444 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
6445 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
6446 fpOffset += sizeof(double);
6449 /*---------------------------------------------------------------*/
6450 /* Restore the parameter registers now that we've set up the lmf */
6451 /*---------------------------------------------------------------*/
6452 s390_lmg (code, s390_r2, s390_r6, s390_r13,
6453 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6456 if (cfg->method->save_lmf)
6457 argsClobbered = TRUE;
6459 if (tracing) {
6460 argsClobbered = TRUE;
6461 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
6465 * Optimize the common case of the first bblock making a call with the same
6466 * arguments as the method. This works because the arguments are still in their
6467 * original argument registers.
6469 if (!argsClobbered) {
6470 MonoBasicBlock *first_bb = cfg->bb_entry;
6471 MonoInst *next;
6472 int filter = FILTER_IL_SEQ_POINT;
6474 next = mono_bb_first_inst (first_bb, filter);
6475 if (!next && first_bb->next_bb) {
6476 first_bb = first_bb->next_bb;
6477 next = mono_bb_first_inst (first_bb, filter);
6480 if (first_bb->in_count > 1)
6481 next = NULL;
6483 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
6484 ArgInfo *ainfo = cinfo->args + i;
6485 gboolean match = FALSE;
6487 inst = cfg->args [i];
6488 if (inst->opcode != OP_REGVAR) {
6489 switch (ainfo->regtype) {
6490 case RegTypeGeneral: {
6491 if (((next->opcode == OP_LOAD_MEMBASE) ||
6492 (next->opcode == OP_LOADI4_MEMBASE)) &&
6493 next->inst_basereg == inst->inst_basereg &&
6494 next->inst_offset == inst->inst_offset) {
6495 if (next->dreg == ainfo->reg) {
6496 NULLIFY_INS (next);
6497 match = TRUE;
6498 } else {
6499 next->opcode = OP_MOVE;
6500 next->sreg1 = ainfo->reg;
6501 /* Only continue if the instruction doesn't change argument regs */
6502 if (next->dreg == ainfo->reg)
6503 match = TRUE;
6506 break;
6508 default:
6509 break;
6511 } else {
6512 /* Argument allocated to (non-volatile) register */
6513 switch (ainfo->regtype) {
6514 case RegTypeGeneral:
6515 if (next->opcode == OP_MOVE &&
6516 next->sreg1 == inst->dreg &&
6517 next->dreg == ainfo->reg) {
6518 NULLIFY_INS (next);
6519 match = TRUE;
6521 break;
6522 default:
6523 break;
6527 if (match) {
6528 next = mono_inst_next (next, filter);
6529 if (!next)
6530 break;
6535 set_code_cursor (cfg, code);
6537 return code;
6540 /*========================= End of Function ========================*/
6542 /*------------------------------------------------------------------*/
6543 /* */
6544 /* Name - mono_arch_emit_epilog */
6545 /* */
6546 /* Function - Emit the instructions for a function epilog. */
6547 /* */
6548 /*------------------------------------------------------------------*/
6550 void
6551 mono_arch_emit_epilog (MonoCompile *cfg)
6553 MonoMethod *method = cfg->method;
6554 int tracing = 0;
6555 guint8 *code;
6556 int max_epilog_size = 96;
6557 int fpOffset = 0;
6559 if (cfg->method->save_lmf)
6560 max_epilog_size += 128;
6562 if (mono_jit_trace_calls != NULL)
6563 max_epilog_size += 128;
6565 code = realloc_code (cfg, max_epilog_size);
6567 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6568 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6569 tracing = 1;
6572 if (method->save_lmf)
6573 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6575 code = backUpStackPtr(cfg, code);
6577 if (cfg->arch.fpSize != 0) {
6578 fpOffset = -cfg->arch.fpSize;
6579 for (int i=8; i<16; i++) {
6580 if (cfg->arch.used_fp_regs & (1 << i)) {
6581 s390_ldy (code, i, 0, STK_BASE, fpOffset);
6582 fpOffset += sizeof(double);
6587 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6588 s390_br (code, s390_r14);
6590 set_code_cursor (cfg, code);
6594 /*========================= End of Function ========================*/
6596 /*------------------------------------------------------------------*/
6597 /* */
6598 /* Name - mono_arch_emit_exceptions */
6599 /* */
6600 /* Function - Emit the blocks to handle exception conditions. */
6601 /* */
6602 /*------------------------------------------------------------------*/
6604 void
6605 mono_arch_emit_exceptions (MonoCompile *cfg)
6607 MonoJumpInfo *patch_info;
6608 guint8 *code;
6609 int nThrows = 0,
6610 exc_count = 0,
6611 iExc;
6612 guint32 code_size;
6613 MonoClass *exc_classes [MAX_EXC];
6614 guint8 *exc_throw_start [MAX_EXC];
6616 for (patch_info = cfg->patch_info;
6617 patch_info;
6618 patch_info = patch_info->next) {
6619 if (patch_info->type == MONO_PATCH_INFO_EXC)
6620 exc_count++;
6623 code_size = exc_count * 48;
6625 code = realloc_code (cfg, code_size);
6627 /*---------------------------------------------------------------------*/
6628 /* Add code to raise exceptions */
6629 /*---------------------------------------------------------------------*/
6630 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6631 switch (patch_info->type) {
6632 case MONO_PATCH_INFO_EXC: {
6633 guint8 *ip = patch_info->ip.i + cfg->native_code;
6634 MonoClass *exc_class;
6635 guint64 throw_ip;
6637 /*-----------------------------------------------------*/
6638 /* Patch the branch in epilog to come here */
6639 /*-----------------------------------------------------*/
6640 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6642 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6643 "System",
6644 patch_info->data.name);
6645 throw_ip = patch_info->ip.i;
6647 for (iExc = 0; iExc < nThrows; ++iExc)
6648 if (exc_classes [iExc] == exc_class)
6649 break;
6651 if (iExc < nThrows) {
6652 s390_jcl (code, S390_CC_UN,
6653 (guint64) exc_throw_start [iExc]);
6654 patch_info->type = MONO_PATCH_INFO_NONE;
6655 } else {
6657 if (nThrows < MAX_EXC) {
6658 exc_classes [nThrows] = exc_class;
6659 exc_throw_start [nThrows] = code;
6662 /*---------------------------------------------*/
6663 /* Patch the parameter passed to the handler */
6664 /*---------------------------------------------*/
6665 S390_SET (code, s390_r2, m_class_get_type_token (exc_class));
6666 /*---------------------------------------------*/
6667 /* Load return address & parameter register */
6668 /*---------------------------------------------*/
6669 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6670 cfg->native_code + 8), code));
6671 /*---------------------------------------------*/
6672 /* Reuse the current patch to set the jump */
6673 /*---------------------------------------------*/
6674 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6675 patch_info->data.name = "mono_arch_throw_corlib_exception";
6676 patch_info->ip.i = code - cfg->native_code;
6677 S390_BR_TEMPLATE (code, s390_r1);
6679 break;
6681 default:
6682 /* do nothing */
6683 break;
6686 set_code_cursor (cfg, code);
6689 /*========================= End of Function ========================*/
6691 /*------------------------------------------------------------------*/
6692 /* */
6693 /* Name - mono_arch_finish_init */
6694 /* */
6695 /* Function - Setup the JIT's Thread Level Specific Data. */
6696 /* */
6697 /*------------------------------------------------------------------*/
6699 void
6700 mono_arch_finish_init (void)
6704 /*========================= End of Function ========================*/
6706 /*------------------------------------------------------------------*/
6707 /* */
6708 /* Name - mono_arch_free_jit_tls_data */
6709 /* */
6710 /* Function - Free tls data. */
6711 /* */
6712 /*------------------------------------------------------------------*/
6714 void
6715 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6719 /*========================= End of Function ========================*/
6721 /*------------------------------------------------------------------*/
6722 /* */
6723 /* Name - mono_arch_emit_inst_for_method */
6724 /* */
6725 /*------------------------------------------------------------------*/
6727 MonoInst*
6728 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6730 return NULL;
6733 /*========================= End of Function ========================*/
6735 /*------------------------------------------------------------------*/
6736 /* */
6737 /* Name - mono_arch_decompose_opts */
6738 /* */
6739 /* Function - Decompose opcode into a System z opcode. */
6740 /* */
6741 /*------------------------------------------------------------------*/
6743 void
6744 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6747 * Have to rename these to avoid being decomposed normally, since the normal
6748 * decomposition does not work on S390.
6750 switch (ins->opcode) {
6751 case OP_ISUB_OVF:
6752 ins->opcode = OP_S390_ISUB_OVF;
6753 break;
6754 case OP_ISUB_OVF_UN:
6755 ins->opcode = OP_S390_ISUB_OVF_UN;
6756 break;
6757 case OP_IADD_OVF:
6758 ins->opcode = OP_S390_IADD_OVF;
6759 break;
6760 case OP_IADD_OVF_UN:
6761 ins->opcode = OP_S390_IADD_OVF_UN;
6762 break;
6763 case OP_LADD_OVF:
6764 ins->opcode = OP_S390_LADD_OVF;
6765 break;
6766 case OP_LADD_OVF_UN:
6767 ins->opcode = OP_S390_LADD_OVF_UN;
6768 break;
6769 case OP_LSUB_OVF:
6770 ins->opcode = OP_S390_LSUB_OVF;
6771 break;
6772 case OP_LSUB_OVF_UN:
6773 ins->opcode = OP_S390_LSUB_OVF_UN;
6774 break;
6775 default:
6776 break;
6780 /*========================= End of Function ========================*/
6782 /*------------------------------------------------------------------*/
6783 /* */
6784 /* Name - mono_arch_regalloc_cost */
6785 /* */
6786 /* Function - Determine the cost, in the number of memory */
6787 /* references, of the action of allocating the var- */
6788 /* iable VMV into a register during global register */
6789 /* allocation. */
6790 /* */
6791 /* Returns - Cost */
6792 /* */
6793 /*------------------------------------------------------------------*/
6795 guint32
6796 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6798 /* FIXME: */
6799 return 2;
6802 /*========================= End of Function ========================*/
6804 /*------------------------------------------------------------------*/
6805 /* */
6806 /* Name - mono_arch_flush_register_windows */
6807 /* */
6808 /* Function - */
6809 /* */
6810 /* Returns - */
6811 /* */
6812 /*------------------------------------------------------------------*/
6814 void
6815 mono_arch_flush_register_windows (void)
6819 /*========================= End of Function ========================*/
6821 /*------------------------------------------------------------------*/
6822 /* */
6823 /* Name - mono_arch_is_inst_imm */
6824 /* */
6825 /* Function - Determine if operand qualifies as an immediate */
6826 /* value. For s390 this is a value -32768-32768 */
6827 /* */
6828 /* Returns - True|False - is [not] immediate value. */
6829 /* */
6830 /*------------------------------------------------------------------*/
6832 gboolean
6833 mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm)
6835 return s390_is_imm32 (imm);
6838 /*========================= End of Function ========================*/
6840 /*------------------------------------------------------------------*/
6841 /* */
6842 /* Name - mono_arch_get_patch_offset */
6843 /* */
6844 /* Function - Dummy entry point until s390x supports aot. */
6845 /* */
6846 /* Returns - Offset for patch. */
6847 /* */
6848 /*------------------------------------------------------------------*/
6850 guint32
6851 mono_arch_get_patch_offset (guint8 *code)
6853 return 0;
6856 /*========================= End of Function ========================*/
6858 /*------------------------------------------------------------------*/
6859 /* */
6860 /* Name - mono_arch_context_get_int_reg. */
6861 /* */
6862 /* Function - */
6863 /* */
6864 /* Returns - Return a register from the context. */
6865 /* */
6866 /*------------------------------------------------------------------*/
6868 mgreg_t
6869 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6871 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6874 /*========================= End of Function ========================*/
6876 /*------------------------------------------------------------------*/
6877 /* */
6878 /* Name - mono_arch_context_set_int_reg. */
6879 /* */
6880 /* Function - Set a value in a specified register. */
6881 /* */
6882 /*------------------------------------------------------------------*/
6884 void
6885 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6887 ctx->uc_mcontext.gregs[reg] = val;
6890 /*========================= End of Function ========================*/
6892 /*------------------------------------------------------------------*/
6893 /* */
6894 /* Name - mono_arch_get_this_arg_from_call. */
6895 /* */
6896 /* Function - */
6897 /* */
6898 /*------------------------------------------------------------------*/
6900 gpointer
6901 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6903 return (gpointer) regs [s390_r2];
6906 /*========================= End of Function ========================*/
6908 /*------------------------------------------------------------------*/
6909 /* */
6910 /* Name - get_delegate_invoke_impl. */
6911 /* */
6912 /* Function - */
6913 /* */
6914 /*------------------------------------------------------------------*/
6916 static gpointer
6917 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6919 guint8 *code, *start;
6921 if (has_target) {
6922 int size = 32;
6924 start = code = mono_global_codeman_reserve (size);
6926 /* Replace the this argument with the target */
6927 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6928 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6929 s390_br (code, s390_r1);
6930 g_assert ((code - start) <= size);
6932 mono_arch_flush_icache (start, size);
6933 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
6934 } else {
6935 int size, i;
6937 size = 32 + param_count * 8;
6938 start = code = mono_global_codeman_reserve (size);
6940 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6941 /* slide down the arguments */
6942 for (i = 0; i < param_count; ++i) {
6943 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6945 s390_br (code, s390_r1);
6947 g_assert ((code - start) <= size);
6949 mono_arch_flush_icache (start, size);
6950 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
6953 if (has_target) {
6954 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6955 } else {
6956 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6957 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6958 g_free (name);
6961 return start;
6964 /*========================= End of Function ========================*/
6966 /*------------------------------------------------------------------*/
6967 /* */
6968 /* Name - mono_arch_get_delegate_invoke_impls. */
6969 /* */
6970 /* Function - */
6971 /* */
6972 /*------------------------------------------------------------------*/
6974 GSList*
6975 mono_arch_get_delegate_invoke_impls (void)
6977 GSList *res = NULL;
6978 MonoTrampInfo *info;
6979 int i;
6981 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6982 res = g_slist_prepend (res, info);
6984 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6985 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6986 res = g_slist_prepend (res, info);
6989 return res;
6992 /*========================= End of Function ========================*/
6994 /*------------------------------------------------------------------*/
6995 /* */
6996 /* Name - mono_arch_get_delegate_invoke_impl. */
6997 /* */
6998 /* Function - */
6999 /* */
7000 /*------------------------------------------------------------------*/
7002 gpointer
7003 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
7005 guint8 *code, *start;
7007 /* FIXME: Support more cases */
7008 if (MONO_TYPE_ISSTRUCT (sig->ret))
7009 return NULL;
7011 if (has_target) {
7012 static guint8* cached = NULL;
7014 if (cached)
7015 return cached;
7017 if (mono_ee_features.use_aot_trampolines) {
7018 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
7019 } else {
7020 MonoTrampInfo *info;
7021 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
7022 mono_tramp_info_register (info, NULL);
7025 mono_memory_barrier ();
7027 cached = start;
7028 } else {
7029 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
7030 int i;
7032 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
7033 return NULL;
7034 for (i = 0; i < sig->param_count; ++i)
7035 if (!mono_is_regsize_var (sig->params [i]))
7036 return NULL;
7039 code = cache [sig->param_count];
7040 if (code)
7041 return code;
7043 if (mono_ee_features.use_aot_trampolines) {
7044 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
7045 start = mono_aot_get_trampoline (name);
7046 g_free (name);
7047 } else {
7048 MonoTrampInfo *info;
7049 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
7050 mono_tramp_info_register (info, NULL);
7053 mono_memory_barrier ();
7055 cache [sig->param_count] = start;
7057 return start;
7060 /*========================= End of Function ========================*/
7062 /*------------------------------------------------------------------*/
7063 /* */
7064 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
7065 /* */
7066 /* Function - */
7067 /* */
7068 /*------------------------------------------------------------------*/
7070 gpointer
7071 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
7072 int offset, gboolean load_imt_reg)
7074 guint8 *code, *start;
7075 int size = 40;
7077 start = code = mono_global_codeman_reserve (size);
7080 * Replace the "this" argument with the target
7082 s390_lgr (code, s390_r1, s390_r2);
7083 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
7086 * Load the IMT register, if needed
7088 if (load_imt_reg) {
7089 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
7093 * Load the vTable
7095 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
7096 if (offset != 0) {
7097 s390_agfi(code, s390_r1, offset);
7099 s390_lg (code, s390_r1, 0, s390_r1, 0);
7100 s390_br (code, s390_r1);
7102 mono_arch_flush_icache (start, code - start);
7103 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
7105 return(start);
7108 /*========================= End of Function ========================*/
7110 /*------------------------------------------------------------------*/
7111 /* */
7112 /* Name - mono_arch_build_imt_trampoline. */
7113 /* */
7114 /* Function - */
7115 /* */
7116 /*------------------------------------------------------------------*/
7118 gpointer
7119 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
7120 MonoIMTCheckItem **imt_entries, int count,
7121 gpointer fail_tramp)
7123 int i;
7124 int size = 0;
7125 guchar *code, *start;
7126 char trampName[64];
7128 for (i = 0; i < count; ++i) {
7129 MonoIMTCheckItem *item = imt_entries [i];
7130 if (item->is_equals) {
7131 if (item->check_target_idx) {
7132 if (!item->compare_done)
7133 item->chunk_size += CMP_SIZE + JUMP_SIZE;
7134 if (item->has_target_code)
7135 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
7136 else
7137 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
7138 LOAD_SIZE;
7139 } else {
7140 if (fail_tramp) {
7141 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
7142 2 * LOADCON_SIZE;
7143 if (!item->has_target_code)
7144 item->chunk_size += LOAD_SIZE;
7145 } else {
7146 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
7147 #if ENABLE_WRONG_METHOD_CHECK
7148 item->chunk_size += CMP_SIZE + JUMP_SIZE;
7149 #endif
7152 } else {
7153 item->chunk_size += CMP_SIZE + JUMP_SIZE;
7154 imt_entries [item->check_target_idx]->compare_done = TRUE;
7156 size += item->chunk_size;
7159 if (fail_tramp)
7160 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
7161 else
7162 code = mono_domain_code_reserve (domain, size);
7164 start = code;
7166 for (i = 0; i < count; ++i) {
7167 MonoIMTCheckItem *item = imt_entries [i];
7168 item->code_target = (guint8 *) code;
7169 if (item->is_equals) {
7170 if (item->check_target_idx) {
7171 if (!item->compare_done) {
7172 S390_SET (code, s390_r0, item->key);
7173 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
7175 item->jmp_code = (guint8*) code;
7176 s390_jcl (code, S390_CC_NE, 0);
7178 if (item->has_target_code) {
7179 S390_SET (code, s390_r1, item->value.target_code);
7180 } else {
7181 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7182 s390_lg (code, s390_r1, 0, s390_r1, 0);
7184 s390_br (code, s390_r1);
7185 } else {
7186 if (fail_tramp) {
7187 gint64 target;
7189 S390_SET (code, s390_r0, item->key);
7190 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
7191 item->jmp_code = (guint8*) code;
7192 s390_jcl (code, S390_CC_NE, 0);
7193 if (item->has_target_code) {
7194 S390_SET (code, s390_r1, item->value.target_code);
7195 } else {
7196 g_assert (vtable);
7197 S390_SET (code, s390_r1,
7198 (&(vtable->vtable [item->value.vtable_slot])));
7199 s390_lg (code, s390_r1, 0, s390_r1, 0);
7201 s390_br (code, s390_r1);
7202 target = (gint64) S390_RELATIVE(code, item->jmp_code);
7203 s390_patch_rel(item->jmp_code+2, target);
7204 S390_SET (code, s390_r1, fail_tramp);
7205 s390_br (code, s390_r1);
7206 item->jmp_code = NULL;
7207 } else {
7208 /* enable the commented code to assert on wrong method */
7209 #if ENABLE_WRONG_METHOD_CHECK
7210 g_assert_not_reached ();
7211 #endif
7212 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7213 s390_lg (code, s390_r1, 0, s390_r1, 0);
7214 s390_br (code, s390_r1);
7217 } else {
7218 S390_SET (code, s390_r0, item->key);
7219 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
7220 item->jmp_code = (guint8 *) code;
7221 s390_jcl (code, S390_CC_GE, 0);
7225 * patch the branches to get to the target items
7227 for (i = 0; i < count; ++i) {
7228 MonoIMTCheckItem *item = imt_entries [i];
7229 if (item->jmp_code) {
7230 if (item->check_target_idx) {
7231 gint64 offset;
7232 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
7233 item->jmp_code);
7234 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
7239 mono_arch_flush_icache ((guint8*)start, (code - start));
7240 MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
7242 if (!fail_tramp)
7243 UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
7245 g_assert (code - start <= size);
7247 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
7248 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
7250 return (start);
7253 /*========================= End of Function ========================*/
7255 /*------------------------------------------------------------------*/
7256 /* */
7257 /* Name - mono_arch_find_imt_method. */
7258 /* */
7259 /* Function - Get the method address from MONO_ARCH_IMT_REG */
7260 /* found in the save area. */
7261 /* */
7262 /*------------------------------------------------------------------*/
7264 MonoMethod*
7265 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
7267 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
7270 /*========================= End of Function ========================*/
7272 /*------------------------------------------------------------------*/
7273 /* */
7274 /* Name - mono_arch_find_static_call_vtable */
7275 /* */
7276 /* Function - Find the static call vtable. */
7277 /* */
7278 /*------------------------------------------------------------------*/
7280 MonoVTable*
7281 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
7283 mgreg_t *r = (mgreg_t*)regs;
7285 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
7288 /*========================= End of Function ========================*/
7290 /*------------------------------------------------------------------*/
7291 /* */
7292 /* Name - mono_arch_get_cie_program */
7293 /* */
7294 /* Function - Find the static call vtable. */
7295 /* */
7296 /*------------------------------------------------------------------*/
7298 GSList*
7299 mono_arch_get_cie_program (void)
7301 GSList *l = NULL;
7303 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
7305 return(l);
7308 /*========================= End of Function ========================*/
7310 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7312 /*------------------------------------------------------------------*/
7313 /* */
7314 /* Name - mono_arch_set_breakpoint. */
7315 /* */
7316 /* Function - Set a breakpoint at the native code corresponding */
7317 /* to JI at NATIVE_OFFSET. The location should */
7318 /* contain code emitted by OP_SEQ_POINT. */
7319 /* */
7320 /*------------------------------------------------------------------*/
7322 void
7323 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
7325 guint8 *code = ip;
7327 breakpointCode.pTrigger = bp_trigger_page;
7328 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
7329 code += BREAKPOINT_SIZE;
7332 /*========================= End of Function ========================*/
7334 /*------------------------------------------------------------------*/
7335 /* */
7336 /* Name - mono_arch_clear_breakpoint. */
7337 /* */
7338 /* Function - Clear the breakpoint at IP. */
7339 /* */
7340 /*------------------------------------------------------------------*/
7342 void
7343 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
7345 guint8 *code = ip;
7346 int i;
7348 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
7349 s390_nop(code);
7352 /*========================= End of Function ========================*/
7354 /*------------------------------------------------------------------*/
7355 /* */
7356 /* Name - mono_arch_is_breakpoint_event. */
7357 /* */
7358 /* Function - */
7359 /* */
7360 /*------------------------------------------------------------------*/
7362 gboolean
7363 mono_arch_is_breakpoint_event (void *info, void *sigctx)
7365 siginfo_t* sinfo = (siginfo_t*) info;
7368 * Sometimes the address is off by 4
7370 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
7371 return TRUE;
7372 else
7373 return FALSE;
7376 /*========================= End of Function ========================*/
7378 /*------------------------------------------------------------------*/
7379 /* */
7380 /* Name - mono_arch_skip_breakpoint. */
7381 /* */
7382 /* Function - Modify the CTX so the IP is placed after the */
7383 /* breakpoint instruction, so when we resume, the */
7384 /* instruction is not executed again. */
7385 /* */
7386 /*------------------------------------------------------------------*/
7388 void
7389 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
7391 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
7394 /*========================= End of Function ========================*/
7396 /*------------------------------------------------------------------*/
7397 /* */
7398 /* Name - mono_arch_start_single_stepping. */
7399 /* */
7400 /* Function - Start single stepping. */
7401 /* */
7402 /*------------------------------------------------------------------*/
7404 void
7405 mono_arch_start_single_stepping (void)
7407 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
7410 /*========================= End of Function ========================*/
7412 /*------------------------------------------------------------------*/
7413 /* */
7414 /* Name - mono_arch_stop_single_stepping. */
7415 /* */
7416 /* Function - Stop single stepping. */
7417 /* */
7418 /*------------------------------------------------------------------*/
7420 void
7421 mono_arch_stop_single_stepping (void)
7423 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
7426 /*========================= End of Function ========================*/
7428 /*------------------------------------------------------------------*/
7429 /* */
7430 /* Name - mono_arch_is_single_step_event. */
7431 /* */
7432 /* Function - Return whether the machine state in sigctx cor- */
7433 /* responds to a single step event. */
7434 /* */
7435 /*------------------------------------------------------------------*/
7437 gboolean
7438 mono_arch_is_single_step_event (void *info, void *sigctx)
7440 siginfo_t* sinfo = (siginfo_t*) info;
7443 * Sometimes the address is off by 4
7445 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7446 return TRUE;
7447 else
7448 return FALSE;
7451 /*========================= End of Function ========================*/
7453 /*------------------------------------------------------------------*/
7454 /* */
7455 /* Name - mono_arch_skip_single_step. */
7456 /* */
7457 /* Function - Modify the ctx so the IP is placed after the */
7458 /* single step trigger instruction, so that the */
7459 /* instruction is not executed again. */
7460 /* */
7461 /*------------------------------------------------------------------*/
7463 void
7464 mono_arch_skip_single_step (MonoContext *ctx)
7466 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7469 /*========================= End of Function ========================*/
7471 /*------------------------------------------------------------------*/
7472 /* */
7473 /* Name - mono_arch_create_seq_point_info. */
7474 /* */
7475 /* Function - Return a pointer to a data struction which is */
7476 /* used by the sequence point implementation in */
7477 /* AOTed code. */
7478 /* */
7479 /*------------------------------------------------------------------*/
7481 gpointer
7482 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7484 NOT_IMPLEMENTED;
7485 return NULL;
7488 /*========================= End of Function ========================*/
7490 #endif
7492 /*------------------------------------------------------------------*/
7493 /* */
7494 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7495 /* */
7496 /* Function - If this CPU supports vector operations then it */
7497 /* supports the equivalent of SSE1-4. */
7498 /* */
7499 /*------------------------------------------------------------------*/
7501 guint32
7502 mono_arch_cpu_enumerate_simd_versions (void)
7504 guint32 sseOpts = 0;
7506 if (mono_hwcap_s390x_has_vec)
7507 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7508 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7509 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7510 SIMD_VERSION_SSE4a);
7512 return (sseOpts);
7515 /*========================= End of Function ========================*/
7517 /*------------------------------------------------------------------*/
7518 /* */
7519 /* Name - mono_arch_opcode_supported. */
7520 /* */
7521 /* Function - Check if a given op code is supported. */
7522 /* */
7523 /*------------------------------------------------------------------*/
7525 gboolean
7526 mono_arch_opcode_supported (int opcode)
7528 switch (opcode) {
7529 case OP_ATOMIC_ADD_I4:
7530 case OP_ATOMIC_ADD_I8:
7531 case OP_ATOMIC_EXCHANGE_I4:
7532 case OP_ATOMIC_EXCHANGE_I8:
7533 return TRUE;
7534 default:
7535 return FALSE;
7539 /*========================= End of Function ========================*/
7541 /*------------------------------------------------------------------*/
7542 /* */
7543 /* Name - mono_arch_tailcall_supported. */
7544 /* */
7545 /* Function - Check if a tailcall is supported. */
7546 /* */
7547 /*------------------------------------------------------------------*/
7549 static const gboolean debug_tailcall = FALSE;
7551 static gboolean
7552 is_supported_tailcall_helper (gboolean value, const char *svalue)
7554 if (!value && debug_tailcall)
7555 g_print ("%s %s\n", __func__, svalue);
7556 return value;
7559 #define IS_SUPPORTED_TAILCALL(x) (is_supported_tailcall_helper((x), #x))
7561 gboolean
7562 mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig)
7564 g_assert (caller_sig);
7565 g_assert (callee_sig);
7567 CallInfo *caller_info = get_call_info (NULL, caller_sig);
7568 CallInfo *callee_info = get_call_info (NULL, callee_sig);
7570 gboolean res = IS_SUPPORTED_TAILCALL (callee_info->stack_usage <= caller_info->stack_usage)
7571 && IS_SUPPORTED_TAILCALL (callee_info->struct_ret == caller_info->struct_ret)
7572 && IS_SUPPORTED_TAILCALL (memcmp (&callee_info->ret, &caller_info->ret, sizeof (caller_info->ret)) == 0);
7574 // valuetypes passed semantic-byvalue ABI-byref are often to a local.
7575 // FIXME ABIs vary as to if this local is in the parameter area or not,
7576 // so this check might not be needed.
7577 ArgInfo const * const ainfo = callee_info->args + callee_sig->hasthis;
7578 for (int i = 0; res && i < callee_sig->param_count; ++i) {
7579 res = IS_SUPPORTED_TAILCALL (ainfo [i].regtype != RegTypeStructByAddr)
7580 && IS_SUPPORTED_TAILCALL (ainfo [i].regtype != RegTypeStructByAddrOnStack);
7583 g_free (caller_info);
7584 g_free (callee_info);
7586 return res;
7589 /*========================= End of Function ========================*/