[ci] Bump timeout in ms-test-suite
[mono-project.git] / mono / mini / mini-s390x.c
blobc3f763ac5d0670b23b3a9373ff2f428f730ece1a
1 /*------------------------------------------------------------------*/
2 /* */
3 /* Name - mini-s390.c */
4 /* */
5 /* Function - S/390 backend for the Mono code generator. */
6 /* */
7 /* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
8 /* */
9 /* Date - January, 2004 */
10 /* */
11 /* Derivation - From mini-x86 & mini-ppc by - */
12 /* Paolo Molaro (lupus@ximian.com) */
13 /* Dietmar Maurer (dietmar@ximian.com) */
14 /* */
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
18 /* D e f i n e s */
19 /*------------------------------------------------------------------*/
21 #define MAX_ARCH_DELEGATE_PARAMS 7
23 #define EMIT_COND_BRANCH(ins,cond) \
24 { \
25 if (ins->inst_true_bb->native_offset) { \
26 int displace; \
27 displace = ((cfg->native_code + \
28 ins->inst_true_bb->native_offset) - code) / 2; \
29 if (s390_is_imm16(displace)) { \
30 s390_brc (code, cond, displace); \
31 } else { \
32 s390_jcl (code, cond, displace); \
33 } \
34 } else { \
35 mono_add_patch_info (cfg, code - cfg->native_code, \
36 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
37 s390_jcl (code, cond, 0); \
38 } \
41 #define EMIT_UNCOND_BRANCH(ins) \
42 { \
43 if (ins->inst_target_bb->native_offset) { \
44 int displace; \
45 displace = ((cfg->native_code + \
46 ins->inst_target_bb->native_offset) - code) / 2; \
47 if (s390_is_imm16(displace)) { \
48 s390_brc (code, S390_CC_UN, displace); \
49 } else { \
50 s390_jcl (code, S390_CC_UN, displace); \
51 } \
52 } else { \
53 mono_add_patch_info (cfg, code - cfg->native_code, \
54 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
55 s390_jcl (code, S390_CC_UN, 0); \
56 } \
59 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
60 do { \
61 mono_add_patch_info (cfg, code - cfg->native_code, \
62 MONO_PATCH_INFO_EXC, exc_name); \
63 s390_jcl (code, cond, 0); \
64 } while (0);
66 #define CHECK_SRCDST_COM \
67 if (ins->dreg == ins->sreg2) { \
68 src2 = ins->sreg1; \
69 } else { \
70 src2 = ins->sreg2; \
71 if (ins->dreg != ins->sreg1) { \
72 s390_lgr (code, ins->dreg, ins->sreg1); \
73 } \
76 #define CHECK_SRCDST_NCOM \
77 if (ins->dreg == ins->sreg2) { \
78 src2 = s390_r13; \
79 s390_lgr (code, s390_r13, ins->sreg2); \
80 } else { \
81 src2 = ins->sreg2; \
82 } \
83 if (ins->dreg != ins->sreg1) { \
84 s390_lgr (code, ins->dreg, ins->sreg1); \
87 #define CHECK_SRCDST_COM_I \
88 if (ins->dreg == ins->sreg2) { \
89 src2 = ins->sreg1; \
90 } else { \
91 src2 = ins->sreg2; \
92 if (ins->dreg != ins->sreg1) { \
93 s390_lgfr (code, ins->dreg, ins->sreg1); \
94 } \
97 #define CHECK_SRCDST_NCOM_I \
98 if (ins->dreg == ins->sreg2) { \
99 src2 = s390_r13; \
100 s390_lgfr (code, s390_r13, ins->sreg2); \
101 } else { \
102 src2 = ins->sreg2; \
104 if (ins->dreg != ins->sreg1) { \
105 s390_lgfr (code, ins->dreg, ins->sreg1); \
108 #define CHECK_SRCDST_COM_F \
109 if (ins->dreg == ins->sreg2) { \
110 src2 = ins->sreg1; \
111 } else { \
112 src2 = ins->sreg2; \
113 if (ins->dreg != ins->sreg1) { \
114 s390_ldr (code, ins->dreg, ins->sreg1); \
118 #define CHECK_SRCDST_NCOM_F \
119 if (ins->dreg == ins->sreg2) { \
120 src2 = s390_f15; \
121 s390_ldr (code, s390_r13, ins->sreg2); \
122 } else { \
123 src2 = ins->sreg2; \
125 if (ins->dreg != ins->sreg1) { \
126 s390_ldr (code, ins->dreg, ins->sreg1); \
129 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
130 MonoInst *inst; \
131 int sReg, dReg; \
132 MONO_INST_NEW (cfg, inst, OP_NOP); \
133 if (size > 256) { \
134 inst->dreg = dest; \
135 inst->inst_offset = offset; \
136 inst->sreg1 = src; \
137 inst->inst_imm = imm; \
138 } else { \
139 if (s390_is_uimm12(offset)) { \
140 inst->dreg = dest; \
141 inst->inst_offset = offset; \
142 } else { \
143 dReg = mono_alloc_preg (cfg); \
144 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
145 dReg, dest, offset); \
146 inst->dreg = dReg; \
147 inst->inst_offset = 0; \
149 if (s390_is_uimm12(imm)) { \
150 inst->sreg1 = src; \
151 inst->inst_imm = imm; \
152 } else { \
153 sReg = mono_alloc_preg (cfg); \
154 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
155 sReg, src, imm); \
156 inst->sreg1 = sReg; \
157 inst->inst_imm = 0; \
160 inst->opcode = OP_S390_MOVE; \
161 inst->backend.size = size; \
162 MONO_ADD_INS (cfg->cbb, inst); \
163 } while (0)
165 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
166 int reg = mono_alloc_preg (cfg); \
167 switch (size) { \
168 case 0: \
169 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
170 break; \
171 case 1: \
172 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
173 reg, sr, so); \
174 break; \
175 case 2: \
176 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
177 reg, sr, so); \
178 break; \
179 case 4: \
180 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
181 reg, sr, so); \
182 break; \
183 case 8: \
184 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
185 reg, sr, so); \
186 break; \
188 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
189 } while (0)
191 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
192 int tmpr; \
193 switch (size) { \
194 case 0: \
195 tmpr = mono_alloc_preg (cfg); \
196 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
197 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
198 dr, dx, tmpr); \
199 break; \
200 case 1: \
201 tmpr = mono_alloc_preg (cfg); \
202 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
203 tmpr, sr, so); \
204 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
205 dr, dx, tmpr); \
206 break; \
207 case 2: \
208 tmpr = mono_alloc_preg (cfg); \
209 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
210 tmpr, sr, so); \
211 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
212 dr, dx, tmpr); \
213 break; \
214 case 4: \
215 tmpr = mono_alloc_preg (cfg); \
216 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
217 tmpr, sr, so); \
218 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
219 dr, dx, tmpr); \
220 break; \
221 case 8: \
222 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
223 break; \
225 } while (0)
227 #undef DEBUG
228 #define DEBUG(a) if (cfg->verbose_level > 1) a
230 #define MAX_EXC 16
232 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
234 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
235 #define S390X_NOP_SIZE sizeof(RR_Format)
237 #define MAX(a, b) ((a) > (b) ? (a) : (b))
240 * imt trampoline size values
242 #define CMP_SIZE 24
243 #define LOADCON_SIZE 20
244 #define LOAD_SIZE 6
245 #define BR_SIZE 2
246 #define JUMP_SIZE 6
247 #define ENABLE_WRONG_METHOD_CHECK 0
249 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
250 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
252 /*========================= End of Defines =========================*/
254 /*------------------------------------------------------------------*/
255 /* I n c l u d e s */
256 /*------------------------------------------------------------------*/
258 #include "mini.h"
259 #include <string.h>
260 #include <sys/types.h>
261 #include <unistd.h>
263 #include <mono/metadata/abi-details.h>
264 #include <mono/metadata/appdomain.h>
265 #include <mono/metadata/debug-helpers.h>
266 #include <mono/metadata/profiler-private.h>
267 #include <mono/utils/mono-error.h>
268 #include <mono/utils/mono-error-internals.h>
269 #include <mono/utils/mono-math.h>
270 #include <mono/utils/mono-mmap.h>
271 #include <mono/utils/mono-hwcap.h>
272 #include <mono/utils/mono-threads.h>
274 #include "mini-s390x.h"
275 #include "cpu-s390x.h"
276 #include "support-s390x.h"
277 #include "jit-icalls.h"
278 #include "ir-emit.h"
279 #include "trace.h"
280 #include "mini-gc.h"
282 /*========================= End of Includes ========================*/
284 /*------------------------------------------------------------------*/
285 /* T y p e d e f s */
286 /*------------------------------------------------------------------*/
288 typedef struct {
289 guint stack_size,
290 local_size,
291 code_size,
292 parm_size,
293 offset,
294 offStruct,
295 retStruct;
296 } size_data;
298 /*------------------------------------------------------------------*/
299 /* Used by the instrument_emit_epilog */
300 /*------------------------------------------------------------------*/
302 enum {
303 SAVE_NONE,
304 SAVE_STRUCT,
305 SAVE_ONE,
306 SAVE_TWO,
307 SAVE_R4,
308 SAVE_R8
311 typedef struct InstList InstList;
313 struct InstList {
314 InstList *prev;
315 InstList *next;
316 MonoInst *data;
319 typedef enum {
320 RegTypeGeneral,
321 RegTypeBase,
322 RegTypeFP,
323 RegTypeFPR4,
324 RegTypeStructByVal,
325 RegTypeStructByValInFP,
326 RegTypeStructByAddr,
327 RegTypeStructByAddrOnStack
328 } ArgStorage;
330 typedef struct {
331 gint32 offset; /* offset from caller's stack */
332 gint32 offparm; /* offset from callee's stack */
333 guint16 vtsize; /* in param area */
334 guint8 reg;
335 ArgStorage regtype;
336 guint32 size; /* Size of structure used by RegTypeStructByVal */
337 gint32 type; /* Data type of argument */
338 } ArgInfo;
340 typedef struct {
341 int nargs;
342 int lastgr;
343 guint32 stack_usage;
344 guint32 struct_ret;
345 ArgInfo ret;
346 ArgInfo sigCookie;
347 size_data sz;
348 int vret_arg_index;
349 ArgInfo args [1];
350 } CallInfo;
352 typedef struct {
353 gint64 gr[5]; /* R2-R6 */
354 gdouble fp[3]; /* F0-F2 */
355 } __attribute__ ((packed)) RegParm;
357 typedef struct {
358 RR_Format basr;
359 RI_Format j;
360 void *pTrigger;
361 RXY_Format lg;
362 RXY_Format trigger;
363 } __attribute__ ((packed)) breakpoint_t;
365 /*========================= End of Typedefs ========================*/
367 /*------------------------------------------------------------------*/
368 /* P r o t o t y p e s */
369 /*------------------------------------------------------------------*/
371 static void indent (int);
372 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
373 static void decodeParm (MonoType *, void *, int);
374 static void enter_method (MonoMethod *, RegParm *, char *);
375 static void leave_method (MonoMethod *, ...);
376 static inline void add_general (guint *, size_data *, ArgInfo *);
377 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
378 static inline void add_float (guint *, size_data *, ArgInfo *);
379 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
380 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
381 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
382 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
384 /*========================= End of Prototypes ======================*/
386 /*------------------------------------------------------------------*/
387 /* G l o b a l V a r i a b l e s */
388 /*------------------------------------------------------------------*/
390 int mono_exc_esp_offset = 0;
392 __thread int indent_level = 0;
394 static gint appdomain_tls_offset = -1,
395 lmf_tls_offset = -1,
396 lmf_addr_tls_offset = -1;
398 pthread_key_t lmf_addr_key;
400 gboolean lmf_addr_key_inited = FALSE;
403 * The code generated for sequence points reads from this location,
404 * which is made read-only when single stepping is enabled.
406 static gpointer ss_trigger_page;
409 * Enabled breakpoints read from this trigger page
411 static gpointer bp_trigger_page;
413 breakpoint_t breakpointCode;
415 static mono_mutex_t mini_arch_mutex;
417 static const char * grNames[] = {
418 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
419 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
420 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
421 "s390_r15"
424 static const char * fpNames[] = {
425 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
426 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
427 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
428 "s390_f15"
431 static const char * vrNames[] = {
432 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
433 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
434 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
435 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
438 /*====================== End of Global Variables ===================*/
440 /*------------------------------------------------------------------*/
441 /* */
442 /* Name - mono_arch_regname */
443 /* */
444 /* Function - Returns the name of the register specified by */
445 /* the input parameter. */
446 /* */
447 /*------------------------------------------------------------------*/
449 const char*
450 mono_arch_regname (int reg)
452 if (reg >= 0 && reg < 16)
453 return grNames [reg];
454 else
455 return "unknown";
458 /*========================= End of Function ========================*/
460 /*------------------------------------------------------------------*/
461 /* */
462 /* Name - mono_arch_fregname */
463 /* */
464 /* Function - Returns the name of the register specified by */
465 /* the input parameter. */
466 /* */
467 /*------------------------------------------------------------------*/
469 const char*
470 mono_arch_fregname (int reg)
472 if (reg >= 0 && reg < 16)
473 return fpNames [reg];
474 else
475 return "unknown";
478 /*========================= End of Function ========================*/
480 /*------------------------------------------------------------------*/
481 /* */
482 /* Name - mono_arch_xregname */
483 /* */
484 /* Function - Returns the name of the register specified by */
485 /* the input parameter. */
486 /* */
487 /*------------------------------------------------------------------*/
489 const char *
490 mono_arch_xregname (int reg)
492 if (reg < s390_VR_NREG)
493 return vrNames [reg];
494 else
495 return "unknown";
498 /*========================= End of Function ========================*/
500 /*------------------------------------------------------------------*/
501 /* */
502 /* Name - arch_get_argument_info */
503 /* */
504 /* Function - Gathers information on parameters such as size, */
505 /* alignment, and padding. arg_info should be large */
506 /* enough to hold param_count + 1 entries. */
507 /* */
508 /* Parameters - @csig - Method signature */
509 /* @param_count - No. of parameters to consider */
510 /* @arg_info - An array to store the result info */
511 /* */
512 /* Returns - Size of the activation frame */
513 /* */
514 /*------------------------------------------------------------------*/
517 mono_arch_get_argument_info (MonoMethodSignature *csig,
518 int param_count,
519 MonoJitArgumentInfo *arg_info)
521 int k, frame_size = 0;
522 int size, align, pad;
523 int offset = 8;
525 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
526 frame_size += sizeof (gpointer);
527 offset += 8;
530 arg_info [0].offset = offset;
532 if (csig->hasthis) {
533 frame_size += sizeof (gpointer);
534 offset += 8;
537 arg_info [0].size = frame_size;
539 for (k = 0; k < param_count; k++) {
541 if (csig->pinvoke)
542 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
543 else
544 size = mini_type_stack_size (csig->params [k], &align);
546 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
547 arg_info [k].pad = pad;
548 frame_size += size;
549 arg_info [k + 1].pad = 0;
550 arg_info [k + 1].size = size;
551 offset += pad;
552 arg_info [k + 1].offset = offset;
553 offset += size;
556 align = MONO_ARCH_FRAME_ALIGNMENT;
557 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
558 arg_info [k].pad = pad;
560 return frame_size;
563 /*========================= End of Function ========================*/
565 /*------------------------------------------------------------------*/
566 /* */
567 /* Name - emit_unwind_regs. */
568 /* */
569 /* Function - Determines if a value can be returned in one or */
570 /* two registers. */
571 /* */
572 /*------------------------------------------------------------------*/
574 static void __inline__
575 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
577 int i;
579 for (i = start; i < end; i++) {
580 mono_emit_unwind_op_offset (cfg, code, i, offset);
581 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
582 offset += sizeof(gulong);
586 /*========================= End of Function ========================*/
588 /*------------------------------------------------------------------*/
589 /* */
590 /* Name - retFitsInReg. */
591 /* */
592 /* Function - Determines if a value can be returned in one or */
593 /* two registers. */
594 /* */
595 /*------------------------------------------------------------------*/
597 static inline gboolean
598 retFitsInReg(guint32 size)
600 switch (size) {
601 case 0:
602 case 1:
603 case 2:
604 case 4:
605 case 8:
606 return (TRUE);
607 break;
608 default:
609 return (FALSE);
613 /*========================= End of Function ========================*/
615 /*------------------------------------------------------------------*/
616 /* */
617 /* Name - backStackPtr. */
618 /* */
619 /* Function - Restore Stack Pointer to previous frame. */
620 /* */
621 /*------------------------------------------------------------------*/
623 static inline guint8 *
624 backUpStackPtr(MonoCompile *cfg, guint8 *code)
626 int stackSize = cfg->stack_usage;
628 if (cfg->frame_reg != STK_BASE)
629 s390_lgr (code, STK_BASE, cfg->frame_reg);
631 if (s390_is_imm16 (stackSize)) {
632 s390_aghi (code, STK_BASE, stackSize);
633 } else {
634 while (stackSize > 32767) {
635 s390_aghi (code, STK_BASE, 32767);
636 stackSize -= 32767;
638 s390_aghi (code, STK_BASE, stackSize);
640 return (code);
643 /*========================= End of Function ========================*/
645 /*------------------------------------------------------------------*/
646 /* */
647 /* Name - indent */
648 /* */
649 /* Function - Perform nice indenting to current level */
650 /* */
651 /*------------------------------------------------------------------*/
653 static void
654 indent (int diff) {
655 int v;
656 if (diff < 0)
657 indent_level += diff;
658 v = indent_level;
659 printf("%p [%3d] ",(void *)pthread_self(),v);
660 while (v-- > 0) {
661 printf (". ");
663 if (diff > 0)
664 indent_level += diff;
667 /*========================= End of Function ========================*/
669 /*------------------------------------------------------------------*/
670 /* */
671 /* Name - cvtMonoType */
672 /* */
673 /* Function - Convert a mono-type to a string. */
674 /* */
675 /*------------------------------------------------------------------*/
677 static const char *
678 cvtMonoType(MonoTypeEnum t)
680 switch(t)
682 case MONO_TYPE_END:
683 return "MONO_TYPE_END";
684 case MONO_TYPE_VOID:
685 return "MONO_TYPE_VOID";
686 case MONO_TYPE_BOOLEAN:
687 return "MONO_TYPE_BOOLEAN";
688 case MONO_TYPE_CHAR:
689 return "MONO_TYPE_CHAR";
690 case MONO_TYPE_I1:
691 return "MONO_TYPE_I1";
692 case MONO_TYPE_U1:
693 return "MONO_TYPE_U1";
694 case MONO_TYPE_I2:
695 return "MONO_TYPE_I2";
696 case MONO_TYPE_U2:
697 return "MONO_TYPE_U2";
698 case MONO_TYPE_I4:
699 return "MONO_TYPE_I4";
700 case MONO_TYPE_U4:
701 return "MONO_TYPE_U4";
702 case MONO_TYPE_I8:
703 return "MONO_TYPE_I8";
704 case MONO_TYPE_U8:
705 return "MONO_TYPE_U8";
706 case MONO_TYPE_R4:
707 return "MONO_TYPE_R4";
708 case MONO_TYPE_R8:
709 return "MONO_TYPE_R8";
710 case MONO_TYPE_STRING:
711 return "MONO_TYPE_STRING";
712 case MONO_TYPE_PTR:
713 return "MONO_TYPE_PTR";
714 case MONO_TYPE_BYREF:
715 return "MONO_TYPE_BYREF";
716 case MONO_TYPE_VALUETYPE:
717 return "MONO_TYPE_VALUETYPE";
718 case MONO_TYPE_CLASS:
719 return "MONO_TYPE_CLASS";
720 case MONO_TYPE_VAR:
721 return "MONO_TYPE_VAR";
722 case MONO_TYPE_ARRAY:
723 return "MONO_TYPE_ARRAY";
724 case MONO_TYPE_GENERICINST:
725 return "MONO_TYPE_GENERICINST";
726 case MONO_TYPE_TYPEDBYREF:
727 return "MONO_TYPE_TYPEDBYREF";
728 case MONO_TYPE_I:
729 return "MONO_TYPE_I";
730 case MONO_TYPE_U:
731 return "MONO_TYPE_U";
732 case MONO_TYPE_FNPTR:
733 return "MONO_TYPE_FNPTR";
734 case MONO_TYPE_OBJECT:
735 return "MONO_TYPE_OBJECT";
736 case MONO_TYPE_SZARRAY:
737 return "MONO_TYPE_SZARRAY";
738 case MONO_TYPE_MVAR:
739 return "MONO_TYPE_MVAR";
740 case MONO_TYPE_CMOD_REQD:
741 return "MONO_TYPE_CMOD_REQD";
742 case MONO_TYPE_CMOD_OPT:
743 return "MONO_TYPE_CMOD_OPT";
744 case MONO_TYPE_INTERNAL:
745 return "MONO_TYPE_INTERNAL";
746 case MONO_TYPE_MODIFIER:
747 return "MONO_TYPE_MODIFIER";
748 case MONO_TYPE_SENTINEL:
749 return "MONO_TYPE_SENTINEL";
750 case MONO_TYPE_PINNED:
751 return "MONO_TYPE_PINNED";
752 default:
755 return "unknown";
758 /*========================= End of Function ========================*/
760 /*------------------------------------------------------------------*/
761 /* */
762 /* Name - decodeParm */
763 /* */
764 /* Function - Decode a parameter for the trace. */
765 /* */
766 /*------------------------------------------------------------------*/
768 static void
769 decodeParmString (MonoString *s)
771 MonoError error;
772 char *str = mono_string_to_utf8_checked(s, &error);
773 if (is_ok (&error)) {
774 printf("[STRING:%p:%s], ", s, str);
775 g_free (str);
776 } else {
777 mono_error_cleanup (&error);
778 printf("[STRING:%p:], ", s);
782 static void
783 decodeParm(MonoType *type, void *curParm, int size)
785 guint32 simpleType;
787 if (type->byref) {
788 printf("[BYREF:%p], ", *((char **) curParm));
789 } else {
790 simpleType = mini_get_underlying_type(type)->type;
791 enum_parmtype:
792 switch (simpleType) {
793 case MONO_TYPE_I :
794 printf ("[INTPTR:%p], ", *((int **) curParm));
795 break;
796 case MONO_TYPE_U :
797 printf ("[UINTPTR:%p], ", *((int **) curParm));
798 break;
799 case MONO_TYPE_BOOLEAN :
800 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
801 break;
802 case MONO_TYPE_CHAR :
803 printf ("[CHAR:%c], ", *((int *) curParm));
804 break;
805 case MONO_TYPE_I1 :
806 printf ("[INT1:%ld], ", *((gint64 *) curParm));
807 break;
808 case MONO_TYPE_I2 :
809 printf ("[INT2:%ld], ", *((gint64 *) curParm));
810 break;
811 case MONO_TYPE_I4 :
812 printf ("[INT4:%ld], ", *((gint64 *) curParm));
813 break;
814 case MONO_TYPE_U1 :
815 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
816 break;
817 case MONO_TYPE_U2 :
818 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
819 break;
820 case MONO_TYPE_U4 :
821 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
822 break;
823 case MONO_TYPE_U8 :
824 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
825 break;
826 case MONO_TYPE_STRING : {
827 MonoString *s = *((MonoString **) curParm);
828 if (s) {
829 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
830 decodeParmString (s);
831 } else {
832 printf("[STRING:null], ");
834 break;
836 case MONO_TYPE_CLASS :
837 case MONO_TYPE_OBJECT : {
838 MonoObject *obj = *((MonoObject **) curParm);
839 MonoClass *klass;
840 if ((obj) && (obj->vtable)) {
841 printf("[CLASS/OBJ:");
842 klass = obj->vtable->klass;
843 printf("%p [%p] ",obj,curParm);
844 if (klass == mono_defaults.string_class) {
845 decodeParmString ((MonoString *)obj);
846 } else if (klass == mono_defaults.int32_class) {
847 printf("[INT32:%p:%d]",
848 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
849 } else
850 printf("[%s.%s:%p]",
851 klass->name_space, klass->name, obj);
852 printf("], ");
853 } else {
854 printf("[OBJECT:null], ");
856 break;
858 case MONO_TYPE_PTR :
859 printf("[PTR:%p], ", *((gpointer **) (curParm)));
860 break;
861 case MONO_TYPE_FNPTR :
862 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
863 break;
864 case MONO_TYPE_ARRAY :
865 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
866 break;
867 case MONO_TYPE_SZARRAY :
868 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
869 break;
870 case MONO_TYPE_I8 :
871 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
872 break;
873 case MONO_TYPE_R4 :
874 printf("[FLOAT4:%g], ", *((float *) (curParm)));
875 break;
876 case MONO_TYPE_R8 :
877 printf("[FLOAT8:%g], ", *((double *) (curParm)));
878 break;
879 case MONO_TYPE_VALUETYPE : {
880 int i;
881 MonoMarshalType *info;
883 if (type->data.klass->enumtype) {
884 simpleType = mono_class_enum_basetype (type->data.klass)->type;
885 printf("{VALUETYPE} - ");
886 goto enum_parmtype;
889 info = mono_marshal_load_type_info (type->data.klass);
891 if ((info->native_size == sizeof(float)) &&
892 (info->num_fields == 1) &&
893 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
894 printf("[FLOAT4:%f], ", *((float *) (curParm)));
895 break;
898 if ((info->native_size == sizeof(double)) &&
899 (info->num_fields == 1) &&
900 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
901 printf("[FLOAT8:%g], ", *((double *) (curParm)));
902 break;
905 printf("[VALUETYPE:");
906 for (i = 0; i < size; i++)
907 printf("%02x,", *((guint8 *)curParm+i));
908 printf("], ");
909 break;
911 case MONO_TYPE_TYPEDBYREF: {
912 int i;
913 printf("[TYPEDBYREF:");
914 for (i = 0; i < size; i++)
915 printf("%02x,", *((guint8 *)curParm+i));
916 printf("]");
917 break;
919 default :
920 printf("[%s], ",cvtMonoType(simpleType));
925 /*========================= End of Function ========================*/
927 /*------------------------------------------------------------------*/
928 /* */
929 /* Name - enter_method */
930 /* */
931 /* Function - Perform tracing of the entry to the current */
932 /* method. */
933 /* */
934 /*------------------------------------------------------------------*/
936 static void
937 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
939 int i, oParm = 0, iParm = 0;
940 MonoClass *klass;
941 MonoObject *obj;
942 MonoMethodSignature *sig;
943 char *fname;
944 guint64 ip;
945 CallInfo *cinfo;
946 ArgInfo *ainfo;
947 void *curParm;
949 fname = mono_method_full_name (method, TRUE);
950 indent (1);
951 printf ("ENTER: %s ", fname);
952 g_free (fname);
954 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
955 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
957 if (rParm == NULL)
958 return;
960 sig = mono_method_signature (method);
962 cinfo = get_call_info (NULL, NULL, sig);
964 if (cinfo->struct_ret) {
965 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
966 iParm = 1;
969 if (sig->hasthis) {
970 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
971 obj = (MonoObject *) this_arg;
972 switch(method->klass->this_arg.type) {
973 case MONO_TYPE_VALUETYPE:
974 if (obj) {
975 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
976 printf("this:[value:%p:%016lx], ", this_arg, *value);
977 } else
978 printf ("this:[NULL], ");
979 break;
980 case MONO_TYPE_STRING:
981 if (obj) {
982 if (obj->vtable) {
983 klass = obj->vtable->klass;
984 if (klass == mono_defaults.string_class) {
985 printf ("this:");
986 decodeParmString((MonoString *)obj);
987 } else {
988 printf ("this:%p[%s.%s], ",
989 obj, klass->name_space, klass->name);
991 } else
992 printf("vtable:[NULL], ");
993 } else
994 printf ("this:[NULL], ");
995 break;
996 default :
997 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
999 oParm++;
1002 for (i = 0; i < sig->param_count; ++i) {
1003 ainfo = &cinfo->args[i + oParm];
1004 switch (ainfo->regtype) {
1005 case RegTypeGeneral :
1006 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1007 break;
1008 case RegTypeFP :
1009 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1010 break;
1011 case RegTypeBase :
1012 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1013 break;
1014 case RegTypeStructByVal :
1015 if (ainfo->reg != STK_BASE) {
1016 int offset = sizeof(glong) - ainfo->size;
1017 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1019 else
1020 curParm = sp+ainfo->offset;
1022 if (retFitsInReg (ainfo->vtsize))
1023 decodeParm(sig->params[i],
1024 curParm,
1025 ainfo->size);
1026 else
1027 decodeParm(sig->params[i],
1028 *((char **) curParm),
1029 ainfo->vtsize);
1030 break;
1031 case RegTypeStructByAddr :
1032 if (ainfo->reg != STK_BASE)
1033 curParm = &(rParm->gr[ainfo->reg-2]);
1034 else
1035 curParm = sp+ainfo->offset;
1037 decodeParm(sig->params[i],
1038 *((char **) curParm),
1039 ainfo->vtsize);
1040 break;
1042 default :
1043 printf("???, ");
1046 printf("\n");
1047 g_free(cinfo);
1050 /*========================= End of Function ========================*/
1052 /*------------------------------------------------------------------*/
1053 /* */
1054 /* Name - leave_method */
1055 /* */
1056 /* Function - */
1057 /* */
1058 /*------------------------------------------------------------------*/
1060 static void
1061 leave_method (MonoMethod *method, ...)
1063 MonoType *type;
1064 char *fname;
1065 guint64 ip;
1066 va_list ap;
1068 va_start(ap, method);
1070 fname = mono_method_full_name (method, TRUE);
1071 indent (-1);
1072 printf ("LEAVE: %s", fname);
1073 g_free (fname);
1075 type = mono_method_signature (method)->ret;
1077 handle_enum:
1078 switch (type->type) {
1079 case MONO_TYPE_VOID:
1080 break;
1081 case MONO_TYPE_BOOLEAN: {
1082 int val = va_arg (ap, int);
1083 if (val)
1084 printf ("[TRUE:%d]", val);
1085 else
1086 printf ("[FALSE]");
1088 break;
1090 case MONO_TYPE_CHAR: {
1091 int val = va_arg (ap, int);
1092 printf ("[CHAR:%d]", val);
1093 break;
1095 case MONO_TYPE_I1: {
1096 int val = va_arg (ap, int);
1097 printf ("[INT1:%d]", val);
1098 break;
1100 case MONO_TYPE_U1: {
1101 int val = va_arg (ap, int);
1102 printf ("[UINT1:%d]", val);
1103 break;
1105 case MONO_TYPE_I2: {
1106 int val = va_arg (ap, int);
1107 printf ("[INT2:%d]", val);
1108 break;
1110 case MONO_TYPE_U2: {
1111 int val = va_arg (ap, int);
1112 printf ("[UINT2:%d]", val);
1113 break;
1115 case MONO_TYPE_I4: {
1116 int val = va_arg (ap, int);
1117 printf ("[INT4:%d]", val);
1118 break;
1120 case MONO_TYPE_U4: {
1121 int val = va_arg (ap, int);
1122 printf ("[UINT4:%d]", val);
1123 break;
1125 case MONO_TYPE_I: {
1126 gint64 val = va_arg (ap, gint64);
1127 printf ("[INT:%ld]", val);
1128 printf("]");
1129 break;
1131 case MONO_TYPE_U: {
1132 gint64 val = va_arg (ap, gint64);
1133 printf ("[UINT:%lu]", val);
1134 printf("]");
1135 break;
1137 case MONO_TYPE_STRING: {
1138 MonoString *s = va_arg (ap, MonoString *);
1140 if (s) {
1141 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1142 decodeParmString (s);
1143 } else
1144 printf ("[STRING:null], ");
1145 break;
1147 case MONO_TYPE_CLASS:
1148 case MONO_TYPE_OBJECT: {
1149 MonoObject *o = va_arg (ap, MonoObject *);
1151 if ((o) && (o->vtable)) {
1152 if (o->vtable->klass == mono_defaults.boolean_class) {
1153 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1154 } else if (o->vtable->klass == mono_defaults.int32_class) {
1155 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1156 } else if (o->vtable->klass == mono_defaults.int64_class) {
1157 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1158 } else
1159 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1160 } else
1161 printf ("[OBJECT:%p]", o);
1163 break;
1165 case MONO_TYPE_PTR:
1166 case MONO_TYPE_FNPTR:
1167 case MONO_TYPE_ARRAY:
1168 case MONO_TYPE_SZARRAY: {
1169 gpointer p = va_arg (ap, gpointer);
1170 printf ("[result=%p]", p);
1171 break;
1173 case MONO_TYPE_I8: {
1174 gint64 l = va_arg (ap, gint64);
1175 printf ("[LONG:%ld]", l);
1176 break;
1178 case MONO_TYPE_U8: {
1179 guint64 l = va_arg (ap, guint64);
1180 printf ("[ULONG:%lu]", l);
1181 break;
1183 case MONO_TYPE_R4: {
1184 double f = va_arg (ap, double);
1185 printf ("[FLOAT4:%g]\n", f);
1186 break;
1188 case MONO_TYPE_R8: {
1189 double f = va_arg (ap, double);
1190 printf ("[FLOAT8:%g]\n", f);
1191 break;
1193 case MONO_TYPE_VALUETYPE: {
1194 MonoMarshalType *info;
1195 if (type->data.klass->enumtype) {
1196 type = mono_class_enum_basetype (type->data.klass);
1197 goto handle_enum;
1198 } else {
1199 int size, align;
1201 info = mono_marshal_load_type_info (type->data.klass);
1203 if ((info->native_size == sizeof(float)) &&
1204 (info->num_fields == 1) &&
1205 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1206 double f = va_arg (ap, double);
1207 printf("[FLOAT4:%g]\n", (double) f);
1208 break;
1211 if ((info->native_size == sizeof(double)) &&
1212 (info->num_fields == 1) &&
1213 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1214 double f = va_arg (ap, double);
1215 printf("[FLOAT8:%g]\n", f);
1216 break;
1219 size = mono_type_size (type, &align);
1220 switch (size) {
1221 case 1: {
1222 guint32 p = va_arg (ap, guint32);
1223 printf ("[%02x]\n",p);
1224 break;
1226 case 2: {
1227 guint32 p = va_arg (ap, guint32);
1228 printf ("[%04x]\n",p);
1229 break;
1231 case 4: {
1232 guint32 p = va_arg (ap, guint32);
1233 printf ("[%08x]\n",p);
1234 break;
1236 case 8: {
1237 guint64 p = va_arg (ap, guint64);
1238 printf ("[%016lx]\n",p);
1239 break;
1241 default: {
1242 gpointer p = va_arg (ap, gpointer);
1243 printf ("[VALUETYPE] %p\n",p);
1247 break;
1249 case MONO_TYPE_TYPEDBYREF: {
1250 guint8 *p = va_arg (ap, gpointer);
1251 int j, size, align;
1252 size = mono_type_size (type, &align);
1253 switch (size) {
1254 case 1:
1255 case 2:
1256 case 4:
1257 case 8:
1258 printf ("[");
1259 for (j = 0; p && j < size; j++)
1260 printf ("%02x,", p [j]);
1261 printf ("]\n");
1262 break;
1263 default:
1264 printf ("[TYPEDBYREF]\n");
1267 break;
1268 case MONO_TYPE_GENERICINST: {
1269 printf("[GENERICINST]\n");
1271 break;
1272 case MONO_TYPE_MVAR: {
1273 printf("[MVAR]\n");
1275 break;
1276 case MONO_TYPE_CMOD_REQD: {
1277 printf("[CMOD_REQD]\n");
1279 break;
1280 case MONO_TYPE_CMOD_OPT: {
1281 printf("[CMOD_OPT]\n");
1283 break;
1284 case MONO_TYPE_INTERNAL: {
1285 printf("[INTERNAL]\n");
1287 break;
1288 default:
1289 printf ("(unknown return type %x)",
1290 mono_method_signature (method)->ret->type);
1293 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1294 printf (" ip: %p\n", (gpointer) ip);
1295 va_end (ap);
1298 /*========================= End of Function ========================*/
1300 /*------------------------------------------------------------------*/
1301 /* */
1302 /* Name - mono_arch_cpu_init */
1303 /* */
1304 /* Function - Perform CPU specific initialization to execute */
1305 /* managed code. */
1306 /* */
1307 /*------------------------------------------------------------------*/
1309 void
1310 mono_arch_cpu_init (void)
1314 /*========================= End of Function ========================*/
1316 /*------------------------------------------------------------------*/
1317 /* */
1318 /* Name - mono_arch_init. */
1319 /* */
1320 /* Function - Initialize architecture specific code. */
1321 /* */
1322 /*------------------------------------------------------------------*/
1324 void
1325 mono_arch_init (void)
1327 guint8 *code;
1329 mono_set_partial_sharing_supported (FALSE);
1330 mono_os_mutex_init_recursive (&mini_arch_mutex);
1332 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1333 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1334 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1336 code = (guint8 *) &breakpointCode;
1337 s390_basr(code, s390_r13, 0);
1338 s390_j(code, 6);
1339 s390_llong(code, 0);
1340 s390_lg(code, s390_r13, 0, s390_r13, 4);
1341 s390_lg(code, s390_r0, 0, s390_r13, 0);
1344 /*========================= End of Function ========================*/
1346 /*------------------------------------------------------------------*/
1347 /* */
1348 /* Name - mono_arch_cleanup. */
1349 /* */
1350 /* Function - Cleanup architecture specific code . */
1351 /* */
1352 /*------------------------------------------------------------------*/
1354 void
1355 mono_arch_cleanup (void)
1357 if (ss_trigger_page)
1358 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1359 if (bp_trigger_page)
1360 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1361 mono_os_mutex_destroy (&mini_arch_mutex);
1364 /*========================= End of Function ========================*/
1366 /*------------------------------------------------------------------*/
1367 /* */
1368 /* Name - mono_arch_cpu_optimizations */
1369 /* */
1370 /* Function - Returns the optimizations supported on this CPU */
1371 /* */
1372 /*------------------------------------------------------------------*/
1374 guint32
1375 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1377 guint32 opts = 0;
1379 /*----------------------------------------------------------*/
1380 /* No s390-specific optimizations yet */
1381 /*----------------------------------------------------------*/
1382 *exclude_mask = MONO_OPT_LINEARS;
1383 return opts;
1386 /*========================= End of Function ========================*/
1388 /*------------------------------------------------------------------*/
1389 /* */
1390 /* Name - mono_arch_get_allocatable_int_vars */
1391 /* */
1392 /* Function - */
1393 /* */
1394 /*------------------------------------------------------------------*/
1396 GList *
1397 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1399 GList *vars = NULL;
1400 int i;
1402 for (i = 0; i < cfg->num_varinfo; i++) {
1403 MonoInst *ins = cfg->varinfo [i];
1404 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1406 /* unused vars */
1407 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1408 continue;
1410 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1411 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1412 continue;
1414 /* we can only allocate 32 bit values */
1415 if (mono_is_regsize_var(ins->inst_vtype)) {
1416 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1417 g_assert (i == vmv->idx);
1418 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1422 return vars;
1425 /*========================= End of Function ========================*/
1427 /*------------------------------------------------------------------*/
1428 /* */
1429 /* Name - mono_arch_global_int_regs */
1430 /* */
1431 /* Function - Return a list of usable integer registers. */
1432 /* */
1433 /*------------------------------------------------------------------*/
1435 GList *
1436 mono_arch_get_global_int_regs (MonoCompile *cfg)
1438 GList *regs = NULL;
1439 MonoMethodHeader *header;
1440 int i, top = 13;
1442 header = cfg->header;
1443 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1444 cfg->frame_reg = s390_r11;
1447 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1448 top = 12;
1449 for (i = 8; i < top; ++i) {
1450 if (cfg->frame_reg != i)
1451 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1454 return regs;
1457 /*========================= End of Function ========================*/
1459 /*------------------------------------------------------------------*/
1460 /* */
1461 /* Name - mono_arch_flush_icache */
1462 /* */
1463 /* Function - Flush the CPU icache. */
1464 /* */
1465 /*------------------------------------------------------------------*/
1467 void
1468 mono_arch_flush_icache (guint8 *code, gint size)
1472 /*========================= End of Function ========================*/
1474 /*------------------------------------------------------------------*/
1475 /* */
1476 /* Name - add_general */
1477 /* */
1478 /* Function - Determine code and stack size incremements for a */
1479 /* parameter. */
1480 /* */
1481 /*------------------------------------------------------------------*/
1483 static void inline
1484 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1486 if (*gr > S390_LAST_ARG_REG) {
1487 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1488 ainfo->offset = sz->stack_size;
1489 ainfo->reg = STK_BASE;
1490 ainfo->regtype = RegTypeBase;
1491 sz->stack_size += sizeof(long);
1492 sz->local_size += sizeof(long);
1493 sz->offStruct += sizeof(long);
1494 sz->code_size += 12;
1495 } else {
1496 ainfo->reg = *gr;
1497 sz->code_size += 8;
1499 (*gr) ++;
1502 /*========================= End of Function ========================*/
1504 /*------------------------------------------------------------------*/
1505 /* */
1506 /* Name - add_stackParm */
1507 /* */
1508 /* Function - Determine code and stack size incremements for a */
1509 /* parameter. */
1510 /* */
1511 /*------------------------------------------------------------------*/
1513 static void inline
1514 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1516 if (*gr > S390_LAST_ARG_REG) {
1517 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1518 ainfo->reg = STK_BASE;
1519 ainfo->offset = sz->stack_size;
1520 ainfo->regtype = RegTypeStructByAddrOnStack;
1521 sz->stack_size += sizeof (gpointer);
1522 sz->parm_size += sizeof(gpointer);
1523 sz->offStruct += sizeof(gpointer);
1524 } else {
1525 ainfo->reg = *gr;
1526 ainfo->offset = sz->stack_size;
1527 ainfo->regtype = RegTypeStructByAddr;
1529 (*gr) ++;
1530 ainfo->offparm = sz->offset;
1531 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1532 ainfo->size = size;
1533 ainfo->vtsize = size;
1534 sz->parm_size += size;
1537 /*========================= End of Function ========================*/
1539 /*------------------------------------------------------------------*/
1540 /* */
1541 /* Name - add_float */
1542 /* */
1543 /* Function - Determine code and stack size incremements for a */
1544 /* float parameter. */
1545 /* */
1546 /*------------------------------------------------------------------*/
1548 static void inline
1549 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1551 if ((*fr) <= S390_LAST_FPARG_REG) {
1552 ainfo->regtype = RegTypeFP;
1553 ainfo->reg = *fr;
1554 sz->code_size += 4;
1555 (*fr) += 2;
1557 else {
1558 ainfo->offset = sz->stack_size;
1559 ainfo->reg = STK_BASE;
1560 ainfo->regtype = RegTypeBase;
1561 sz->code_size += 4;
1562 sz->stack_size += sizeof(double);
1563 sz->local_size += sizeof(double);
1564 sz->offStruct += sizeof(double);
1568 /*========================= End of Function ========================*/
1570 /*------------------------------------------------------------------*/
1571 /* */
1572 /* Name - get_call_info */
1573 /* */
1574 /* Function - Determine the amount of space required for code */
1575 /* and stack. In addition determine starting points */
1576 /* for stack-based parameters, and area for struct- */
1577 /* ures being returned on the stack. */
1578 /* */
1579 /*------------------------------------------------------------------*/
1581 static CallInfo *
1582 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1584 guint i, fr, gr, size, pstart;
1585 int nParm = sig->hasthis + sig->param_count;
1586 MonoType *ret_type;
1587 guint32 simpleType, align;
1588 gboolean is_pinvoke = sig->pinvoke;
1589 CallInfo *cinfo;
1590 size_data *sz;
1592 if (mp)
1593 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1594 else
1595 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1597 fr = 0;
1598 gr = s390_r2;
1599 nParm = 0;
1600 cinfo->struct_ret = 0;
1601 sz = &cinfo->sz;
1602 sz->retStruct = 0;
1603 sz->offset = 0;
1604 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1605 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1606 sz->code_size = 0;
1607 sz->parm_size = 0;
1608 sz->local_size = 0;
1609 align = 0;
1610 size = 0;
1612 /*----------------------------------------------------------*/
1613 /* We determine the size of the return code/stack in case we*/
1614 /* need to reserve a register to be used to address a stack */
1615 /* area that the callee will use. */
1616 /*----------------------------------------------------------*/
1618 ret_type = mini_get_underlying_type (sig->ret);
1619 simpleType = ret_type->type;
1620 enum_retvalue:
1621 switch (simpleType) {
1622 case MONO_TYPE_BOOLEAN:
1623 case MONO_TYPE_I1:
1624 case MONO_TYPE_U1:
1625 case MONO_TYPE_I2:
1626 case MONO_TYPE_U2:
1627 case MONO_TYPE_CHAR:
1628 case MONO_TYPE_I4:
1629 case MONO_TYPE_U4:
1630 case MONO_TYPE_I:
1631 case MONO_TYPE_U:
1632 case MONO_TYPE_CLASS:
1633 case MONO_TYPE_OBJECT:
1634 case MONO_TYPE_SZARRAY:
1635 case MONO_TYPE_ARRAY:
1636 case MONO_TYPE_PTR:
1637 case MONO_TYPE_FNPTR:
1638 case MONO_TYPE_STRING:
1639 cinfo->ret.reg = s390_r2;
1640 sz->code_size += 4;
1641 break;
1642 case MONO_TYPE_R4:
1643 case MONO_TYPE_R8:
1644 cinfo->ret.reg = s390_f0;
1645 sz->code_size += 4;
1646 break;
1647 case MONO_TYPE_I8:
1648 case MONO_TYPE_U8:
1649 cinfo->ret.reg = s390_r2;
1650 sz->code_size += 4;
1651 break;
1652 case MONO_TYPE_GENERICINST:
1653 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1654 cinfo->ret.reg = s390_r2;
1655 sz->code_size += 4;
1656 break;
1658 /* Fall through */
1659 case MONO_TYPE_VALUETYPE: {
1660 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1661 if (klass->enumtype) {
1662 simpleType = mono_class_enum_basetype (klass)->type;
1663 goto enum_retvalue;
1665 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1667 cinfo->struct_ret = 1;
1668 cinfo->ret.size = size;
1669 cinfo->ret.vtsize = size;
1670 break;
1672 case MONO_TYPE_TYPEDBYREF:
1673 size = sizeof (MonoTypedRef);
1674 cinfo->struct_ret = 1;
1675 cinfo->ret.size = size;
1676 cinfo->ret.vtsize = size;
1677 break;
1678 case MONO_TYPE_VOID:
1679 break;
1680 default:
1681 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1685 pstart = 0;
1687 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1688 * the first argument, allowing 'this' to be always passed in the first arg reg.
1689 * Also do this if the first argument is a reference type, since virtual calls
1690 * are sometimes made using calli without sig->hasthis set, like in the delegate
1691 * invoke wrappers.
1693 if (cinfo->struct_ret && !is_pinvoke &&
1694 (sig->hasthis ||
1695 (sig->param_count > 0 &&
1696 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1697 if (sig->hasthis) {
1698 cinfo->args[nParm].size = sizeof (gpointer);
1699 add_general (&gr, sz, cinfo->args + nParm);
1700 } else {
1701 cinfo->args[nParm].size = sizeof (gpointer);
1702 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1703 pstart = 1;
1705 nParm ++;
1706 cinfo->vret_arg_index = 1;
1707 cinfo->ret.reg = gr;
1708 gr ++;
1709 } else {
1710 /* this */
1711 if (sig->hasthis) {
1712 cinfo->args[nParm].size = sizeof (gpointer);
1713 add_general (&gr, sz, cinfo->args + nParm);
1714 nParm ++;
1717 if (cinfo->struct_ret) {
1718 cinfo->ret.reg = gr;
1719 gr ++;
1723 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1724 gr = S390_LAST_ARG_REG + 1;
1725 fr = S390_LAST_FPARG_REG + 1;
1727 /* Emit the signature cookie just before the implicit arguments */
1728 add_general (&gr, sz, &cinfo->sigCookie);
1731 /*----------------------------------------------------------*/
1732 /* We determine the size of the parameter code and stack */
1733 /* requirements by checking the types and sizes of the */
1734 /* parameters. */
1735 /*----------------------------------------------------------*/
1737 for (i = pstart; i < sig->param_count; ++i) {
1738 MonoType *ptype;
1740 /*--------------------------------------------------*/
1741 /* Handle vararg type calls. All args are put on */
1742 /* the stack. */
1743 /*--------------------------------------------------*/
1744 if ((sig->call_convention == MONO_CALL_VARARG) &&
1745 (i == sig->sentinelpos)) {
1746 gr = S390_LAST_ARG_REG + 1;
1747 fr = S390_LAST_FPARG_REG + 1;
1748 add_general (&gr, sz, &cinfo->sigCookie);
1751 if (sig->params [i]->byref) {
1752 add_general (&gr, sz, cinfo->args+nParm);
1753 cinfo->args[nParm].size = sizeof(gpointer);
1754 nParm++;
1755 continue;
1758 ptype = mini_get_underlying_type (sig->params [i]);
1759 simpleType = ptype->type;
1760 cinfo->args[nParm].type = simpleType;
1761 switch (simpleType) {
1762 case MONO_TYPE_BOOLEAN:
1763 case MONO_TYPE_I1:
1764 case MONO_TYPE_U1:
1765 cinfo->args[nParm].size = sizeof(char);
1766 add_general (&gr, sz, cinfo->args+nParm);
1767 nParm++;
1768 break;
1769 case MONO_TYPE_I2:
1770 case MONO_TYPE_U2:
1771 case MONO_TYPE_CHAR:
1772 cinfo->args[nParm].size = sizeof(short);
1773 add_general (&gr, sz, cinfo->args+nParm);
1774 nParm++;
1775 break;
1776 case MONO_TYPE_I4:
1777 case MONO_TYPE_U4:
1778 cinfo->args[nParm].size = sizeof(int);
1779 add_general (&gr, sz, cinfo->args+nParm);
1780 nParm++;
1781 break;
1782 case MONO_TYPE_I:
1783 case MONO_TYPE_U:
1784 case MONO_TYPE_PTR:
1785 case MONO_TYPE_FNPTR:
1786 case MONO_TYPE_CLASS:
1787 case MONO_TYPE_OBJECT:
1788 case MONO_TYPE_STRING:
1789 case MONO_TYPE_SZARRAY:
1790 case MONO_TYPE_ARRAY:
1791 cinfo->args[nParm].size = sizeof(gpointer);
1792 add_general (&gr, sz, cinfo->args+nParm);
1793 nParm++;
1794 break;
1795 case MONO_TYPE_I8:
1796 case MONO_TYPE_U8:
1797 cinfo->args[nParm].size = sizeof(long long);
1798 add_general (&gr, sz, cinfo->args+nParm);
1799 nParm++;
1800 break;
1801 case MONO_TYPE_R4:
1802 cinfo->args[nParm].size = sizeof(float);
1803 add_float (&fr, sz, cinfo->args+nParm);
1804 nParm++;
1805 break;
1806 case MONO_TYPE_R8:
1807 cinfo->args[nParm].size = sizeof(double);
1808 add_float (&fr, sz, cinfo->args+nParm);
1809 nParm++;
1810 break;
1811 case MONO_TYPE_GENERICINST:
1812 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1813 cinfo->args[nParm].size = sizeof(gpointer);
1814 add_general (&gr, sz, cinfo->args+nParm);
1815 nParm++;
1816 break;
1818 /* Fall through */
1819 case MONO_TYPE_VALUETYPE: {
1820 MonoMarshalType *info;
1821 MonoClass *klass = mono_class_from_mono_type (ptype);
1823 if (sig->pinvoke)
1824 size = mono_class_native_size(klass, NULL);
1825 else
1826 size = mono_class_value_size(klass, NULL);
1828 if (simpleType != MONO_TYPE_GENERICINST) {
1829 info = mono_marshal_load_type_info(klass);
1831 if ((info->native_size == sizeof(float)) &&
1832 (info->num_fields == 1) &&
1833 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1834 cinfo->args[nParm].size = sizeof(float);
1835 add_float(&fr, sz, cinfo->args+nParm);
1836 nParm ++;
1837 break;
1840 if ((info->native_size == sizeof(double)) &&
1841 (info->num_fields == 1) &&
1842 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1843 cinfo->args[nParm].size = sizeof(double);
1844 add_float(&fr, sz, cinfo->args+nParm);
1845 nParm ++;
1846 break;
1850 cinfo->args[nParm].vtsize = 0;
1851 cinfo->args[nParm].size = 0;
1853 switch (size) {
1854 /*----------------------------------*/
1855 /* On S/390, structures of size 1, */
1856 /* 2, 4, and 8 bytes are passed in */
1857 /* (a) register(s). */
1858 /*----------------------------------*/
1859 case 0:
1860 case 1:
1861 case 2:
1862 case 4:
1863 case 8:
1864 add_general(&gr, sz, cinfo->args+nParm);
1865 cinfo->args[nParm].size = size;
1866 cinfo->args[nParm].regtype = RegTypeStructByVal;
1867 nParm++;
1868 sz->local_size += sizeof(long);
1869 break;
1870 default:
1871 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1872 nParm++;
1875 break;
1876 case MONO_TYPE_TYPEDBYREF: {
1877 int size = sizeof (MonoTypedRef);
1879 cinfo->args[nParm].vtsize = 0;
1880 cinfo->args[nParm].size = 0;
1882 switch (size) {
1883 /*----------------------------------*/
1884 /* On S/390, structures of size 1, */
1885 /* 2, 4, and 8 bytes are passed in */
1886 /* (a) register(s). */
1887 /*----------------------------------*/
1888 case 0:
1889 case 1:
1890 case 2:
1891 case 4:
1892 case 8:
1893 add_general(&gr, sz, cinfo->args+nParm);
1894 cinfo->args[nParm].size = size;
1895 cinfo->args[nParm].regtype = RegTypeStructByVal;
1896 nParm++;
1897 sz->local_size += sizeof(long);
1898 break;
1899 default:
1900 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1901 nParm++;
1904 break;
1905 default:
1906 g_error ("Can't trampoline 0x%x", ptype);
1910 /*----------------------------------------------------------*/
1911 /* Handle the case where there are no implicit arguments */
1912 /*----------------------------------------------------------*/
1913 if ((sig->call_convention == MONO_CALL_VARARG) &&
1914 (nParm > 0) &&
1915 (!sig->pinvoke) &&
1916 (sig->param_count == sig->sentinelpos)) {
1917 gr = S390_LAST_ARG_REG + 1;
1918 fr = S390_LAST_FPARG_REG + 1;
1919 add_general (&gr, sz, &cinfo->sigCookie);
1922 /*----------------------------------------------------------*/
1923 /* If we are passing a structure back then if it won't be */
1924 /* in a register(s) then we make room at the end of the */
1925 /* parameters that may have been placed on the stack */
1926 /*----------------------------------------------------------*/
1927 if (cinfo->struct_ret) {
1928 cinfo->ret.offset = sz->stack_size;
1929 switch (cinfo->ret.size) {
1930 case 0:
1931 case 1:
1932 case 2:
1933 case 4:
1934 case 8:
1935 break;
1936 default:
1937 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1941 cinfo->lastgr = gr;
1942 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1943 sz->offset;
1944 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1946 return (cinfo);
1949 /*========================= End of Function ========================*/
1951 /*------------------------------------------------------------------*/
1952 /* */
1953 /* Name - mono_arch_allocate_vars */
1954 /* */
1955 /* Function - Set var information according to the calling */
1956 /* convention for S/390. The local var stuff should */
1957 /* most likely be split in another method. */
1958 /* */
1959 /* Parameter - @m - Compile unit. */
1960 /* */
1961 /*------------------------------------------------------------------*/
1963 void
1964 mono_arch_allocate_vars (MonoCompile *cfg)
1966 MonoMethodSignature *sig;
1967 MonoMethodHeader *header;
1968 MonoInst *inst;
1969 CallInfo *cinfo;
1970 int iParm, iVar, offset, align, size, curinst;
1971 int frame_reg = STK_BASE;
1972 int sArg, eArg;
1974 header = cfg->header;
1976 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1978 /*---------------------------------------------------------*/
1979 /* We use the frame register also for any method that has */
1980 /* filter clauses. This way, when the handlers are called, */
1981 /* the code will reference local variables using the frame */
1982 /* reg instead of the stack pointer: if we had to restore */
1983 /* the stack pointer, we'd corrupt the method frames that */
1984 /* are already on the stack (since filters get called */
1985 /* before stack unwinding happens) when the filter code */
1986 /* would call any method. */
1987 /*---------------------------------------------------------*/
1988 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1989 frame_reg = s390_r11;
1991 cfg->frame_reg = frame_reg;
1993 cfg->arch.bkchain_reg = -1;
1995 if (frame_reg != STK_BASE)
1996 cfg->used_int_regs |= (1 << frame_reg);
1998 if (cfg->uses_rgctx_reg)
1999 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2001 sig = mono_method_signature (cfg->method);
2003 cinfo = get_call_info (cfg, cfg->mempool, sig);
2005 if (!cinfo->struct_ret) {
2006 switch (mini_get_underlying_type (sig->ret)->type) {
2007 case MONO_TYPE_VOID:
2008 break;
2009 default:
2010 cfg->ret->opcode = OP_REGVAR;
2011 cfg->ret->dreg = s390_r2;
2012 break;
2016 /*--------------------------------------------------------------*/
2017 /* local vars are at a positive offset from the stack pointer */
2018 /* also note that if the function uses alloca, we use s390_r11 */
2019 /* to point at the local variables. */
2020 /* add parameter area size for called functions */
2021 /*--------------------------------------------------------------*/
2022 if (cfg->param_area == 0)
2023 offset = S390_MINIMAL_STACK_SIZE;
2024 else
2025 offset = cfg->param_area;
2027 cfg->sig_cookie = 0;
2029 if (cinfo->struct_ret) {
2030 inst = cfg->vret_addr;
2031 offset = S390_ALIGN(offset, sizeof(gpointer));
2032 inst->inst_offset = offset;
2033 inst->opcode = OP_REGOFFSET;
2034 inst->inst_basereg = frame_reg;
2035 offset += sizeof(gpointer);
2036 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2037 printf ("vret_addr =");
2038 mono_print_ins (cfg->vret_addr);
2042 if (sig->hasthis) {
2043 inst = cfg->args [0];
2044 if (inst->opcode != OP_REGVAR) {
2045 inst->opcode = OP_REGOFFSET;
2046 inst->inst_basereg = frame_reg;
2047 offset = S390_ALIGN(offset, sizeof(gpointer));
2048 inst->inst_offset = offset;
2049 offset += sizeof (gpointer);
2051 curinst = sArg = 1;
2052 } else {
2053 curinst = sArg = 0;
2056 eArg = sig->param_count + sArg;
2058 if (sig->call_convention == MONO_CALL_VARARG)
2059 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2061 for (iParm = sArg; iParm < eArg; ++iParm) {
2062 inst = cfg->args [curinst];
2063 if (inst->opcode != OP_REGVAR) {
2064 switch (cinfo->args[iParm].regtype) {
2065 case RegTypeStructByAddr : {
2066 MonoInst *indir;
2068 size = sizeof (gpointer);
2070 inst->opcode = OP_REGOFFSET;
2071 inst->inst_basereg = frame_reg;
2072 offset = S390_ALIGN (offset, sizeof (gpointer));
2073 inst->inst_offset = offset;
2075 /* Add a level of indirection */
2076 MONO_INST_NEW (cfg, indir, 0);
2077 *indir = *inst;
2078 inst->opcode = OP_VTARG_ADDR;
2079 inst->inst_left = indir;
2081 break;
2082 case RegTypeStructByAddrOnStack : {
2083 MonoInst *indir;
2085 size = sizeof (gpointer);
2087 /* Similar to the == STK_BASE case below */
2088 cfg->arch.bkchain_reg = s390_r12;
2089 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2091 inst->opcode = OP_REGOFFSET;
2092 inst->dreg = mono_alloc_preg (cfg);
2093 inst->inst_basereg = cfg->arch.bkchain_reg;
2094 inst->inst_offset = cinfo->args [iParm].offset;
2096 /* Add a level of indirection */
2097 MONO_INST_NEW (cfg, indir, 0);
2098 *indir = *inst;
2099 inst->opcode = OP_VTARG_ADDR;
2100 inst->inst_left = indir;
2101 break;
2103 case RegTypeStructByVal :
2104 size = cinfo->args[iParm].size;
2105 offset = S390_ALIGN(offset, size);
2106 inst->opcode = OP_REGOFFSET;
2107 inst->inst_basereg = frame_reg;
2108 inst->inst_offset = offset;
2109 break;
2110 default :
2111 if (cinfo->args [iParm].reg == STK_BASE) {
2113 * These arguments are in the previous frame, so we can't
2114 * compute their offset from the current frame pointer right
2115 * now, since cfg->stack_offset is not yet known, so dedicate a
2116 * register holding the previous frame pointer.
2118 cfg->arch.bkchain_reg = s390_r12;
2119 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2121 inst->opcode = OP_REGOFFSET;
2122 inst->inst_basereg = cfg->arch.bkchain_reg;
2123 size = (cinfo->args[iParm].size < 8
2124 ? 8 - cinfo->args[iParm].size
2125 : 0);
2126 inst->inst_offset = cinfo->args [iParm].offset + size;
2127 size = sizeof (long);
2128 } else {
2129 inst->opcode = OP_REGOFFSET;
2130 inst->inst_basereg = frame_reg;
2131 size = (cinfo->args[iParm].size < 8
2132 ? sizeof(int)
2133 : sizeof(long));
2134 offset = S390_ALIGN(offset, size);
2135 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2136 inst->inst_offset = offset;
2137 else
2138 inst->inst_offset = offset + (8 - size);
2140 break;
2142 #if 0
2143 if ((sig->call_convention == MONO_CALL_VARARG) &&
2144 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2145 (iParm < sig->sentinelpos))
2146 cfg->sig_cookie += size;
2147 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2148 #endif
2150 offset += MAX(size, 8);
2152 curinst++;
2155 cfg->locals_min_stack_offset = offset;
2157 curinst = cfg->locals_start;
2158 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2159 inst = cfg->varinfo [iVar];
2160 if ((inst->flags & MONO_INST_IS_DEAD) ||
2161 (inst->opcode == OP_REGVAR))
2162 continue;
2164 /*--------------------------------------------------*/
2165 /* inst->backend.is_pinvoke indicates native sized */
2166 /* value typs this is used by the pinvoke wrappers */
2167 /* when they call functions returning structure */
2168 /*--------------------------------------------------*/
2169 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2170 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2171 (guint32 *) &align);
2172 else
2173 size = mono_type_size (inst->inst_vtype, &align);
2175 offset = S390_ALIGN(offset, align);
2176 inst->inst_offset = offset;
2177 inst->opcode = OP_REGOFFSET;
2178 inst->inst_basereg = frame_reg;
2179 offset += size;
2180 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2181 iVar, inst->inst_offset, size));
2184 cfg->locals_max_stack_offset = offset;
2186 /*------------------------------------------------------*/
2187 /* Allow space for the trace method stack area if needed*/
2188 /*------------------------------------------------------*/
2189 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2190 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2191 offset += S390_TRACE_STACK_SIZE;
2193 /*------------------------------------------------------*/
2194 /* Reserve space to save LMF and caller saved registers */
2195 /*------------------------------------------------------*/
2196 if (cfg->method->save_lmf)
2197 offset += sizeof (MonoLMF);
2199 /*------------------------------------------------------*/
2200 /* align the offset */
2201 /*------------------------------------------------------*/
2202 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2204 /*------------------------------------------------------*/
2205 /* Fix offsets for args whose value is in parent frame */
2206 /*------------------------------------------------------*/
2207 for (iParm = sArg; iParm < eArg; ++iParm) {
2208 inst = cfg->args [iParm];
2210 if (inst->opcode == OP_S390_STKARG) {
2211 inst->opcode = OP_REGOFFSET;
2212 inst->inst_offset += cfg->stack_offset;
2217 /*========================= End of Function ========================*/
2219 /*------------------------------------------------------------------*/
2220 /* */
2221 /* Name - mono_arch_create_vars */
2222 /* */
2223 /*------------------------------------------------------------------*/
2225 void
2226 mono_arch_create_vars (MonoCompile *cfg)
2228 MonoMethodSignature *sig;
2229 CallInfo *cinfo;
2231 sig = mono_method_signature (cfg->method);
2233 cinfo = get_call_info (cfg, cfg->mempool, sig);
2235 if (cinfo->struct_ret) {
2236 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2237 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2238 printf ("vret_addr = ");
2239 mono_print_ins (cfg->vret_addr);
2244 /*========================= End of Function ========================*/
2246 /*------------------------------------------------------------------*/
2247 /* */
2248 /* Name - add_outarg_reg2. */
2249 /* */
2250 /*------------------------------------------------------------------*/
2252 static void
2253 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2255 MonoInst *ins;
2257 switch (storage) {
2258 case RegTypeGeneral:
2259 MONO_INST_NEW (cfg, ins, OP_MOVE);
2260 ins->dreg = mono_alloc_ireg (cfg);
2261 ins->sreg1 = tree->dreg;
2262 MONO_ADD_INS (cfg->cbb, ins);
2263 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2264 break;
2265 case RegTypeFP:
2266 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2267 ins->dreg = mono_alloc_freg (cfg);
2268 ins->sreg1 = tree->dreg;
2269 MONO_ADD_INS (cfg->cbb, ins);
2270 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2271 break;
2272 case RegTypeFPR4:
2273 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2274 ins->dreg = mono_alloc_freg (cfg);
2275 ins->sreg1 = tree->dreg;
2276 MONO_ADD_INS (cfg->cbb, ins);
2277 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2278 break;
2279 default:
2280 g_assert_not_reached ();
2284 /*========================= End of Function ========================*/
2286 /*------------------------------------------------------------------*/
2287 /* */
2288 /* Name - emit_sig_cookie. */
2289 /* */
2290 /*------------------------------------------------------------------*/
2292 static void
2293 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2295 MonoMethodSignature *tmpSig;
2296 MonoInst *sig_arg;
2298 cfg->disable_aot = TRUE;
2300 /*----------------------------------------------------------*/
2301 /* mono_ArgIterator_Setup assumes the signature cookie is */
2302 /* passed first and all the arguments which were before it */
2303 /* passed on the stack after the signature. So compensate */
2304 /* by passing a different signature. */
2305 /*----------------------------------------------------------*/
2306 tmpSig = mono_metadata_signature_dup (call->signature);
2307 tmpSig->param_count -= call->signature->sentinelpos;
2308 tmpSig->sentinelpos = 0;
2309 if (tmpSig->param_count > 0)
2310 memcpy (tmpSig->params,
2311 call->signature->params + call->signature->sentinelpos,
2312 tmpSig->param_count * sizeof(MonoType *));
2314 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2315 sig_arg->dreg = mono_alloc_ireg (cfg);
2316 sig_arg->inst_p0 = tmpSig;
2317 MONO_ADD_INS (cfg->cbb, sig_arg);
2319 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2320 cinfo->sigCookie.offset, sig_arg->dreg);
2323 /*========================= End of Function ========================*/
2325 /*------------------------------------------------------------------*/
2326 /* */
2327 /* Name - mono_arch_emit_call */
2328 /* */
2329 /*------------------------------------------------------------------*/
2331 void
2332 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2334 MonoInst *in;
2335 MonoMethodSignature *sig;
2336 MonoInst *ins;
2337 int i, n, lParamArea;
2338 CallInfo *cinfo;
2339 ArgInfo *ainfo = NULL;
2340 int stackSize;
2341 MonoMethodHeader *header;
2342 int frmReg;
2344 sig = call->signature;
2345 n = sig->param_count + sig->hasthis;
2346 DEBUG (g_print ("Call requires: %d parameters\n",n));
2348 cinfo = get_call_info (cfg, cfg->mempool, sig);
2350 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2351 cinfo->sz.parm_size + cinfo->sz.offset;
2352 call->stack_usage = MAX(stackSize, call->stack_usage);
2353 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2354 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2355 cfg->flags |= MONO_CFG_HAS_CALLS;
2357 if (cinfo->struct_ret) {
2358 MONO_INST_NEW (cfg, ins, OP_MOVE);
2359 ins->sreg1 = call->vret_var->dreg;
2360 ins->dreg = mono_alloc_preg (cfg);
2361 MONO_ADD_INS (cfg->cbb, ins);
2362 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2365 header = cfg->header;
2366 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2367 frmReg = s390_r11;
2368 else
2369 frmReg = STK_BASE;
2371 for (i = 0; i < n; ++i) {
2372 MonoType *t;
2374 ainfo = cinfo->args + i;
2375 if (i >= sig->hasthis)
2376 t = sig->params [i - sig->hasthis];
2377 else
2378 t = &mono_defaults.int_class->byval_arg;
2379 t = mini_get_underlying_type (t);
2381 in = call->args [i];
2383 if ((sig->call_convention == MONO_CALL_VARARG) &&
2384 (!sig->pinvoke) &&
2385 (i == sig->sentinelpos)) {
2386 emit_sig_cookie (cfg, call, cinfo);
2389 switch (ainfo->regtype) {
2390 case RegTypeGeneral:
2391 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2392 break;
2393 case RegTypeFP:
2394 if (MONO_TYPE_ISSTRUCT (t)) {
2395 /* Valuetype passed in one fp register */
2396 ainfo->regtype = RegTypeStructByValInFP;
2397 /* Fall through */
2398 } else {
2399 if (ainfo->size == 4)
2400 ainfo->regtype = RegTypeFPR4;
2401 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2402 break;
2404 case RegTypeStructByVal:
2405 case RegTypeStructByAddr:
2406 case RegTypeStructByAddrOnStack: {
2407 guint32 align;
2408 guint32 size;
2410 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2411 size = sizeof (MonoTypedRef);
2412 align = sizeof (gpointer);
2414 else
2415 if (sig->pinvoke)
2416 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2417 else {
2419 * Other backends use mono_type_stack_size (), but that
2420 * aligns the size to 8, which is larger than the size of
2421 * the source, leading to reads of invalid memory if the
2422 * source is at the end of address space.
2424 size = mono_class_value_size (in->klass, &align);
2427 g_assert (in->klass);
2429 ainfo->offparm += cinfo->sz.offStruct;
2431 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2432 ins->sreg1 = in->dreg;
2433 ins->klass = in->klass;
2434 ins->backend.size = ainfo->size;
2435 ins->inst_p0 = call;
2436 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2437 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2439 MONO_ADD_INS (cfg->cbb, ins);
2441 if (ainfo->regtype == RegTypeStructByAddr) {
2443 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2444 * use the normal OUTARG opcodes to pass the address of the location to
2445 * the callee.
2447 int treg = mono_alloc_preg (cfg);
2448 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2449 frmReg, ainfo->offparm);
2450 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2451 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2452 /* The address of the valuetype is passed on the stack */
2453 int treg = mono_alloc_preg (cfg);
2454 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2455 frmReg, ainfo->offparm);
2456 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2457 ainfo->reg, ainfo->offset, treg);
2459 if (cfg->compute_gc_maps) {
2460 MonoInst *def;
2462 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2465 break;
2467 case RegTypeBase:
2468 if (!t->byref && t->type == MONO_TYPE_R4) {
2469 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2470 STK_BASE, ainfo->offset + 4,
2471 in->dreg);
2472 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2473 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2474 STK_BASE, ainfo->offset,
2475 in->dreg);
2476 } else {
2477 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2478 ins->inst_destbasereg = STK_BASE;
2479 ins->inst_offset = ainfo->offset;
2480 ins->sreg1 = in->dreg;
2482 #if 0
2483 /* This is needed by MonoTypedRef->value to point to the correct data */
2484 if ((sig->call_convention == MONO_CALL_VARARG) &&
2485 (i >= sig->sentinelpos)) {
2486 switch (ainfo->size) {
2487 case 1:
2488 ins->opcode = OP_STOREI1_MEMBASE_REG;
2489 break;
2490 case 2:
2491 ins->opcode = OP_STOREI2_MEMBASE_REG;
2492 break;
2493 case 4:
2494 ins->opcode = OP_STOREI4_MEMBASE_REG;
2495 break;
2496 default:
2497 break;
2500 #endif
2502 MONO_ADD_INS (cfg->cbb, ins);
2504 break;
2505 default:
2506 g_assert_not_reached ();
2507 break;
2512 * Handle the case where there are no implicit arguments
2514 if ((sig->call_convention == MONO_CALL_VARARG) &&
2515 (!sig->pinvoke) &&
2516 (i == sig->sentinelpos)) {
2517 emit_sig_cookie (cfg, call, cinfo);
2521 /*========================= End of Function ========================*/
2523 /*------------------------------------------------------------------*/
2524 /* */
2525 /* Name - mono_arch_emit_outarg_vt */
2526 /* */
2527 /*------------------------------------------------------------------*/
2529 void
2530 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2532 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2533 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2534 int size = ins->backend.size;
2536 if (ainfo->regtype == RegTypeStructByVal) {
2538 arg->ins.sreg1 = ainfo->reg;
2539 arg->ins.opcode = OP_OUTARG_VT;
2540 arg->size = ainfo->size;
2541 arg->offset = ainfo->offset;
2542 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2544 if (ainfo->reg != STK_BASE) {
2545 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2546 } else {
2547 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2548 src->dreg, 0);
2550 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2551 int dreg = mono_alloc_freg (cfg);
2553 if (ainfo->size == 4) {
2554 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2555 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2556 } else {
2557 g_assert (ainfo->size == 8);
2559 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2562 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2563 } else {
2564 MonoError error;
2565 MonoMethodHeader *header;
2566 int srcReg;
2568 header = mono_method_get_header_checked (cfg->method, &error);
2569 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2570 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2571 srcReg = s390_r11;
2572 else
2573 srcReg = STK_BASE;
2575 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2576 src->dreg, 0, size);
2578 if (cfg->compute_gc_maps) {
2579 MonoInst *def;
2581 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2586 /*========================= End of Function ========================*/
2588 /*------------------------------------------------------------------*/
2589 /* */
2590 /* Name - mono_arch_emit_setret */
2591 /* */
2592 /*------------------------------------------------------------------*/
2594 void
2595 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2597 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2599 if (!ret->byref) {
2600 if (ret->type == MONO_TYPE_R4) {
2601 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2602 return;
2603 } else if (ret->type == MONO_TYPE_R8) {
2604 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2605 return;
2609 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2612 /*========================= End of Function ========================*/
2614 /*------------------------------------------------------------------*/
2615 /* */
2616 /* Name - mono_arch_instrument_mem_needs */
2617 /* */
2618 /* Function - Allow tracing to work with this interface (with */
2619 /* an optional argument). */
2620 /* */
2621 /*------------------------------------------------------------------*/
2623 void
2624 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2626 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2627 *stack = 0;
2628 /* split prolog-epilog requirements? */
2629 *code = 50; /* max bytes needed: check this number */
2632 /*========================= End of Function ========================*/
2634 /*------------------------------------------------------------------*/
2635 /* */
2636 /* Name - mono_arch_instrument_prolog */
2637 /* */
2638 /* Function - Create an "instrumented" prolog. */
2639 /* */
2640 /*------------------------------------------------------------------*/
2642 void*
2643 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2644 gboolean enable_arguments)
2646 guchar *code = p;
2647 int parmOffset,
2648 fpOffset,
2649 baseReg;
2651 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2652 if (cfg->method->save_lmf)
2653 parmOffset -= sizeof(MonoLMF);
2654 fpOffset = parmOffset + (5*sizeof(gpointer));
2655 baseReg = STK_BASE;
2657 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2658 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2659 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2660 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2661 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2662 S390_SET (code, s390_r1, func);
2663 S390_SET (code, s390_r2, cfg->method);
2664 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2665 s390_lgr (code, s390_r4, STK_BASE);
2666 s390_aghi (code, s390_r4, cfg->stack_usage);
2667 s390_basr (code, s390_r14, s390_r1);
2668 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2669 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2670 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2671 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2672 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2674 return code;
2677 /*========================= End of Function ========================*/
2679 /*------------------------------------------------------------------*/
2680 /* */
2681 /* Name - mono_arch_instrument_epilog */
2682 /* */
2683 /* Function - Create an epilog that will handle the returned */
2684 /* values used in instrumentation. */
2685 /* */
2686 /*------------------------------------------------------------------*/
2688 void*
2689 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2691 guchar *code = p;
2692 int save_mode = SAVE_NONE,
2693 saveOffset,
2694 offset;
2695 MonoMethod *method = cfg->method;
2696 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2698 offset = code - cfg->native_code;
2699 /*-----------------------------------------*/
2700 /* We need about 128 bytes of instructions */
2701 /*-----------------------------------------*/
2702 if (offset > (cfg->code_size - 128)) {
2703 cfg->code_size *= 2;
2704 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2705 code = cfg->native_code + offset;
2708 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2709 if (method->save_lmf)
2710 saveOffset -= sizeof(MonoLMF);
2712 handle_enum:
2713 switch (rtype) {
2714 case MONO_TYPE_VOID:
2715 /* special case string .ctor icall */
2716 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2717 save_mode = SAVE_ONE;
2718 else
2719 save_mode = SAVE_NONE;
2720 break;
2721 case MONO_TYPE_I8:
2722 case MONO_TYPE_U8:
2723 save_mode = SAVE_ONE;
2724 break;
2725 case MONO_TYPE_R4:
2726 save_mode = SAVE_R4;
2727 break;
2728 case MONO_TYPE_R8:
2729 save_mode = SAVE_R8;
2730 break;
2731 case MONO_TYPE_VALUETYPE:
2732 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2733 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2734 goto handle_enum;
2736 save_mode = SAVE_STRUCT;
2737 break;
2738 default:
2739 save_mode = SAVE_ONE;
2740 break;
2743 switch (save_mode) {
2744 case SAVE_ONE:
2745 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2746 if (enable_arguments) {
2747 s390_lgr (code, s390_r3, s390_r2);
2749 break;
2750 case SAVE_R4:
2751 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2752 if (enable_arguments) {
2753 s390_ldebr (code, s390_f0, s390_f0);
2755 break;
2756 case SAVE_R8:
2757 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2758 break;
2759 case SAVE_STRUCT:
2760 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2761 if (enable_arguments) {
2762 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2763 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2765 break;
2766 case SAVE_NONE:
2767 default:
2768 break;
2771 S390_SET (code, s390_r1, func);
2772 S390_SET (code, s390_r2, cfg->method);
2773 s390_basr (code, s390_r14, s390_r1);
2775 switch (save_mode) {
2776 case SAVE_ONE:
2777 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2778 break;
2779 case SAVE_R4:
2780 case SAVE_R8:
2781 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2782 break;
2783 case SAVE_STRUCT:
2784 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2785 break;
2786 case SAVE_NONE:
2787 default:
2788 break;
2791 return code;
2794 /*========================= End of Function ========================*/
2796 /*------------------------------------------------------------------*/
2797 /* */
2798 /* Name - mono_arch_peephole_pass_1 */
2799 /* */
2800 /* Function - Form a peephole pass at the code looking for */
2801 /* simple optimizations. */
2802 /* */
2803 /*------------------------------------------------------------------*/
2805 void
2806 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2810 /*========================= End of Function ========================*/
2812 /*------------------------------------------------------------------*/
2813 /* */
2814 /* Name - mono_arch_peephole_pass_2 */
2815 /* */
2816 /* Function - Form a peephole pass at the code looking for */
2817 /* simple optimizations. */
2818 /* */
2819 /*------------------------------------------------------------------*/
2821 void
2822 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2824 MonoInst *ins, *n;
2826 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2827 mono_peephole_ins (bb, ins);
2831 /*========================= End of Function ========================*/
2833 /*------------------------------------------------------------------*/
2834 /* */
2835 /* Name - mono_arch_lowering_pass. */
2836 /* */
2837 /*------------------------------------------------------------------*/
2839 void
2840 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2842 MonoInst *ins, *next;
2844 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2845 switch (ins->opcode) {
2846 case OP_DIV_IMM:
2847 case OP_REM_IMM:
2848 case OP_IDIV_IMM:
2849 case OP_IREM_IMM:
2850 case OP_IDIV_UN_IMM:
2851 case OP_IREM_UN_IMM:
2852 case OP_LAND_IMM:
2853 case OP_LOR_IMM:
2854 case OP_LREM_IMM:
2855 case OP_LXOR_IMM:
2856 case OP_LOCALLOC_IMM:
2857 mono_decompose_op_imm (cfg, bb, ins);
2858 break;
2859 case OP_LADD_IMM:
2860 if (!s390_is_imm16 (ins->inst_imm))
2861 /* This is created by the memcpy code which ignores is_inst_imm */
2862 mono_decompose_op_imm (cfg, bb, ins);
2863 break;
2864 default:
2865 break;
2869 bb->max_vreg = cfg->next_vreg;
2872 /*========================= End of Function ========================*/
2874 /*------------------------------------------------------------------*/
2875 /* */
2876 /* Name - emit_float_to_int */
2877 /* */
2878 /* Function - Create instructions which will convert a floating */
2879 /* point value to integer. */
2880 /* */
2881 /*------------------------------------------------------------------*/
2883 static guchar*
2884 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2886 /* sreg is a float, dreg is an integer reg. */
2887 if (is_signed) {
2888 s390_cgdbr (code, dreg, 5, sreg);
2889 switch (size) {
2890 case 1:
2891 s390_ltgr (code, dreg, dreg);
2892 s390_jnl (code, 4);
2893 s390_oill (code, dreg, 0x80);
2894 s390_lghi (code, s390_r0, 0xff);
2895 s390_ngr (code, dreg, s390_r0);
2896 break;
2897 case 2:
2898 s390_ltgr (code, dreg, dreg);
2899 s390_jnl (code, 4);
2900 s390_oill (code, dreg, 0x8000);
2901 s390_llill(code, s390_r0, 0xffff);
2902 s390_ngr (code, dreg, s390_r0);
2903 break;
2905 } else {
2906 short *o[1];
2907 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2908 s390_ldgr (code, s390_f14, s390_r13);
2909 s390_ldr (code, s390_f15, sreg);
2910 s390_cdbr (code, s390_f15, s390_f14);
2911 s390_jl (code, 0); CODEPTR (code, o[0]);
2912 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2913 s390_ldgr (code, s390_f14, s390_r13);
2914 s390_sdbr (code, s390_f15, s390_f14);
2915 s390_cfdbr (code, dreg, 7, s390_f15);
2916 s390_j (code, 4);
2917 PTRSLOT (code, o[0]);
2918 s390_cfdbr (code, dreg, 5, sreg);
2919 switch (size) {
2920 case 1:
2921 s390_lghi (code, s390_r0, 0xff);
2922 s390_ngr (code, dreg, s390_r0);
2923 break;
2924 case 2:
2925 s390_llill(code, s390_r0, 0xffff);
2926 s390_ngr (code, dreg, s390_r0);
2927 break;
2930 return code;
2933 /*========================= End of Function ========================*/
2935 /*------------------------------------------------------------------*/
2936 /* */
2937 /* Name - gboolean_is_unsigned. */
2938 /* */
2939 /* Function - Return TRUE if next opcode is checking for un- */
2940 /* signed value. */
2941 /* */
2942 /*------------------------------------------------------------------*/
2944 static
2945 gboolean is_unsigned (MonoInst *next)
2947 if ((next) &&
2948 (((next->opcode >= OP_IBNE_UN) &&
2949 (next->opcode <= OP_IBLT_UN)) ||
2950 ((next->opcode >= OP_LBNE_UN) &&
2951 (next->opcode <= OP_LBLT_UN)) ||
2952 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2953 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2954 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2955 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2956 ((next->opcode == OP_CLT_UN) ||
2957 (next->opcode == OP_CGT_UN)) ||
2958 ((next->opcode == OP_ICLT_UN) ||
2959 (next->opcode == OP_ICGT_UN) ||
2960 (next->opcode == OP_LCLT_UN) ||
2961 (next->opcode == OP_LCGT_UN))))
2962 return TRUE;
2963 else
2964 return FALSE;
2967 /*========================= End of Function ========================*/
2969 /*------------------------------------------------------------------*/
2970 /* */
2971 /* Name - mono_arch_output_basic_block */
2972 /* */
2973 /* Function - Perform the "real" work of emitting instructions */
2974 /* that will do the work of in the basic block. */
2975 /* */
2976 /*------------------------------------------------------------------*/
2978 void
2979 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2981 MonoInst *ins;
2982 MonoCallInst *call;
2983 guint offset;
2984 guint8 *code = cfg->native_code + cfg->code_len;
2985 guint last_offset = 0;
2986 int max_len, src2;
2988 /* we don't align basic blocks of loops on s390 */
2990 if (cfg->verbose_level > 2)
2991 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2993 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2994 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2995 g_assert (!mono_compile_aot);
2996 cov->data [bb->dfn].cil_code = bb->cil_code;
2997 /* This is not thread save, but good enough */
2998 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2999 s390_alsi (code, 0, s390_r1, 1);
3002 MONO_BB_FOR_EACH_INS (bb, ins) {
3003 offset = code - cfg->native_code;
3005 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3007 if (offset > (cfg->code_size - max_len - 16)) {
3008 cfg->code_size *= 2;
3009 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3010 code = cfg->native_code + offset;
3013 mono_debug_record_line_number (cfg, ins, offset);
3015 switch (ins->opcode) {
3016 case OP_STOREI1_MEMBASE_IMM: {
3017 s390_lghi (code, s390_r0, ins->inst_imm);
3018 S390_LONG (code, stcy, stc, s390_r0, 0,
3019 ins->inst_destbasereg, ins->inst_offset);
3021 break;
3022 case OP_STOREI2_MEMBASE_IMM: {
3023 s390_lghi (code, s390_r0, ins->inst_imm);
3024 S390_LONG (code, sthy, sth, s390_r0, 0,
3025 ins->inst_destbasereg, ins->inst_offset);
3027 break;
3028 case OP_STOREI4_MEMBASE_IMM: {
3029 s390_lgfi (code, s390_r0, ins->inst_imm);
3030 S390_LONG (code, sty, st, s390_r0, 0,
3031 ins->inst_destbasereg, ins->inst_offset);
3033 break;
3034 case OP_STORE_MEMBASE_IMM:
3035 case OP_STOREI8_MEMBASE_IMM: {
3036 S390_SET (code, s390_r0, ins->inst_imm);
3037 S390_LONG (code, stg, stg, s390_r0, 0,
3038 ins->inst_destbasereg, ins->inst_offset);
3040 break;
3041 case OP_STOREI1_MEMBASE_REG: {
3042 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3043 ins->inst_destbasereg, ins->inst_offset);
3045 break;
3046 case OP_STOREI2_MEMBASE_REG: {
3047 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3048 ins->inst_destbasereg, ins->inst_offset);
3050 break;
3051 case OP_STOREI4_MEMBASE_REG: {
3052 S390_LONG (code, sty, st, ins->sreg1, 0,
3053 ins->inst_destbasereg, ins->inst_offset);
3055 break;
3056 case OP_STORE_MEMBASE_REG:
3057 case OP_STOREI8_MEMBASE_REG: {
3058 S390_LONG (code, stg, stg, ins->sreg1, 0,
3059 ins->inst_destbasereg, ins->inst_offset);
3061 break;
3062 case OP_LOADU4_MEM:
3063 g_assert_not_reached ();
3064 break;
3065 case OP_LOAD_MEMBASE:
3066 case OP_LOADI8_MEMBASE: {
3067 S390_LONG (code, lg, lg, ins->dreg, 0,
3068 ins->inst_basereg, ins->inst_offset);
3070 break;
3071 case OP_LOADI4_MEMBASE: {
3072 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3073 ins->inst_basereg, ins->inst_offset);
3075 break;
3076 case OP_LOADU4_MEMBASE: {
3077 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3078 ins->inst_basereg, ins->inst_offset);
3080 break;
3081 case OP_LOADU1_MEMBASE: {
3082 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3083 ins->inst_basereg, ins->inst_offset);
3085 break;
3086 case OP_LOADI1_MEMBASE: {
3087 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3088 ins->inst_basereg, ins->inst_offset);
3090 break;
3091 case OP_LOADU2_MEMBASE: {
3092 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3093 ins->inst_basereg, ins->inst_offset);
3095 break;
3096 case OP_LOADI2_MEMBASE: {
3097 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3098 ins->inst_basereg, ins->inst_offset);
3100 break;
3101 case OP_LCONV_TO_I1: {
3102 s390_lgbr (code, ins->dreg, ins->sreg1);
3104 break;
3105 case OP_LCONV_TO_I2: {
3106 s390_lghr (code, ins->dreg, ins->sreg1);
3108 break;
3109 case OP_LCONV_TO_U1: {
3110 s390_llgcr (code, ins->dreg, ins->sreg1);
3112 break;
3113 case OP_LCONV_TO_U2: {
3114 s390_llghr (code, ins->dreg, ins->sreg1);
3116 break;
3117 case OP_ICONV_TO_I1: {
3118 s390_lgbr (code, ins->dreg, ins->sreg1);
3120 break;
3121 case OP_ICONV_TO_I2: {
3122 s390_lghr (code, ins->dreg, ins->sreg1);
3124 break;
3125 case OP_ICONV_TO_U1: {
3126 s390_llgcr (code, ins->dreg, ins->sreg1);
3128 break;
3129 case OP_ICONV_TO_U2: {
3130 s390_llghr (code, ins->dreg, ins->sreg1);
3132 break;
3133 case OP_COMPARE:
3134 case OP_LCOMPARE: {
3135 if (is_unsigned (ins->next))
3136 s390_clgr (code, ins->sreg1, ins->sreg2);
3137 else
3138 s390_cgr (code, ins->sreg1, ins->sreg2);
3140 break;
3141 case OP_ICOMPARE: {
3142 if (is_unsigned (ins->next))
3143 s390_clr (code, ins->sreg1, ins->sreg2);
3144 else
3145 s390_cr (code, ins->sreg1, ins->sreg2);
3147 break;
3148 case OP_COMPARE_IMM:
3149 case OP_LCOMPARE_IMM: {
3150 S390_SET (code, s390_r0, ins->inst_imm);
3151 if (is_unsigned (ins->next))
3152 s390_clgr (code, ins->sreg1, s390_r0);
3153 else
3154 s390_cgr (code, ins->sreg1, s390_r0);
3156 break;
3157 case OP_ICOMPARE_IMM: {
3158 S390_SET (code, s390_r0, ins->inst_imm);
3159 if (is_unsigned (ins->next))
3160 s390_clr (code, ins->sreg1, s390_r0);
3161 else
3162 s390_cr (code, ins->sreg1, s390_r0);
3164 break;
3165 case OP_BREAK: {
3166 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3167 mono_break);
3168 S390_CALL_TEMPLATE (code, s390_r14);
3170 break;
3171 case OP_ADDCC: {
3172 CHECK_SRCDST_COM;
3173 s390_agr (code, ins->dreg, src2);
3175 break;
3176 case OP_LADD: {
3177 CHECK_SRCDST_COM;
3178 s390_agr (code, ins->dreg, src2);
3180 break;
3181 case OP_ADC: {
3182 CHECK_SRCDST_COM;
3183 s390_alcgr (code, ins->dreg, src2);
3185 break;
3186 case OP_ADD_IMM: {
3187 if (ins->dreg != ins->sreg1) {
3188 s390_lgr (code, ins->dreg, ins->sreg1);
3190 if (s390_is_imm16 (ins->inst_imm)) {
3191 s390_aghi (code, ins->dreg, ins->inst_imm);
3192 } else if (s390_is_imm32 (ins->inst_imm)) {
3193 s390_agfi (code, ins->dreg, ins->inst_imm);
3194 } else {
3195 S390_SET (code, s390_r0, ins->inst_imm);
3196 s390_agr (code, ins->dreg, s390_r0);
3199 break;
3200 case OP_LADD_IMM: {
3201 if (ins->dreg != ins->sreg1) {
3202 s390_lgr (code, ins->dreg, ins->sreg1);
3204 g_assert (s390_is_imm16 (ins->inst_imm));
3205 s390_aghi (code, ins->dreg, ins->inst_imm);
3207 break;
3208 case OP_ADC_IMM: {
3209 if (ins->dreg != ins->sreg1) {
3210 s390_lgr (code, ins->dreg, ins->sreg1);
3212 if (s390_is_imm16 (ins->inst_imm)) {
3213 s390_lghi (code, s390_r0, ins->inst_imm);
3214 s390_alcgr (code, ins->dreg, s390_r0);
3215 } else {
3216 S390_SET (code, s390_r0, ins->inst_imm);
3217 s390_alcgr (code, ins->dreg, s390_r0);
3220 break;
3221 case OP_IADD_OVF:
3222 case OP_S390_IADD_OVF: {
3223 CHECK_SRCDST_COM;
3224 s390_ar (code, ins->dreg, src2);
3225 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3226 s390_lgfr (code, ins->dreg, ins->dreg);
3228 break;
3229 case OP_IADD_OVF_UN:
3230 case OP_S390_IADD_OVF_UN: {
3231 CHECK_SRCDST_COM;
3232 s390_algr (code, ins->dreg, src2);
3233 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3234 s390_llgfr (code, ins->dreg, ins->dreg);
3236 break;
3237 case OP_ADD_OVF_CARRY: {
3238 CHECK_SRCDST_COM;
3239 s390_lghi (code, s390_r0, 0);
3240 s390_lgr (code, s390_r1, s390_r0);
3241 s390_alcgr (code, s390_r0, s390_r1);
3242 s390_agr (code, ins->dreg, src2);
3243 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3244 s390_agr (code, ins->dreg, s390_r0);
3245 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3247 break;
3248 case OP_ADD_OVF_UN_CARRY: {
3249 CHECK_SRCDST_COM;
3250 s390_alcgr (code, ins->dreg, src2);
3251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3253 break;
3254 case OP_SUBCC: {
3255 CHECK_SRCDST_NCOM;
3256 s390_sgr (code, ins->dreg, src2);
3258 break;
3259 case OP_LSUB: {
3260 CHECK_SRCDST_NCOM;
3261 s390_sgr (code, ins->dreg, src2);
3263 break;
3264 case OP_SBB: {
3265 CHECK_SRCDST_NCOM;
3266 s390_slbgr(code, ins->dreg, src2);
3268 break;
3269 case OP_SUB_IMM: {
3270 if (ins->dreg != ins->sreg1) {
3271 s390_lgr (code, ins->dreg, ins->sreg1);
3273 if (s390_is_imm16 (-ins->inst_imm)) {
3274 s390_aghi (code, ins->dreg, -ins->inst_imm);
3275 } else if (s390_is_imm32 (-ins->inst_imm)) {
3276 s390_slgfi (code, ins->dreg, ins->inst_imm);
3277 } else {
3278 S390_SET (code, s390_r0, ins->inst_imm);
3279 s390_slgr (code, ins->dreg, s390_r0);
3282 break;
3283 case OP_LSUB_IMM: {
3284 if (ins->dreg != ins->sreg1) {
3285 s390_lgr (code, ins->dreg, ins->sreg1);
3287 if (s390_is_imm16 (-ins->inst_imm)) {
3288 s390_aghi (code, ins->dreg, -ins->inst_imm);
3289 } else if (s390_is_imm32 (-ins->inst_imm)) {
3290 s390_slgfi (code, ins->dreg, ins->inst_imm);
3291 } else {
3292 S390_SET (code, s390_r0, ins->inst_imm);
3293 s390_slgr (code, ins->dreg, s390_r0);
3296 break;
3297 case OP_SBB_IMM: {
3298 if (ins->dreg != ins->sreg1) {
3299 s390_lgr (code, ins->dreg, ins->sreg1);
3301 if (s390_is_imm16 (-ins->inst_imm)) {
3302 s390_lghi (code, s390_r0, ins->inst_imm);
3303 s390_slbgr (code, ins->dreg, s390_r0);
3304 } else {
3305 S390_SET (code, s390_r0, ins->inst_imm);
3306 s390_slbgr(code, ins->dreg, s390_r0);
3309 break;
3310 case OP_SUB_OVF_CARRY: {
3311 CHECK_SRCDST_NCOM;
3312 s390_lghi (code, s390_r0, 0);
3313 s390_lgr (code, s390_r1, s390_r0);
3314 s390_slbgr (code, s390_r0, s390_r1);
3315 s390_sgr (code, ins->dreg, src2);
3316 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3317 s390_agr (code, ins->dreg, s390_r0);
3318 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3320 break;
3321 case OP_SUB_OVF_UN_CARRY: {
3322 CHECK_SRCDST_NCOM;
3323 s390_slbgr (code, ins->dreg, src2);
3324 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3326 break;
3327 case OP_LAND: {
3328 if (ins->sreg1 == ins->dreg) {
3329 s390_ngr (code, ins->dreg, ins->sreg2);
3331 else {
3332 if (ins->sreg2 == ins->dreg) {
3333 s390_ngr (code, ins->dreg, ins->sreg1);
3335 else {
3336 s390_lgr (code, ins->dreg, ins->sreg1);
3337 s390_ngr (code, ins->dreg, ins->sreg2);
3341 break;
3342 case OP_AND_IMM: {
3343 if (ins->dreg != ins->sreg1) {
3344 s390_lgr (code, ins->dreg, ins->sreg1);
3346 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3347 s390_ngr (code, ins->dreg, s390_r0);
3349 break;
3350 case OP_LDIV: {
3351 s390_lgr (code, s390_r1, ins->sreg1);
3352 s390_dsgr (code, s390_r0, ins->sreg2);
3353 s390_lgr (code, ins->dreg, s390_r1);
3355 break;
3356 case OP_LDIV_UN: {
3357 s390_lgr (code, s390_r1, ins->sreg1);
3358 s390_lghi (code, s390_r0, 0);
3359 s390_dlgr (code, s390_r0, ins->sreg2);
3360 s390_lgr (code, ins->dreg, s390_r1);
3362 break;
3363 case OP_LREM: {
3364 s390_lgr (code, s390_r1, ins->sreg1);
3365 s390_dsgr (code, s390_r0, ins->sreg2);
3366 s390_lgr (code, ins->dreg, s390_r0);
3367 break;
3369 case OP_LREM_IMM: {
3370 if (s390_is_imm16 (ins->inst_imm)) {
3371 s390_lghi (code, s390_r13, ins->inst_imm);
3372 } else {
3373 s390_lgfi (code, s390_r13, ins->inst_imm);
3375 s390_lgr (code, s390_r0, ins->sreg1);
3376 s390_dsgr (code, s390_r0, s390_r13);
3377 s390_lgfr (code, ins->dreg, s390_r0);
3379 break;
3380 case OP_LREM_UN: {
3381 s390_lgr (code, s390_r1, ins->sreg1);
3382 s390_lghi (code, s390_r0, 0);
3383 s390_dlgr (code, s390_r0, ins->sreg2);
3384 s390_lgr (code, ins->dreg, s390_r0);
3386 break;
3387 case OP_LOR: {
3388 if (ins->sreg1 == ins->dreg) {
3389 s390_ogr (code, ins->dreg, ins->sreg2);
3391 else {
3392 if (ins->sreg2 == ins->dreg) {
3393 s390_ogr (code, ins->dreg, ins->sreg1);
3395 else {
3396 s390_lgr (code, ins->dreg, ins->sreg1);
3397 s390_ogr (code, ins->dreg, ins->sreg2);
3401 break;
3402 case OP_OR_IMM: {
3403 if (ins->dreg != ins->sreg1) {
3404 s390_lgr (code, ins->dreg, ins->sreg1);
3406 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3407 s390_ogr (code, ins->dreg, s390_r0);
3409 break;
3410 case OP_LXOR: {
3411 if (ins->sreg1 == ins->dreg) {
3412 s390_xgr (code, ins->dreg, ins->sreg2);
3414 else {
3415 if (ins->sreg2 == ins->dreg) {
3416 s390_xgr (code, ins->dreg, ins->sreg1);
3418 else {
3419 s390_lgr (code, ins->dreg, ins->sreg1);
3420 s390_xgr (code, ins->dreg, ins->sreg2);
3424 break;
3425 case OP_XOR_IMM: {
3426 if (ins->dreg != ins->sreg1) {
3427 s390_lgr (code, ins->dreg, ins->sreg1);
3429 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3430 s390_xgr (code, ins->dreg, s390_r0);
3432 break;
3433 case OP_LSHL: {
3434 CHECK_SRCDST_NCOM;
3435 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3437 break;
3438 case OP_SHL_IMM:
3439 case OP_LSHL_IMM: {
3440 if (ins->sreg1 != ins->dreg) {
3441 s390_lgr (code, ins->dreg, ins->sreg1);
3443 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3445 break;
3446 case OP_LSHR: {
3447 CHECK_SRCDST_NCOM;
3448 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3450 break;
3451 case OP_SHR_IMM:
3452 case OP_LSHR_IMM: {
3453 if (ins->sreg1 != ins->dreg) {
3454 s390_lgr (code, ins->dreg, ins->sreg1);
3456 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3458 break;
3459 case OP_SHR_UN_IMM:
3460 case OP_LSHR_UN_IMM: {
3461 if (ins->sreg1 != ins->dreg) {
3462 s390_lgr (code, ins->dreg, ins->sreg1);
3464 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3466 break;
3467 case OP_LSHR_UN: {
3468 CHECK_SRCDST_NCOM;
3469 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3471 break;
3472 case OP_LNOT: {
3473 if (ins->sreg1 != ins->dreg) {
3474 s390_lgr (code, ins->dreg, ins->sreg1);
3476 s390_lghi (code, s390_r0, -1);
3477 s390_xgr (code, ins->dreg, s390_r0);
3479 break;
3480 case OP_LNEG: {
3481 s390_lcgr (code, ins->dreg, ins->sreg1);
3483 break;
3484 case OP_LMUL: {
3485 CHECK_SRCDST_COM;
3486 s390_msgr (code, ins->dreg, src2);
3488 break;
3489 case OP_MUL_IMM:
3490 case OP_LMUL_IMM: {
3491 if (ins->dreg != ins->sreg1) {
3492 s390_lgr (code, ins->dreg, ins->sreg1);
3494 if (s390_is_imm16 (ins->inst_imm)) {
3495 s390_lghi (code, s390_r13, ins->inst_imm);
3496 } else if (s390_is_imm32 (ins->inst_imm)) {
3497 s390_lgfi (code, s390_r13, ins->inst_imm);
3498 } else {
3499 S390_SET (code, s390_r13, ins->inst_imm);
3501 s390_msgr (code, ins->dreg, s390_r13);
3503 break;
3504 case OP_LMUL_OVF: {
3505 short int *o[2];
3506 s390_ltgr (code, s390_r1, ins->sreg1);
3507 s390_jz (code, 0); CODEPTR(code, o[0]);
3508 s390_ltgr (code, s390_r0, ins->sreg2);
3509 s390_jnz (code, 6);
3510 s390_lghi (code, s390_r1, 0);
3511 s390_j (code, 0); CODEPTR(code, o[1]);
3512 s390_xgr (code, s390_r0, s390_r1);
3513 s390_msgr (code, s390_r1, ins->sreg2);
3514 s390_xgr (code, s390_r0, s390_r1);
3515 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3516 s390_ltgr (code, s390_r0, s390_r0);
3517 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3518 PTRSLOT (code, o[0]);
3519 PTRSLOT (code, o[1]);
3520 s390_lgr (code, ins->dreg, s390_r1);
3522 break;
3523 case OP_LMUL_OVF_UN: {
3524 s390_lghi (code, s390_r0, 0);
3525 s390_lgr (code, s390_r1, ins->sreg1);
3526 s390_mlgr (code, s390_r0, ins->sreg2);
3527 s390_ltgr (code, s390_r0, s390_r0);
3528 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3529 s390_lgr (code, ins->dreg, s390_r1);
3531 break;
3532 case OP_IADDCC: {
3533 g_assert_not_reached ();
3534 CHECK_SRCDST_COM_I;
3535 s390_algr (code, ins->dreg, src2);
3537 break;
3538 case OP_IADD: {
3539 CHECK_SRCDST_COM_I;
3540 s390_agr (code, ins->dreg, src2);
3542 break;
3543 case OP_IADC: {
3544 g_assert_not_reached ();
3545 CHECK_SRCDST_COM_I;
3546 s390_alcgr (code, ins->dreg, src2);
3548 break;
3549 case OP_IADD_IMM: {
3550 if (ins->dreg != ins->sreg1) {
3551 s390_lgfr (code, ins->dreg, ins->sreg1);
3553 if (s390_is_imm16 (ins->inst_imm)) {
3554 s390_aghi (code, ins->dreg, ins->inst_imm);
3555 } else {
3556 s390_afi (code, ins->dreg, ins->inst_imm);
3559 break;
3560 case OP_IADC_IMM: {
3561 if (ins->dreg != ins->sreg1) {
3562 s390_lgfr (code, ins->dreg, ins->sreg1);
3564 if (s390_is_imm16 (ins->inst_imm)) {
3565 s390_lghi (code, s390_r0, ins->inst_imm);
3566 s390_alcgr (code, ins->dreg, s390_r0);
3567 } else {
3568 S390_SET (code, s390_r0, ins->inst_imm);
3569 s390_alcgr (code, ins->dreg, s390_r0);
3572 break;
3573 case OP_LADD_OVF:
3574 case OP_S390_LADD_OVF: {
3575 CHECK_SRCDST_COM;
3576 s390_agr (code, ins->dreg, src2);
3577 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3579 break;
3580 case OP_LADD_OVF_UN:
3581 case OP_S390_LADD_OVF_UN: {
3582 CHECK_SRCDST_COM;
3583 s390_algr (code, ins->dreg, src2);
3584 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3586 break;
3587 case OP_ISUBCC: {
3588 CHECK_SRCDST_NCOM_I;
3589 s390_slgr (code, ins->dreg, src2);
3591 break;
3592 case OP_ISUB: {
3593 CHECK_SRCDST_NCOM_I;
3594 s390_sgr (code, ins->dreg, src2);
3596 break;
3597 case OP_ISBB: {
3598 CHECK_SRCDST_NCOM_I;
3599 s390_slbgr (code, ins->dreg, src2);
3601 break;
3602 case OP_ISUB_IMM: {
3603 if (ins->dreg != ins->sreg1) {
3604 s390_lgfr (code, ins->dreg, ins->sreg1);
3606 if (s390_is_imm16 (-ins->inst_imm)) {
3607 s390_aghi (code, ins->dreg, -ins->inst_imm);
3608 } else {
3609 s390_agfi (code, ins->dreg, -ins->inst_imm);
3612 break;
3613 case OP_ISBB_IMM: {
3614 S390_SET (code, s390_r0, ins->inst_imm);
3615 s390_slgfr (code, ins->dreg, s390_r0);
3617 break;
3618 case OP_ISUB_OVF:
3619 case OP_S390_ISUB_OVF: {
3620 CHECK_SRCDST_NCOM;
3621 s390_sr (code, ins->dreg, src2);
3622 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3623 s390_lgfr (code, ins->dreg, ins->dreg);
3625 break;
3626 case OP_ISUB_OVF_UN:
3627 case OP_S390_ISUB_OVF_UN: {
3628 CHECK_SRCDST_NCOM;
3629 s390_slr (code, ins->dreg, src2);
3630 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3631 s390_llgfr(code, ins->dreg, ins->dreg);
3633 break;
3634 case OP_LSUB_OVF:
3635 case OP_S390_LSUB_OVF: {
3636 CHECK_SRCDST_NCOM;
3637 s390_sgr (code, ins->dreg, src2);
3638 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3640 break;
3641 case OP_LSUB_OVF_UN:
3642 case OP_S390_LSUB_OVF_UN: {
3643 CHECK_SRCDST_NCOM;
3644 s390_slgr (code, ins->dreg, src2);
3645 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3647 break;
3648 case OP_IAND: {
3649 CHECK_SRCDST_NCOM_I;
3650 s390_ngr (code, ins->dreg, src2);
3652 break;
3653 case OP_IAND_IMM: {
3654 if (ins->dreg != ins->sreg1) {
3655 s390_lgfr (code, ins->dreg, ins->sreg1);
3657 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3658 s390_ngr (code, ins->dreg, s390_r0);
3660 break;
3661 case OP_IDIV: {
3662 s390_lgfr (code, s390_r0, ins->sreg1);
3663 s390_srda (code, s390_r0, 0, 32);
3664 s390_dr (code, s390_r0, ins->sreg2);
3665 s390_lgfr (code, ins->dreg, s390_r1);
3667 break;
3668 case OP_IDIV_UN: {
3669 s390_lgfr (code, s390_r0, ins->sreg1);
3670 s390_srdl (code, s390_r0, 0, 32);
3671 s390_dlr (code, s390_r0, ins->sreg2);
3672 s390_lgfr (code, ins->dreg, s390_r1);
3674 break;
3675 case OP_IDIV_IMM: {
3676 if (s390_is_imm16 (ins->inst_imm)) {
3677 s390_lghi (code, s390_r13, ins->inst_imm);
3678 } else {
3679 s390_lgfi (code, s390_r13, ins->inst_imm);
3681 s390_lgfr (code, s390_r0, ins->sreg1);
3682 s390_srda (code, s390_r0, 0, 32);
3683 s390_dr (code, s390_r0, ins->sreg2);
3684 s390_lgfr (code, ins->dreg, s390_r1);
3686 break;
3687 case OP_IREM: {
3688 s390_lgfr (code, s390_r0, ins->sreg1);
3689 s390_srda (code, s390_r0, 0, 32);
3690 s390_dr (code, s390_r0, ins->sreg2);
3691 s390_lgfr (code, ins->dreg, s390_r0);
3692 break;
3693 case OP_IREM_UN:
3694 s390_lgfr (code, s390_r0, ins->sreg1);
3695 s390_srdl (code, s390_r0, 0, 32);
3696 s390_dlr (code, s390_r0, ins->sreg2);
3697 s390_lgfr (code, ins->dreg, s390_r0);
3699 break;
3700 case OP_IREM_IMM: {
3701 if (s390_is_imm16 (ins->inst_imm)) {
3702 s390_lghi (code, s390_r13, ins->inst_imm);
3703 } else {
3704 s390_lgfi (code, s390_r13, ins->inst_imm);
3706 s390_lgfr (code, s390_r0, ins->sreg1);
3707 s390_srda (code, s390_r0, 0, 32);
3708 s390_dr (code, s390_r0, ins->sreg2);
3709 s390_lgfr (code, ins->dreg, s390_r0);
3711 break;
3712 case OP_IOR: {
3713 CHECK_SRCDST_COM_I;
3714 s390_ogr (code, ins->dreg, src2);
3716 break;
3717 case OP_IOR_IMM: {
3718 if (ins->dreg != ins->sreg1) {
3719 s390_lgfr (code, ins->dreg, ins->sreg1);
3721 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3722 s390_ogr (code, ins->dreg, s390_r0);
3724 break;
3725 case OP_IXOR: {
3726 CHECK_SRCDST_COM_I;
3727 s390_xgr (code, ins->dreg, src2);
3729 break;
3730 case OP_IXOR_IMM: {
3731 if (ins->dreg != ins->sreg1) {
3732 s390_lgfr (code, ins->dreg, ins->sreg1);
3734 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3735 s390_xgr (code, ins->dreg, s390_r0);
3737 break;
3738 case OP_ISHL: {
3739 CHECK_SRCDST_NCOM;
3740 s390_sll (code, ins->dreg, src2, 0);
3742 break;
3743 case OP_ISHL_IMM: {
3744 if (ins->sreg1 != ins->dreg) {
3745 s390_lgfr (code, ins->dreg, ins->sreg1);
3747 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3749 break;
3750 case OP_ISHR: {
3751 CHECK_SRCDST_NCOM;
3752 s390_sra (code, ins->dreg, src2, 0);
3754 break;
3755 case OP_ISHR_IMM: {
3756 if (ins->sreg1 != ins->dreg) {
3757 s390_lgfr (code, ins->dreg, ins->sreg1);
3759 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3761 break;
3762 case OP_ISHR_UN_IMM: {
3763 if (ins->sreg1 != ins->dreg) {
3764 s390_lgfr (code, ins->dreg, ins->sreg1);
3766 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3768 break;
3769 case OP_ISHR_UN: {
3770 CHECK_SRCDST_NCOM;
3771 s390_srl (code, ins->dreg, src2, 0);
3773 break;
3774 case OP_INOT: {
3775 if (ins->sreg1 != ins->dreg) {
3776 s390_lgfr (code, ins->dreg, ins->sreg1);
3778 s390_lghi (code, s390_r0, -1);
3779 s390_xgr (code, ins->dreg, s390_r0);
3781 break;
3782 case OP_INEG: {
3783 s390_lcgr (code, ins->dreg, ins->sreg1);
3785 break;
3786 case OP_IMUL: {
3787 CHECK_SRCDST_COM_I;
3788 s390_msr (code, ins->dreg, src2);
3790 break;
3791 case OP_IMUL_IMM: {
3792 if (ins->dreg != ins->sreg1) {
3793 s390_lgfr (code, ins->dreg, ins->sreg1);
3795 if (s390_is_imm16 (ins->inst_imm)) {
3796 s390_lghi (code, s390_r0, ins->inst_imm);
3797 } else {
3798 s390_lgfi (code, s390_r0, ins->inst_imm);
3800 s390_msr (code, ins->dreg, s390_r0);
3802 break;
3803 case OP_IMUL_OVF: {
3804 short int *o[2];
3805 s390_ltr (code, s390_r1, ins->sreg1);
3806 s390_jz (code, 0); CODEPTR(code, o[0]);
3807 s390_ltr (code, s390_r0, ins->sreg2);
3808 s390_jnz (code, 6);
3809 s390_lhi (code, s390_r1, 0);
3810 s390_j (code, 0); CODEPTR(code, o[1]);
3811 s390_xr (code, s390_r0, s390_r1);
3812 s390_msr (code, s390_r1, ins->sreg2);
3813 s390_xr (code, s390_r0, s390_r1);
3814 s390_srl (code, s390_r0, 0, 31);
3815 s390_ltr (code, s390_r0, s390_r0);
3816 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3817 PTRSLOT (code, o[0]);
3818 PTRSLOT (code, o[1]);
3819 s390_lgfr (code, ins->dreg, s390_r1);
3821 break;
3822 case OP_IMUL_OVF_UN: {
3823 s390_lhi (code, s390_r0, 0);
3824 s390_lr (code, s390_r1, ins->sreg1);
3825 s390_mlr (code, s390_r0, ins->sreg2);
3826 s390_ltr (code, s390_r0, s390_r0);
3827 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3828 s390_lgfr (code, ins->dreg, s390_r1);
3830 break;
3831 case OP_ICONST:
3832 case OP_I8CONST: {
3833 S390_SET (code, ins->dreg, ins->inst_c0);
3835 break;
3836 case OP_AOTCONST: {
3837 mono_add_patch_info (cfg, code - cfg->native_code,
3838 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3839 S390_LOAD_TEMPLATE (code, ins->dreg);
3841 break;
3842 case OP_JUMP_TABLE: {
3843 mono_add_patch_info (cfg, code - cfg->native_code,
3844 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3845 S390_LOAD_TEMPLATE (code, ins->dreg);
3847 break;
3848 case OP_MOVE:
3849 if (ins->dreg != ins->sreg1) {
3850 s390_lgr (code, ins->dreg, ins->sreg1);
3852 break;
3853 case OP_LCONV_TO_I:
3854 case OP_LCONV_TO_I8:
3855 case OP_SEXT_I4:
3856 s390_lgfr (code, ins->dreg, ins->sreg1);
3857 break;
3858 case OP_LCONV_TO_I4:
3859 s390_lgfr (code, ins->dreg, ins->sreg1);
3860 break;
3861 case OP_LCONV_TO_U:
3862 case OP_LCONV_TO_U8:
3863 case OP_LCONV_TO_U4:
3864 case OP_ZEXT_I4:
3865 s390_llgfr (code, ins->dreg, ins->sreg1);
3866 break;
3867 case OP_LCONV_TO_OVF_U4:
3868 S390_SET (code, s390_r0, 4294967295);
3869 s390_clgr (code, ins->sreg1, s390_r0);
3870 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3871 s390_ltgr (code, ins->sreg1, ins->sreg1);
3872 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3873 s390_llgfr(code, ins->dreg, ins->sreg1);
3874 break;
3875 case OP_LCONV_TO_OVF_I4_UN:
3876 S390_SET (code, s390_r0, 2147483647);
3877 s390_cgr (code, ins->sreg1, s390_r0);
3878 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3879 s390_ltgr (code, ins->sreg1, ins->sreg1);
3880 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3881 s390_lgfr (code, ins->dreg, ins->sreg1);
3882 break;
3883 case OP_FMOVE:
3884 if (ins->dreg != ins->sreg1) {
3885 s390_ldr (code, ins->dreg, ins->sreg1);
3887 break;
3888 case OP_MOVE_F_TO_I8:
3889 s390_lgdr (code, ins->dreg, ins->sreg1);
3890 break;
3891 case OP_MOVE_I8_TO_F:
3892 s390_ldgr (code, ins->dreg, ins->sreg1);
3893 break;
3894 case OP_MOVE_F_TO_I4:
3895 s390_ledbr (code, s390_f0, ins->sreg1);
3896 s390_lgdr (code, ins->dreg, s390_f0);
3897 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3898 break;
3899 case OP_MOVE_I4_TO_F:
3900 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3901 s390_ldgr (code, ins->dreg, s390_r0);
3902 s390_ldebr (code, ins->dreg, ins->dreg);
3903 break;
3904 case OP_FCONV_TO_R4:
3905 s390_ledbr (code, ins->dreg, ins->sreg1);
3906 s390_ldebr (code, ins->dreg, ins->dreg);
3907 break;
3908 case OP_S390_SETF4RET:
3909 s390_ledbr (code, ins->dreg, ins->sreg1);
3910 break;
3911 case OP_TLS_GET: {
3912 if (s390_is_imm16 (ins->inst_offset)) {
3913 s390_lghi (code, s390_r13, ins->inst_offset);
3914 } else if (s390_is_imm32 (ins->inst_offset)) {
3915 s390_lgfi (code, s390_r13, ins->inst_offset);
3916 } else {
3917 S390_SET (code, s390_r13, ins->inst_offset);
3919 s390_ear (code, s390_r1, 0);
3920 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3921 s390_ear (code, s390_r1, 1);
3922 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3924 break;
3925 case OP_JMP: {
3926 if (cfg->method->save_lmf)
3927 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3929 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3930 code = emit_load_volatile_arguments (code, cfg);
3933 code = backUpStackPtr(cfg, code);
3934 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3935 mono_add_patch_info (cfg, code - cfg->native_code,
3936 MONO_PATCH_INFO_METHOD_JUMP,
3937 ins->inst_p0);
3938 s390_jcl (code, S390_CC_UN, 0);
3940 break;
3941 case OP_CHECK_THIS: {
3942 /* ensure ins->sreg1 is not NULL */
3943 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3944 s390_ltgr (code, s390_r0, s390_r0);
3945 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3947 break;
3948 case OP_ARGLIST: {
3949 int offset = cfg->sig_cookie + cfg->stack_usage;
3951 if (s390_is_imm16 (offset)) {
3952 s390_lghi (code, s390_r0, offset);
3953 } else if (s390_is_imm32 (offset)) {
3954 s390_lgfi (code, s390_r0, offset);
3955 } else {
3956 S390_SET (code, s390_r0, offset);
3958 s390_agr (code, s390_r0, cfg->frame_reg);
3959 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3961 break;
3962 case OP_FCALL: {
3963 call = (MonoCallInst*)ins;
3964 if (ins->flags & MONO_INST_HAS_METHOD)
3965 mono_add_patch_info (cfg, code-cfg->native_code,
3966 MONO_PATCH_INFO_METHOD,
3967 call->method);
3968 else
3969 mono_add_patch_info (cfg, code-cfg->native_code,
3970 MONO_PATCH_INFO_ABS,
3971 call->fptr);
3972 S390_CALL_TEMPLATE (code, s390_r14);
3973 if (call->signature->ret->type == MONO_TYPE_R4)
3974 s390_ldebr (code, s390_f0, s390_f0);
3976 break;
3977 case OP_LCALL:
3978 case OP_VCALL:
3979 case OP_VCALL2:
3980 case OP_VOIDCALL:
3981 case OP_CALL: {
3982 call = (MonoCallInst*)ins;
3983 if (ins->flags & MONO_INST_HAS_METHOD)
3984 mono_add_patch_info (cfg, code-cfg->native_code,
3985 MONO_PATCH_INFO_METHOD,
3986 call->method);
3987 else
3988 mono_add_patch_info (cfg, code-cfg->native_code,
3989 MONO_PATCH_INFO_ABS,
3990 call->fptr);
3991 S390_CALL_TEMPLATE (code, s390_r14);
3993 break;
3994 case OP_FCALL_REG: {
3995 call = (MonoCallInst*)ins;
3996 s390_lgr (code, s390_r1, ins->sreg1);
3997 s390_basr (code, s390_r14, s390_r1);
3998 if (call->signature->ret->type == MONO_TYPE_R4)
3999 s390_ldebr (code, s390_f0, s390_f0);
4001 break;
4002 case OP_LCALL_REG:
4003 case OP_VCALL_REG:
4004 case OP_VCALL2_REG:
4005 case OP_VOIDCALL_REG:
4006 case OP_CALL_REG: {
4007 s390_lgr (code, s390_r1, ins->sreg1);
4008 s390_basr (code, s390_r14, s390_r1);
4010 break;
4011 case OP_FCALL_MEMBASE: {
4012 call = (MonoCallInst*)ins;
4013 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4014 s390_basr (code, s390_r14, s390_r1);
4015 if (call->signature->ret->type == MONO_TYPE_R4)
4016 s390_ldebr (code, s390_f0, s390_f0);
4018 break;
4019 case OP_LCALL_MEMBASE:
4020 case OP_VCALL_MEMBASE:
4021 case OP_VCALL2_MEMBASE:
4022 case OP_VOIDCALL_MEMBASE:
4023 case OP_CALL_MEMBASE: {
4024 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4025 s390_basr (code, s390_r14, s390_r1);
4027 break;
4028 case OP_LOCALLOC: {
4029 int alloca_skip;
4030 int area_offset;
4032 if (cfg->param_area == 0)
4033 alloca_skip = S390_MINIMAL_STACK_SIZE;
4034 else
4035 alloca_skip = cfg->param_area;
4037 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4038 s390_lgr (code, s390_r1, ins->sreg1);
4039 if (ins->flags & MONO_INST_INIT)
4040 s390_lgr (code, s390_r0, ins->sreg1);
4041 s390_aghi (code, s390_r1, 14);
4042 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4043 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4044 if (cfg->method->save_lmf) {
4045 /*----------------------------------*/
4046 /* we have to adjust lmf ebp value */
4047 /*----------------------------------*/
4048 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4050 s390_lgr (code, s390_r13, cfg->frame_reg);
4051 if (s390_is_imm16(lmfOffset)) {
4052 s390_aghi (code, s390_r13, lmfOffset);
4053 } else if (s390_is_imm32(lmfOffset)) {
4054 s390_agfi (code, s390_r13, lmfOffset);
4055 } else {
4056 S390_SET (code, s390_r13, lmfOffset);
4058 s390_lgr (code, s390_r14, STK_BASE);
4059 s390_sgr (code, s390_r14, s390_r1);
4060 s390_stg (code, s390_r14, 0, s390_r13,
4061 G_STRUCT_OFFSET(MonoLMF, ebp));
4063 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4064 s390_sgr (code, STK_BASE, s390_r1);
4065 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4066 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4067 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4068 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4069 if (ins->flags & MONO_INST_INIT) {
4070 s390_lgr (code, s390_r1, s390_r0);
4071 s390_lgr (code, s390_r0, ins->dreg);
4072 s390_lgr (code, s390_r14, s390_r12);
4073 s390_lghi (code, s390_r13, 0);
4074 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4075 s390_jo (code, -2);
4076 s390_lgr (code, s390_r12, s390_r14);
4079 break;
4080 case OP_THROW: {
4081 s390_lgr (code, s390_r2, ins->sreg1);
4082 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4083 (gpointer) "mono_arch_throw_exception");
4084 S390_CALL_TEMPLATE(code, s390_r14);
4086 break;
4087 case OP_RETHROW: {
4088 s390_lgr (code, s390_r2, ins->sreg1);
4089 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4090 (gpointer) "mono_arch_rethrow_exception");
4091 S390_CALL_TEMPLATE(code, s390_r14);
4093 break;
4094 case OP_START_HANDLER: {
4095 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4097 S390_LONG (code, stg, stg, s390_r14, 0,
4098 spvar->inst_basereg,
4099 spvar->inst_offset);
4101 break;
4102 case OP_ENDFILTER: {
4103 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4105 if (ins->sreg1 != s390_r2)
4106 s390_lgr(code, s390_r2, ins->sreg1);
4107 S390_LONG (code, lg, lg, s390_r14, 0,
4108 spvar->inst_basereg,
4109 spvar->inst_offset);
4110 s390_br (code, s390_r14);
4112 break;
4113 case OP_ENDFINALLY: {
4114 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4116 S390_LONG (code, lg, lg, s390_r14, 0,
4117 spvar->inst_basereg,
4118 spvar->inst_offset);
4119 s390_br (code, s390_r14);
4121 break;
4122 case OP_CALL_HANDLER: {
4123 mono_add_patch_info (cfg, code-cfg->native_code,
4124 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4125 s390_brasl (code, s390_r14, 0);
4126 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4128 break;
4129 case OP_LABEL: {
4130 ins->inst_c0 = code - cfg->native_code;
4132 break;
4133 case OP_RELAXED_NOP:
4134 case OP_NOP:
4135 case OP_DUMMY_USE:
4136 case OP_DUMMY_STORE:
4137 case OP_NOT_REACHED:
4138 case OP_NOT_NULL: {
4140 break;
4141 case OP_IL_SEQ_POINT:
4142 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4143 break;
4144 case OP_SEQ_POINT: {
4145 int i;
4147 if (cfg->compile_aot)
4148 NOT_IMPLEMENTED;
4151 * Read from the single stepping trigger page. This will cause a
4152 * SIGSEGV when single stepping is enabled.
4153 * We do this _before_ the breakpoint, so single stepping after
4154 * a breakpoint is hit will step to the next IL offset.
4156 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4157 breakpointCode.pTrigger = ss_trigger_page;
4158 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4159 code += BREAKPOINT_SIZE;
4162 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4165 * A placeholder for a possible breakpoint inserted by
4166 * mono_arch_set_breakpoint ().
4168 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4169 s390_nop (code);
4172 * Add an additional nop so skipping the bp doesn't cause the ip to point
4173 * to another IL offset.
4175 s390_nop (code);
4177 break;
4179 case OP_GENERIC_CLASS_INIT: {
4180 static int byte_offset = -1;
4181 static guint8 bitmask;
4182 short int *jump;
4184 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4186 if (byte_offset < 0)
4187 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4189 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4190 s390_jo (code, 0); CODEPTR(code, jump);
4192 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4193 "mono_generic_class_init");
4194 S390_CALL_TEMPLATE(code, s390_r14);
4196 PTRSLOT (code, jump);
4198 ins->flags |= MONO_INST_GC_CALLSITE;
4199 ins->backend.pc_offset = code - cfg->native_code;
4200 break;
4202 case OP_BR:
4203 EMIT_UNCOND_BRANCH(ins);
4204 break;
4205 case OP_BR_REG: {
4206 s390_br (code, ins->sreg1);
4208 break;
4209 case OP_CEQ:
4210 case OP_ICEQ:
4211 case OP_LCEQ: {
4212 s390_lghi(code, ins->dreg, 1);
4213 s390_jz (code, 4);
4214 s390_lghi(code, ins->dreg, 0);
4216 break;
4217 case OP_CLT:
4218 case OP_ICLT:
4219 case OP_LCLT: {
4220 s390_lghi(code, ins->dreg, 1);
4221 s390_jl (code, 4);
4222 s390_lghi(code, ins->dreg, 0);
4224 break;
4225 case OP_CLT_UN:
4226 case OP_ICLT_UN:
4227 case OP_LCLT_UN: {
4228 s390_lghi(code, ins->dreg, 1);
4229 s390_jlo (code, 4);
4230 s390_lghi(code, ins->dreg, 0);
4232 break;
4233 case OP_CGT:
4234 case OP_ICGT:
4235 case OP_LCGT: {
4236 s390_lghi(code, ins->dreg, 1);
4237 s390_jh (code, 4);
4238 s390_lghi(code, ins->dreg, 0);
4240 break;
4241 case OP_CGT_UN:
4242 case OP_ICGT_UN:
4243 case OP_LCGT_UN: {
4244 s390_lghi(code, ins->dreg, 1);
4245 s390_jho (code, 4);
4246 s390_lghi(code, ins->dreg, 0);
4248 break;
4249 case OP_COND_EXC_EQ:
4250 case OP_COND_EXC_IEQ:
4251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4252 break;
4253 case OP_COND_EXC_NE_UN:
4254 case OP_COND_EXC_INE_UN:
4255 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4256 break;
4257 case OP_COND_EXC_LT:
4258 case OP_COND_EXC_ILT:
4259 case OP_COND_EXC_LT_UN:
4260 case OP_COND_EXC_ILT_UN:
4261 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4262 break;
4263 case OP_COND_EXC_GT:
4264 case OP_COND_EXC_IGT:
4265 case OP_COND_EXC_GT_UN:
4266 case OP_COND_EXC_IGT_UN:
4267 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4268 break;
4269 case OP_COND_EXC_GE:
4270 case OP_COND_EXC_IGE:
4271 case OP_COND_EXC_GE_UN:
4272 case OP_COND_EXC_IGE_UN:
4273 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4274 break;
4275 case OP_COND_EXC_LE:
4276 case OP_COND_EXC_ILE:
4277 case OP_COND_EXC_LE_UN:
4278 case OP_COND_EXC_ILE_UN:
4279 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4280 break;
4281 case OP_COND_EXC_OV:
4282 case OP_COND_EXC_IOV:
4283 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4284 break;
4285 case OP_COND_EXC_NO:
4286 case OP_COND_EXC_INO:
4287 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4288 break;
4289 case OP_COND_EXC_C:
4290 case OP_COND_EXC_IC:
4291 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4292 break;
4293 case OP_COND_EXC_NC:
4294 case OP_COND_EXC_INC:
4295 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4296 break;
4297 case OP_LBEQ:
4298 case OP_IBEQ:
4299 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4300 break;
4301 case OP_LBNE_UN:
4302 case OP_IBNE_UN:
4303 EMIT_COND_BRANCH (ins, S390_CC_NE);
4304 break;
4305 case OP_LBLT:
4306 case OP_LBLT_UN:
4307 case OP_IBLT:
4308 case OP_IBLT_UN:
4309 EMIT_COND_BRANCH (ins, S390_CC_LT);
4310 break;
4311 case OP_LBGT:
4312 case OP_LBGT_UN:
4313 case OP_IBGT:
4314 case OP_IBGT_UN:
4315 EMIT_COND_BRANCH (ins, S390_CC_GT);
4316 break;
4317 case OP_LBGE:
4318 case OP_LBGE_UN:
4319 case OP_IBGE:
4320 case OP_IBGE_UN:
4321 EMIT_COND_BRANCH (ins, S390_CC_GE);
4322 break;
4323 case OP_LBLE:
4324 case OP_LBLE_UN:
4325 case OP_IBLE:
4326 case OP_IBLE_UN:
4327 EMIT_COND_BRANCH (ins, S390_CC_LE);
4328 break;
4330 /* floating point opcodes */
4331 case OP_R8CONST: {
4332 if (*((double *) ins->inst_p0) == 0) {
4333 s390_lzdr (code, ins->dreg);
4334 } else {
4335 S390_SET (code, s390_r13, ins->inst_p0);
4336 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4339 break;
4340 case OP_R4CONST: {
4341 if (*((float *) ins->inst_p0) == 0) {
4342 s390_lzdr (code, ins->dreg);
4343 } else {
4344 S390_SET (code, s390_r13, ins->inst_p0);
4345 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4348 break;
4349 case OP_STORER8_MEMBASE_REG: {
4350 S390_LONG (code, stdy, std, ins->sreg1, 0,
4351 ins->inst_destbasereg, ins->inst_offset);
4353 break;
4354 case OP_LOADR8_MEMBASE: {
4355 S390_LONG (code, ldy, ld, ins->dreg, 0,
4356 ins->inst_basereg, ins->inst_offset);
4358 break;
4359 case OP_STORER4_MEMBASE_REG: {
4360 s390_ledbr (code, s390_f15, ins->sreg1);
4361 S390_LONG (code, stey, ste, s390_f15, 0,
4362 ins->inst_destbasereg, ins->inst_offset);
4364 break;
4365 case OP_LOADR4_MEMBASE: {
4366 S390_LONG (code, ley, le, s390_f15, 0,
4367 ins->inst_basereg, ins->inst_offset);
4368 s390_ldebr (code, ins->dreg, s390_f15);
4370 break;
4371 case OP_ICONV_TO_R_UN: {
4372 if (mono_hwcap_s390x_has_fpe) {
4373 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4374 } else {
4375 s390_llgfr (code, s390_r0, ins->sreg1);
4376 s390_cdgbr (code, ins->dreg, s390_r0);
4379 break;
4380 case OP_LCONV_TO_R_UN: {
4381 if (mono_hwcap_s390x_has_fpe) {
4382 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4383 } else {
4384 short int *jump;
4385 s390_cxgbr (code, s390_f12, ins->sreg1);
4386 s390_ltgr (code, ins->sreg1, ins->sreg1);
4387 s390_jnl (code, 0); CODEPTR(code, jump);
4388 S390_SET (code, s390_r13, 0x403f000000000000llu);
4389 s390_lgdr (code, s390_f13, s390_r13);
4390 s390_lzdr (code, s390_f15);
4391 s390_axbr (code, s390_f12, s390_f13);
4392 PTRSLOT(code, jump);
4393 s390_ldxbr (code, s390_f13, s390_f12);
4394 s390_ldr (code, ins->dreg, s390_f13);
4397 break;
4398 case OP_LCONV_TO_R4:
4399 case OP_ICONV_TO_R4: {
4400 s390_cegbr (code, ins->dreg, ins->sreg1);
4401 s390_ldebr (code, ins->dreg, ins->dreg);
4403 break;
4404 case OP_LCONV_TO_R8:
4405 case OP_ICONV_TO_R8: {
4406 s390_cdgbr (code, ins->dreg, ins->sreg1);
4408 break;
4409 case OP_FCONV_TO_I1:
4410 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4411 s390_ltgr (code, ins->dreg, ins->dreg);
4412 s390_jnl (code, 4);
4413 s390_oill (code, ins->dreg, 0x80);
4414 s390_lghi (code, s390_r0, 0xff);
4415 s390_ngr (code, ins->dreg, s390_r0);
4416 break;
4417 case OP_FCONV_TO_U1:
4418 if (mono_hwcap_s390x_has_fpe) {
4419 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4420 s390_lghi (code, s390_r0, 0xff);
4421 s390_ngr (code, ins->dreg, s390_r0);
4422 } else {
4423 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4425 break;
4426 case OP_FCONV_TO_I2:
4427 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4428 s390_ltgr (code, ins->dreg, ins->dreg);
4429 s390_jnl (code, 4);
4430 s390_oill (code, ins->dreg, 0x8000);
4431 s390_llill (code, s390_r0, 0xffff);
4432 s390_ngr (code, ins->dreg, s390_r0);
4433 break;
4434 case OP_FCONV_TO_U2:
4435 if (mono_hwcap_s390x_has_fpe) {
4436 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4437 s390_llill (code, s390_r0, 0xffff);
4438 s390_ngr (code, ins->dreg, s390_r0);
4439 } else {
4440 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4442 break;
4443 case OP_FCONV_TO_I4:
4444 case OP_FCONV_TO_I:
4445 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4446 break;
4447 case OP_FCONV_TO_U4:
4448 case OP_FCONV_TO_U:
4449 if (mono_hwcap_s390x_has_fpe) {
4450 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4451 } else {
4452 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4454 break;
4455 case OP_FCONV_TO_I8:
4456 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4457 break;
4458 case OP_FCONV_TO_U8:
4459 if (mono_hwcap_s390x_has_fpe) {
4460 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4461 } else {
4462 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4464 break;
4465 case OP_LCONV_TO_OVF_I: {
4466 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4467 short int *o[5];
4468 s390_ltgr (code, ins->sreg2, ins->sreg2);
4469 s390_jnl (code, 0); CODEPTR(code, o[0]);
4470 s390_ltgr (code, ins->sreg1, ins->sreg1);
4471 s390_jnl (code, 0); CODEPTR(code, o[1]);
4472 s390_lhi (code, s390_r13, -1);
4473 s390_cgr (code, ins->sreg1, s390_r13);
4474 s390_jnz (code, 0); CODEPTR(code, o[2]);
4475 if (ins->dreg != ins->sreg2)
4476 s390_lgr (code, ins->dreg, ins->sreg2);
4477 s390_j (code, 0); CODEPTR(code, o[3]);
4478 PTRSLOT(code, o[0]);
4479 s390_jz (code, 0); CODEPTR(code, o[4]);
4480 PTRSLOT(code, o[1]);
4481 PTRSLOT(code, o[2]);
4482 mono_add_patch_info (cfg, code - cfg->native_code,
4483 MONO_PATCH_INFO_EXC, "OverflowException");
4484 s390_brasl (code, s390_r14, 0);
4485 PTRSLOT(code, o[3]);
4486 PTRSLOT(code, o[4]);
4488 break;
4489 case OP_ABS: {
4490 s390_lpdbr (code, ins->dreg, ins->sreg1);
4492 break;
4493 case OP_SQRT: {
4494 s390_sqdbr (code, ins->dreg, ins->sreg1);
4496 break;
4497 case OP_FADD: {
4498 CHECK_SRCDST_COM_F;
4499 s390_adbr (code, ins->dreg, src2);
4501 break;
4502 case OP_FSUB: {
4503 CHECK_SRCDST_NCOM_F;
4504 s390_sdbr (code, ins->dreg, src2);
4506 break;
4507 case OP_FMUL: {
4508 CHECK_SRCDST_COM_F;
4509 s390_mdbr (code, ins->dreg, src2);
4511 break;
4512 case OP_FDIV: {
4513 CHECK_SRCDST_NCOM_F;
4514 s390_ddbr (code, ins->dreg, src2);
4516 break;
4517 case OP_FNEG: {
4518 s390_lcdbr (code, ins->dreg, ins->sreg1);
4520 break;
4521 case OP_FREM: {
4522 CHECK_SRCDST_NCOM_F;
4523 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4525 break;
4526 case OP_FCOMPARE: {
4527 s390_cdbr (code, ins->sreg1, ins->sreg2);
4529 break;
4530 case OP_FCEQ: {
4531 s390_cdbr (code, ins->sreg1, ins->sreg2);
4532 s390_lghi (code, ins->dreg, 1);
4533 s390_je (code, 4);
4534 s390_lghi (code, ins->dreg, 0);
4536 break;
4537 case OP_FCLT: {
4538 s390_cdbr (code, ins->sreg1, ins->sreg2);
4539 s390_lghi (code, ins->dreg, 1);
4540 s390_jl (code, 4);
4541 s390_lghi (code, ins->dreg, 0);
4543 break;
4544 case OP_FCLT_UN: {
4545 s390_cdbr (code, ins->sreg1, ins->sreg2);
4546 s390_lghi (code, ins->dreg, 1);
4547 s390_jlo (code, 4);
4548 s390_lghi (code, ins->dreg, 0);
4550 break;
4551 case OP_FCGT: {
4552 s390_cdbr (code, ins->sreg1, ins->sreg2);
4553 s390_lghi (code, ins->dreg, 1);
4554 s390_jh (code, 4);
4555 s390_lghi (code, ins->dreg, 0);
4557 break;
4558 case OP_FCGT_UN: {
4559 s390_cdbr (code, ins->sreg1, ins->sreg2);
4560 s390_lghi (code, ins->dreg, 1);
4561 s390_jho (code, 4);
4562 s390_lghi (code, ins->dreg, 0);
4564 break;
4565 case OP_FBEQ: {
4566 short *o;
4567 s390_jo (code, 0); CODEPTR(code, o);
4568 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4569 PTRSLOT (code, o);
4571 break;
4572 case OP_FBNE_UN:
4573 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4574 break;
4575 case OP_FBLT: {
4576 short *o;
4577 s390_jo (code, 0); CODEPTR(code, o);
4578 EMIT_COND_BRANCH (ins, S390_CC_LT);
4579 PTRSLOT (code, o);
4581 break;
4582 case OP_FBLT_UN:
4583 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4584 break;
4585 case OP_FBGT: {
4586 short *o;
4587 s390_jo (code, 0); CODEPTR(code, o);
4588 EMIT_COND_BRANCH (ins, S390_CC_GT);
4589 PTRSLOT (code, o);
4591 break;
4592 case OP_FBGT_UN:
4593 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4594 break;
4595 case OP_FBGE: {
4596 short *o;
4597 s390_jo (code, 0); CODEPTR(code, o);
4598 EMIT_COND_BRANCH (ins, S390_CC_GE);
4599 PTRSLOT (code, o);
4601 break;
4602 case OP_FBGE_UN:
4603 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4604 break;
4605 case OP_FBLE: {
4606 short *o;
4607 s390_jo (code, 0); CODEPTR(code, o);
4608 EMIT_COND_BRANCH (ins, S390_CC_LE);
4609 PTRSLOT (code, o);
4611 break;
4612 case OP_FBLE_UN:
4613 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4614 break;
4615 case OP_CKFINITE: {
4616 short *o;
4617 s390_lhi (code, s390_r13, 0x7f);
4618 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4619 s390_jz (code, 0); CODEPTR(code, o);
4620 mono_add_patch_info (cfg, code - cfg->native_code,
4621 MONO_PATCH_INFO_EXC, "OverflowException");
4622 s390_brasl (code, s390_r14,0);
4623 PTRSLOT(code, o);
4625 break;
4626 case OP_S390_MOVE: {
4627 if (ins->backend.size > 0) {
4628 if (ins->backend.size <= 256) {
4629 s390_mvc (code, ins->backend.size, ins->dreg,
4630 ins->inst_offset, ins->sreg1, ins->inst_imm);
4631 } else {
4632 s390_lgr (code, s390_r0, ins->dreg);
4633 if (ins->inst_offset > 0) {
4634 if (s390_is_imm16 (ins->inst_offset)) {
4635 s390_aghi (code, s390_r0, ins->inst_offset);
4636 } else if (s390_is_imm32 (ins->inst_offset)) {
4637 s390_agfi (code, s390_r0, ins->inst_offset);
4638 } else {
4639 S390_SET (code, s390_r13, ins->inst_offset);
4640 s390_agr (code, s390_r0, s390_r13);
4643 s390_lgr (code, s390_r12, ins->sreg1);
4644 if (ins->inst_imm > 0) {
4645 if (s390_is_imm16 (ins->inst_imm)) {
4646 s390_aghi (code, s390_r12, ins->inst_imm);
4647 } else if (s390_is_imm32 (ins->inst_imm)) {
4648 s390_agfi (code, s390_r12, ins->inst_imm);
4649 } else {
4650 S390_SET (code, s390_r13, ins->inst_imm);
4651 s390_agr (code, s390_r12, s390_r13);
4654 if (s390_is_imm16 (ins->backend.size)) {
4655 s390_lghi (code, s390_r1, ins->backend.size);
4656 } else if (s390_is_imm32 (ins->inst_offset)) {
4657 s390_agfi (code, s390_r1, ins->backend.size);
4658 } else {
4659 S390_SET (code, s390_r13, ins->backend.size);
4660 s390_agr (code, s390_r1, s390_r13);
4662 s390_lgr (code, s390_r13, s390_r1);
4663 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4664 s390_jo (code, -2);
4668 break;
4669 case OP_ATOMIC_ADD_I8: {
4670 s390_lgr (code, s390_r1, ins->sreg2);
4671 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4672 s390_agr (code, s390_r1, s390_r0);
4673 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4674 s390_jnz (code, -10);
4675 s390_lgr (code, ins->dreg, s390_r1);
4677 break;
4678 case OP_ATOMIC_EXCHANGE_I8: {
4679 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4680 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4681 s390_jnz (code, -6);
4682 s390_lgr (code, ins->dreg, s390_r0);
4684 break;
4685 case OP_ATOMIC_ADD_I4: {
4686 s390_lgfr(code, s390_r1, ins->sreg2);
4687 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4688 s390_agr (code, s390_r1, s390_r0);
4689 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4690 s390_jnz (code, -9);
4691 s390_lgfr(code, ins->dreg, s390_r1);
4693 break;
4694 case OP_ATOMIC_EXCHANGE_I4: {
4695 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4696 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4697 s390_jnz (code, -4);
4698 s390_lgfr(code, ins->dreg, s390_r0);
4700 break;
4701 case OP_S390_BKCHAIN: {
4702 s390_lgr (code, ins->dreg, ins->sreg1);
4703 if (s390_is_imm16 (cfg->stack_offset)) {
4704 s390_aghi (code, ins->dreg, cfg->stack_offset);
4705 } else if (s390_is_imm32 (cfg->stack_offset)) {
4706 s390_agfi (code, ins->dreg, cfg->stack_offset);
4707 } else {
4708 S390_SET (code, s390_r13, cfg->stack_offset);
4709 s390_agr (code, ins->dreg, s390_r13);
4712 break;
4713 case OP_MEMORY_BARRIER:
4714 s390_mem (code);
4715 break;
4716 case OP_GC_SAFE_POINT: {
4717 guint8 *br;
4719 g_assert (mono_threads_is_coop_enabled ());
4721 s390_chi (code, ins->sreg1, 1);
4722 s390_je (code, 0); CODEPTR(code, br);
4723 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4724 mono_threads_state_poll);
4725 S390_CALL_TEMPLATE (code, s390_r14);
4726 PTRSLOT (code, br);
4727 break;
4729 case OP_GC_LIVENESS_DEF:
4730 case OP_GC_LIVENESS_USE:
4731 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4732 ins->backend.pc_offset = code - cfg->native_code;
4733 break;
4734 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4735 ins->backend.pc_offset = code - cfg->native_code;
4736 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4737 break;
4738 #ifdef MONO_ARCH_SIMD_INTRINSICS
4739 case OP_ADDPS:
4740 s390x_addps (code, ins->sreg1, ins->sreg2);
4741 break;
4742 case OP_DIVPS:
4743 s390x_divps (code, ins->sreg1, ins->sreg2);
4744 break;
4745 case OP_MULPS:
4746 s390x_mulps (code, ins->sreg1, ins->sreg2);
4747 break;
4748 case OP_SUBPS:
4749 s390x_subps (code, ins->sreg1, ins->sreg2);
4750 break;
4751 case OP_MAXPS:
4752 s390x_maxps (code, ins->sreg1, ins->sreg2);
4753 break;
4754 case OP_MINPS:
4755 s390x_minps (code, ins->sreg1, ins->sreg2);
4756 break;
4757 case OP_COMPPS:
4758 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4759 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4760 break;
4761 case OP_ANDPS:
4762 s390x_andps (code, ins->sreg1, ins->sreg2);
4763 break;
4764 case OP_ANDNPS:
4765 s390x_andnps (code, ins->sreg1, ins->sreg2);
4766 break;
4767 case OP_ORPS:
4768 s390x_orps (code, ins->sreg1, ins->sreg2);
4769 break;
4770 case OP_XORPS:
4771 s390x_xorps (code, ins->sreg1, ins->sreg2);
4772 break;
4773 case OP_SQRTPS:
4774 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4775 break;
4776 case OP_RSQRTPS:
4777 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4778 break;
4779 case OP_RCPPS:
4780 s390x_rcpps (code, ins->dreg, ins->sreg1);
4781 break;
4782 case OP_ADDSUBPS:
4783 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4784 break;
4785 case OP_HADDPS:
4786 s390x_haddps (code, ins->sreg1, ins->sreg2);
4787 break;
4788 case OP_HSUBPS:
4789 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4790 break;
4791 case OP_DUPPS_HIGH:
4792 s390x_movshdup (code, ins->dreg, ins->sreg1);
4793 break;
4794 case OP_DUPPS_LOW:
4795 s390x_movsldup (code, ins->dreg, ins->sreg1);
4796 break;
4798 case OP_PSHUFLEW_HIGH:
4799 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4800 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4801 break;
4802 case OP_PSHUFLEW_LOW:
4803 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4804 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4805 break;
4806 case OP_PSHUFLED:
4807 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4808 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4809 break;
4810 case OP_SHUFPS:
4811 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4812 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4813 break;
4814 case OP_SHUFPD:
4815 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4816 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4817 break;
4819 case OP_ADDPD:
4820 s390x_addpd (code, ins->sreg1, ins->sreg2);
4821 break;
4822 case OP_DIVPD:
4823 s390x_divpd (code, ins->sreg1, ins->sreg2);
4824 break;
4825 case OP_MULPD:
4826 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4827 break;
4828 case OP_SUBPD:
4829 s390x_subpd (code, ins->sreg1, ins->sreg2);
4830 break;
4831 case OP_MAXPD:
4832 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4833 break;
4834 case OP_MINPD:
4835 s390x_minpd (code, ins->sreg1, ins->sreg2);
4836 break;
4837 case OP_COMPPD:
4838 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4839 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4840 break;
4841 case OP_ANDPD:
4842 s390x_andpd (code, ins->sreg1, ins->sreg2);
4843 break;
4844 case OP_ANDNPD:
4845 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4846 break;
4847 case OP_ORPD:
4848 s390x_orpd (code, ins->sreg1, ins->sreg2);
4849 break;
4850 case OP_XORPD:
4851 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4852 break;
4853 case OP_SQRTPD:
4854 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4855 break;
4856 case OP_ADDSUBPD:
4857 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4858 break;
4859 case OP_HADDPD:
4860 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4861 break;
4862 case OP_HSUBPD:
4863 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4864 break;
4865 case OP_DUPPD:
4866 s390x_movddup (code, ins->dreg, ins->sreg1);
4867 break;
4869 case OP_EXTRACT_MASK:
4870 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4871 break;
4873 case OP_PAND:
4874 s390x_pand (code, ins->sreg1, ins->sreg2);
4875 break;
4876 case OP_POR:
4877 s390x_por (code, ins->sreg1, ins->sreg2);
4878 break;
4879 case OP_PXOR:
4880 s390x_pxor (code, ins->sreg1, ins->sreg2);
4881 break;
4883 case OP_PADDB:
4884 s390x_paddb (code, ins->sreg1, ins->sreg2);
4885 break;
4886 case OP_PADDW:
4887 s390x_paddw (code, ins->sreg1, ins->sreg2);
4888 break;
4889 case OP_PADDD:
4890 s390x_paddd (code, ins->sreg1, ins->sreg2);
4891 break;
4892 case OP_PADDQ:
4893 s390x_paddq (code, ins->sreg1, ins->sreg2);
4894 break;
4896 case OP_PSUBB:
4897 s390x_psubb (code, ins->sreg1, ins->sreg2);
4898 break;
4899 case OP_PSUBW:
4900 s390x_psubw (code, ins->sreg1, ins->sreg2);
4901 break;
4902 case OP_PSUBD:
4903 s390x_psubd (code, ins->sreg1, ins->sreg2);
4904 break;
4905 case OP_PSUBQ:
4906 s390x_psubq (code, ins->sreg1, ins->sreg2);
4907 break;
4909 case OP_PMAXB_UN:
4910 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4911 break;
4912 case OP_PMAXW_UN:
4913 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4914 break;
4915 case OP_PMAXD_UN:
4916 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4917 break;
4919 case OP_PMAXB:
4920 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4921 break;
4922 case OP_PMAXW:
4923 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4924 break;
4925 case OP_PMAXD:
4926 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4927 break;
4929 case OP_PAVGB_UN:
4930 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4931 break;
4932 case OP_PAVGW_UN:
4933 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4934 break;
4936 case OP_PMINB_UN:
4937 s390x_pminub (code, ins->sreg1, ins->sreg2);
4938 break;
4939 case OP_PMINW_UN:
4940 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4941 break;
4942 case OP_PMIND_UN:
4943 s390x_pminud (code, ins->sreg1, ins->sreg2);
4944 break;
4946 case OP_PMINB:
4947 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4948 break;
4949 case OP_PMINW:
4950 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4951 break;
4952 case OP_PMIND:
4953 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4954 break;
4956 case OP_PCMPEQB:
4957 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4958 break;
4959 case OP_PCMPEQW:
4960 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4961 break;
4962 case OP_PCMPEQD:
4963 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4964 break;
4965 case OP_PCMPEQQ:
4966 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4967 break;
4969 case OP_PCMPGTB:
4970 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4971 break;
4972 case OP_PCMPGTW:
4973 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4974 break;
4975 case OP_PCMPGTD:
4976 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4977 break;
4978 case OP_PCMPGTQ:
4979 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4980 break;
4982 case OP_PSUM_ABS_DIFF:
4983 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4984 break;
4986 case OP_UNPACK_LOWB:
4987 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4988 break;
4989 case OP_UNPACK_LOWW:
4990 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4991 break;
4992 case OP_UNPACK_LOWD:
4993 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4994 break;
4995 case OP_UNPACK_LOWQ:
4996 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4997 break;
4998 case OP_UNPACK_LOWPS:
4999 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5000 break;
5001 case OP_UNPACK_LOWPD:
5002 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5003 break;
5005 case OP_UNPACK_HIGHB:
5006 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5007 break;
5008 case OP_UNPACK_HIGHW:
5009 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5010 break;
5011 case OP_UNPACK_HIGHD:
5012 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5013 break;
5014 case OP_UNPACK_HIGHQ:
5015 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5016 break;
5017 case OP_UNPACK_HIGHPS:
5018 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5019 break;
5020 case OP_UNPACK_HIGHPD:
5021 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5022 break;
5024 case OP_PACKW:
5025 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5026 break;
5027 case OP_PACKD:
5028 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5029 break;
5030 case OP_PACKW_UN:
5031 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5032 break;
5033 case OP_PACKD_UN:
5034 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5035 break;
5037 case OP_PADDB_SAT_UN:
5038 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5039 break;
5040 case OP_PSUBB_SAT_UN:
5041 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5042 break;
5043 case OP_PADDW_SAT_UN:
5044 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5045 break;
5046 case OP_PSUBW_SAT_UN:
5047 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5048 break;
5050 case OP_PADDB_SAT:
5051 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5052 break;
5053 case OP_PSUBB_SAT:
5054 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5055 break;
5056 case OP_PADDW_SAT:
5057 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5058 break;
5059 case OP_PSUBW_SAT:
5060 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5061 break;
5063 case OP_PMULW:
5064 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5065 break;
5066 case OP_PMULD:
5067 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5068 break;
5069 case OP_PMULQ:
5070 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5071 break;
5072 case OP_PMULW_HIGH_UN:
5073 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5074 break;
5075 case OP_PMULW_HIGH:
5076 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5077 break;
5079 case OP_PSHRW:
5080 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5081 break;
5082 case OP_PSHRW_REG:
5083 s390x_psrlw (code, ins->dreg, ins->sreg2);
5084 break;
5086 case OP_PSARW:
5087 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5088 break;
5089 case OP_PSARW_REG:
5090 s390x_psraw (code, ins->dreg, ins->sreg2);
5091 break;
5093 case OP_PSHLW:
5094 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5095 break;
5096 case OP_PSHLW_REG:
5097 s390x_psllw (code, ins->dreg, ins->sreg2);
5098 break;
5100 case OP_PSHRD:
5101 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5102 break;
5103 case OP_PSHRD_REG:
5104 s390x_psrld (code, ins->dreg, ins->sreg2);
5105 break;
5107 case OP_PSARD:
5108 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5109 break;
5110 case OP_PSARD_REG:
5111 s390x_psrad (code, ins->dreg, ins->sreg2);
5112 break;
5114 case OP_PSHLD:
5115 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5116 break;
5117 case OP_PSHLD_REG:
5118 s390x_pslld (code, ins->dreg, ins->sreg2);
5119 break;
5121 case OP_PSHRQ:
5122 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5123 break;
5124 case OP_PSHRQ_REG:
5125 s390x_psrlq (code, ins->dreg, ins->sreg2);
5126 break;
5128 /*TODO: This is appart of the sse spec but not added
5129 case OP_PSARQ:
5130 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5131 break;
5132 case OP_PSARQ_REG:
5133 s390x_psraq (code, ins->dreg, ins->sreg2);
5134 break;
5137 case OP_PSHLQ:
5138 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5139 break;
5140 case OP_PSHLQ_REG:
5141 s390x_psllq (code, ins->dreg, ins->sreg2);
5142 break;
5143 case OP_CVTDQ2PD:
5144 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5145 break;
5146 case OP_CVTDQ2PS:
5147 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5148 break;
5149 case OP_CVTPD2DQ:
5150 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5151 break;
5152 case OP_CVTPD2PS:
5153 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5154 break;
5155 case OP_CVTPS2DQ:
5156 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5157 break;
5158 case OP_CVTPS2PD:
5159 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5160 break;
5161 case OP_CVTTPD2DQ:
5162 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5163 break;
5164 case OP_CVTTPS2DQ:
5165 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5166 break;
5168 case OP_ICONV_TO_X:
5169 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5170 break;
5171 case OP_EXTRACT_I4:
5172 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5173 break;
5174 case OP_EXTRACT_I8:
5175 if (ins->inst_c0) {
5176 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5177 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5178 } else {
5179 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5181 break;
5182 case OP_EXTRACT_I1:
5183 case OP_EXTRACT_U1:
5184 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5185 if (ins->inst_c0)
5186 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5187 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5188 break;
5189 case OP_EXTRACT_I2:
5190 case OP_EXTRACT_U2:
5191 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5192 if (ins->inst_c0)
5193 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5194 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5195 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5196 break;
5197 case OP_EXTRACT_R8:
5198 if (ins->inst_c0)
5199 amd64_movhlps (code, ins->dreg, ins->sreg1);
5200 else
5201 s390x_movsd (code, ins->dreg, ins->sreg1);
5202 break;
5203 case OP_INSERT_I2:
5204 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5205 break;
5206 case OP_EXTRACTX_U2:
5207 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5208 break;
5209 case OP_INSERTX_U1_SLOW:
5210 /*sreg1 is the extracted ireg (scratch)
5211 /sreg2 is the to be inserted ireg (scratch)
5212 /dreg is the xreg to receive the value*/
5214 /*clear the bits from the extracted word*/
5215 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5216 /*shift the value to insert if needed*/
5217 if (ins->inst_c0 & 1)
5218 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5219 /*join them together*/
5220 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5221 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5222 break;
5223 case OP_INSERTX_I4_SLOW:
5224 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5225 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5226 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5227 break;
5228 case OP_INSERTX_I8_SLOW:
5229 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5230 if (ins->inst_c0)
5231 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5232 else
5233 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5234 break;
5236 case OP_INSERTX_R4_SLOW:
5237 switch (ins->inst_c0) {
5238 case 0:
5239 if (cfg->r4fp)
5240 s390x_movss (code, ins->dreg, ins->sreg2);
5241 else
5242 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5243 break;
5244 case 1:
5245 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5246 if (cfg->r4fp)
5247 s390x_movss (code, ins->dreg, ins->sreg2);
5248 else
5249 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5250 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5251 break;
5252 case 2:
5253 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5254 if (cfg->r4fp)
5255 s390x_movss (code, ins->dreg, ins->sreg2);
5256 else
5257 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5258 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5259 break;
5260 case 3:
5261 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5262 if (cfg->r4fp)
5263 s390x_movss (code, ins->dreg, ins->sreg2);
5264 else
5265 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5266 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5267 break;
5269 break;
5270 case OP_INSERTX_R8_SLOW:
5271 if (ins->inst_c0)
5272 amd64_movlhps (code, ins->dreg, ins->sreg2);
5273 else
5274 s390x_movsd (code, ins->dreg, ins->sreg2);
5275 break;
5276 case OP_STOREX_MEMBASE_REG:
5277 case OP_STOREX_MEMBASE:
5278 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5279 break;
5280 case OP_LOADX_MEMBASE:
5281 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5282 break;
5283 case OP_LOADX_ALIGNED_MEMBASE:
5284 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5285 break;
5286 case OP_STOREX_ALIGNED_MEMBASE_REG:
5287 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5288 break;
5289 case OP_STOREX_NTA_MEMBASE_REG:
5290 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5291 break;
5292 case OP_PREFETCH_MEMBASE:
5293 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5294 break;
5296 case OP_XMOVE:
5297 /*FIXME the peephole pass should have killed this*/
5298 if (ins->dreg != ins->sreg1)
5299 s390x_movaps (code, ins->dreg, ins->sreg1);
5300 break;
5301 case OP_XZERO:
5302 s390x_pxor (code, ins->dreg, ins->dreg);
5303 break;
5304 case OP_ICONV_TO_R4_RAW:
5305 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5306 break;
5308 case OP_FCONV_TO_R8_X:
5309 s390x_movsd (code, ins->dreg, ins->sreg1);
5310 break;
5312 case OP_XCONV_R8_TO_I4:
5313 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5314 switch (ins->backend.source_opcode) {
5315 case OP_FCONV_TO_I1:
5316 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5317 break;
5318 case OP_FCONV_TO_U1:
5319 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5320 break;
5321 case OP_FCONV_TO_I2:
5322 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5323 break;
5324 case OP_FCONV_TO_U2:
5325 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5326 break;
5328 break;
5330 case OP_EXPAND_I2:
5331 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5332 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5333 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5334 break;
5335 case OP_EXPAND_I4:
5336 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5337 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5338 break;
5339 case OP_EXPAND_I8:
5340 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5341 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5342 break;
5343 case OP_EXPAND_R4:
5344 if (cfg->r4fp) {
5345 s390x_movsd (code, ins->dreg, ins->sreg1);
5346 } else {
5347 s390x_movsd (code, ins->dreg, ins->sreg1);
5348 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5350 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5351 break;
5352 case OP_EXPAND_R8:
5353 s390x_movsd (code, ins->dreg, ins->sreg1);
5354 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5355 break;
5356 #endif
5357 default:
5358 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5359 g_assert_not_reached ();
5362 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5363 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5364 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5365 g_assert_not_reached ();
5368 last_offset = offset;
5371 cfg->code_len = code - cfg->native_code;
5374 /*========================= End of Function ========================*/
5376 /*------------------------------------------------------------------*/
5377 /* */
5378 /* Name - mono_arch_register_lowlevel_calls */
5379 /* */
5380 /* Function - Register routines to help with --trace operation. */
5381 /* */
5382 /*------------------------------------------------------------------*/
5384 void
5385 mono_arch_register_lowlevel_calls (void)
5389 /*========================= End of Function ========================*/
5391 /*------------------------------------------------------------------*/
5392 /* */
5393 /* Name - mono_arch_patch_code */
5394 /* */
5395 /* Function - Process the patch data created during the */
5396 /* instruction build process. This resolves jumps, */
5397 /* calls, variables etc. */
5398 /* */
5399 /*------------------------------------------------------------------*/
5401 void
5402 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5403 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5404 MonoError *error)
5406 MonoJumpInfo *patch_info;
5408 mono_error_init (error);
5410 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5411 unsigned char *ip = patch_info->ip.i + code;
5412 gconstpointer target = NULL;
5414 target = mono_resolve_patch_target (method, domain, code,
5415 patch_info, run_cctors, error);
5416 return_if_nok (error);
5418 switch (patch_info->type) {
5419 case MONO_PATCH_INFO_IP:
5420 case MONO_PATCH_INFO_LDSTR:
5421 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5422 case MONO_PATCH_INFO_LDTOKEN:
5423 case MONO_PATCH_INFO_EXC:
5424 s390_patch_addr (ip, (guint64) target);
5425 continue;
5426 case MONO_PATCH_INFO_METHOD:
5427 case MONO_PATCH_INFO_INTERNAL_METHOD:
5428 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5429 case MONO_PATCH_INFO_RGCTX_FETCH:
5430 case MONO_PATCH_INFO_ABS: {
5431 S390_EMIT_CALL (ip, target);
5432 continue;
5434 case MONO_PATCH_INFO_SWITCH:
5435 /*----------------------------------*/
5436 /* ip points at the basr r13,0/j +4 */
5437 /* instruction the vtable value */
5438 /* follows this (i.e. ip+6) */
5439 /*----------------------------------*/
5440 S390_EMIT_LOAD (ip, target);
5441 continue;
5442 case MONO_PATCH_INFO_METHODCONST:
5443 case MONO_PATCH_INFO_CLASS:
5444 case MONO_PATCH_INFO_IMAGE:
5445 case MONO_PATCH_INFO_FIELD:
5446 case MONO_PATCH_INFO_IID:
5447 case MONO_PATCH_INFO_EXC_NAME:
5448 target = S390_RELATIVE(target, ip);
5449 s390_patch_rel (ip, (guint64) target);
5450 continue;
5451 case MONO_PATCH_INFO_R4:
5452 case MONO_PATCH_INFO_R8:
5453 case MONO_PATCH_INFO_METHOD_REL:
5454 g_assert_not_reached ();
5455 continue;
5456 default:
5457 target = S390_RELATIVE(target, ip);
5458 ip += 2;
5459 s390_patch_rel (ip, (guint64) target);
5464 /*========================= End of Function ========================*/
5466 /*------------------------------------------------------------------*/
5467 /* */
5468 /* Name - emit_load_volatile_arguments */
5469 /* */
5470 /* Function - Emit the instructions to reload parameter regist- */
5471 /* registers for use with "tail" operations. */
5472 /* */
5473 /* The register loading operations performed here */
5474 /* are the mirror of the store operations performed */
5475 /* in mono_arch_emit_prolog and need to be kept in */
5476 /* synchronization with it. */
5477 /* */
5478 /*------------------------------------------------------------------*/
5480 guint8 *
5481 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5483 MonoInst *inst;
5484 MonoMethod *method = cfg->method;
5485 MonoMethodSignature *sig = mono_method_signature(method);
5486 int pos = 0, i;
5487 CallInfo *cinfo;
5489 cinfo = get_call_info (NULL, NULL, sig);
5491 if (cinfo->struct_ret) {
5492 ArgInfo *ainfo = &cinfo->ret;
5493 inst = cfg->vret_addr;
5494 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5497 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5498 ArgInfo *ainfo = cinfo->args + i;
5499 inst = cfg->args [pos];
5501 if (inst->opcode == OP_REGVAR) {
5502 if (ainfo->regtype == RegTypeGeneral)
5503 s390_lgr (code, ainfo->reg, inst->dreg);
5504 else if (ainfo->regtype == RegTypeFP) {
5505 if (inst->dreg != ainfo->reg) {
5506 if (ainfo->size == 4) {
5507 s390_ldebr (code, ainfo->reg, inst->dreg);
5508 } else {
5509 s390_ldr (code, ainfo->reg, inst->dreg);
5513 else if (ainfo->regtype == RegTypeBase) {
5514 } else
5515 g_assert_not_reached ();
5516 } else {
5517 if (ainfo->regtype == RegTypeGeneral) {
5518 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5519 g_assert_not_reached();
5520 switch (ainfo->size) {
5521 case 1:
5522 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5523 break;
5524 case 2:
5525 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5526 break;
5527 case 4:
5528 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5529 break;
5530 case 8:
5531 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532 break;
5534 } else if (ainfo->regtype == RegTypeBase) {
5535 } else if (ainfo->regtype == RegTypeFP) {
5536 if (ainfo->size == 8)
5537 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538 else if (ainfo->size == 4)
5539 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5540 else
5541 g_assert_not_reached ();
5542 } else if (ainfo->regtype == RegTypeStructByVal) {
5543 if (ainfo->reg != STK_BASE) {
5544 switch (ainfo->size) {
5545 case 1:
5546 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5547 break;
5548 case 2:
5549 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550 break;
5551 case 4:
5552 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5553 break;
5554 case 8:
5555 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5556 break;
5559 } else if (ainfo->regtype == RegTypeStructByAddr) {
5560 if (ainfo->reg != STK_BASE) {
5561 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5563 } else
5564 g_assert_not_reached ();
5566 pos++;
5569 return code;
5572 /*========================= End of Function ========================*/
5574 /*------------------------------------------------------------------*/
5575 /* */
5576 /* Name - mono_arch_emit_prolog */
5577 /* */
5578 /* Function - Create the instruction sequence for a function */
5579 /* prolog. */
5580 /* */
5581 /*------------------------------------------------------------------*/
5583 guint8 *
5584 mono_arch_emit_prolog (MonoCompile *cfg)
5586 MonoMethod *method = cfg->method;
5587 MonoBasicBlock *bb;
5588 MonoMethodSignature *sig;
5589 MonoInst *inst;
5590 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5591 guint8 *code;
5592 guint32 size;
5593 CallInfo *cinfo;
5594 int tracing = 0,
5595 argsClobbered = 0,
5596 lmfOffset,
5597 fpOffset;
5599 cfg->code_size = 512;
5601 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5602 tracing = 1;
5603 cfg->code_size += 256;
5604 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5605 cfg->code_size += 256;
5607 if (method->save_lmf)
5608 cfg->code_size += 200;
5610 cfg->native_code = code = g_malloc (cfg->code_size);
5612 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5613 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5614 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5615 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5616 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5618 if (cfg->arch.bkchain_reg != -1)
5619 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5621 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5622 cfg->used_int_regs |= 1 << 11;
5625 alloc_size = cfg->stack_offset;
5627 cfg->stack_usage = cfa_offset = alloc_size;
5628 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5629 s390_lgr (code, s390_r11, STK_BASE);
5630 if (s390_is_imm16 (alloc_size)) {
5631 s390_aghi (code, STK_BASE, -alloc_size);
5632 } else if (s390_is_imm32 (alloc_size)) {
5633 s390_agfi (code, STK_BASE, -alloc_size);
5634 } else {
5635 int stackSize = alloc_size;
5636 while (stackSize > INT_MAX) {
5637 s390_agfi (code, STK_BASE, -INT_MAX);
5638 stackSize -= INT_MAX;
5640 s390_agfi (code, STK_BASE, -stackSize);
5642 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5644 if (cfg->frame_reg != STK_BASE)
5645 s390_lgr (code, s390_r11, STK_BASE);
5647 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5649 /* store runtime generic context */
5650 if (cfg->rgctx_var) {
5651 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5653 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5654 cfg->rgctx_var->inst_basereg,
5655 cfg->rgctx_var->inst_offset);
5658 /* compute max_offset in order to use short forward jumps
5659 * we always do it on s390 because the immediate displacement
5660 * for jumps is too small
5662 max_offset = 0;
5663 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5664 MonoInst *ins;
5665 bb->max_offset = max_offset;
5667 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5668 max_offset += 6;
5670 MONO_BB_FOR_EACH_INS (bb, ins)
5671 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5674 /* load arguments allocated to register from the stack */
5675 sig = mono_method_signature (method);
5676 pos = 0;
5678 cinfo = get_call_info (cfg, cfg->mempool, sig);
5680 if (cinfo->struct_ret) {
5681 ArgInfo *ainfo = &cinfo->ret;
5682 inst = cfg->vret_addr;
5683 inst->backend.size = ainfo->vtsize;
5684 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5687 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5688 ArgInfo *ainfo = cinfo->args + i;
5689 inst = cfg->args [pos];
5691 if (inst->opcode == OP_VTARG_ADDR)
5692 inst = inst->inst_left;
5694 if (inst->opcode == OP_REGVAR) {
5695 if (ainfo->regtype == RegTypeGeneral)
5696 s390_lgr (code, inst->dreg, ainfo->reg);
5697 else if (ainfo->regtype == RegTypeFP) {
5698 if (inst->dreg != ainfo->reg) {
5699 if (ainfo->size == 4) {
5700 s390_ledbr (code, inst->dreg, ainfo->reg);
5701 } else {
5702 s390_ldr (code, inst->dreg, ainfo->reg);
5706 else if (ainfo->regtype == RegTypeBase) {
5707 s390_lgr (code, s390_r13, STK_BASE);
5708 s390_aghi (code, s390_r13, alloc_size);
5709 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5710 } else
5711 g_assert_not_reached ();
5713 if (cfg->verbose_level > 2)
5714 g_print ("Argument %d assigned to register %s\n",
5715 pos, mono_arch_regname (inst->dreg));
5716 } else {
5717 if (ainfo->regtype == RegTypeGeneral) {
5718 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5719 g_assert_not_reached();
5720 switch (ainfo->size) {
5721 case 1:
5722 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5723 break;
5724 case 2:
5725 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5726 break;
5727 case 4:
5728 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5729 break;
5730 case 8:
5731 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5732 break;
5734 } else if (ainfo->regtype == RegTypeBase) {
5735 } else if (ainfo->regtype == RegTypeFP) {
5736 if (ainfo->size == 8)
5737 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5738 else if (ainfo->size == 4)
5739 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5740 else
5741 g_assert_not_reached ();
5742 } else if (ainfo->regtype == RegTypeStructByVal) {
5743 int doffset = inst->inst_offset;
5744 int reg;
5745 if (ainfo->reg != STK_BASE)
5746 reg = ainfo->reg;
5747 else {
5748 reg = s390_r0;
5749 s390_lgr (code, s390_r13, STK_BASE);
5750 s390_aghi (code, s390_r13, alloc_size);
5753 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5754 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5755 : ainfo->size);
5757 switch (size) {
5758 case 1:
5759 if (ainfo->reg == STK_BASE)
5760 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5761 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5762 break;
5763 case 2:
5764 if (ainfo->reg == STK_BASE)
5765 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5766 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5767 break;
5768 case 4:
5769 if (ainfo->reg == STK_BASE)
5770 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5771 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5772 break;
5773 case 8:
5774 if (ainfo->reg == STK_BASE)
5775 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5776 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5777 break;
5779 } else if (ainfo->regtype == RegTypeStructByAddr) {
5780 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5781 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5782 } else
5783 g_assert_not_reached ();
5785 pos++;
5788 if (method->save_lmf) {
5789 /*---------------------------------------------------------------*/
5790 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5791 /*---------------------------------------------------------------*/
5792 lmfOffset = alloc_size - sizeof(MonoLMF);
5794 s390_lgr (code, s390_r13, cfg->frame_reg);
5795 s390_aghi (code, s390_r13, lmfOffset);
5797 /*---------------------------------------------------------------*/
5798 /* Preserve the parameter registers while we fix up the lmf */
5799 /*---------------------------------------------------------------*/
5800 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5801 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5803 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5804 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5805 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5806 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5807 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5809 /*---------------------------------------------------------------*/
5810 /* On return from this call r2 have the address of the &lmf */
5811 /*---------------------------------------------------------------*/
5812 if (lmf_addr_tls_offset == -1) {
5813 mono_add_patch_info (cfg, code - cfg->native_code,
5814 MONO_PATCH_INFO_INTERNAL_METHOD,
5815 (gpointer)"mono_get_lmf_addr");
5816 S390_CALL_TEMPLATE(code, s390_r1);
5817 } else {
5818 /*-------------------------------------------------------*/
5819 /* Get LMF by getting value from thread level storage */
5820 /*-------------------------------------------------------*/
5821 s390_ear (code, s390_r1, 0);
5822 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5823 s390_ear (code, s390_r1, 1);
5824 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5827 /*---------------------------------------------------------------*/
5828 /* Set lmf.lmf_addr = jit_tls->lmf */
5829 /*---------------------------------------------------------------*/
5830 s390_stg (code, s390_r2, 0, s390_r13,
5831 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5832 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5834 /*---------------------------------------------------------------*/
5835 /* Get current lmf */
5836 /*---------------------------------------------------------------*/
5837 s390_lg (code, s390_r0, 0, s390_r2, 0);
5839 /*---------------------------------------------------------------*/
5840 /* Set our lmf as the current lmf */
5841 /*---------------------------------------------------------------*/
5842 s390_stg (code, s390_r13, 0, s390_r2, 0);
5844 /*---------------------------------------------------------------*/
5845 /* Have our lmf.previous_lmf point to the last lmf */
5846 /*---------------------------------------------------------------*/
5847 s390_stg (code, s390_r0, 0, s390_r13,
5848 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5849 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5851 /*---------------------------------------------------------------*/
5852 /* save method info */
5853 /*---------------------------------------------------------------*/
5854 S390_SET (code, s390_r1, method);
5855 s390_stg (code, s390_r1, 0, s390_r13,
5856 G_STRUCT_OFFSET(MonoLMF, method));
5857 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5859 /*---------------------------------------------------------------*/
5860 /* save the current IP */
5861 /*---------------------------------------------------------------*/
5862 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5863 s390_basr (code, s390_r1, 0);
5864 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5868 /*---------------------------------------------------------------*/
5869 /* Save general and floating point registers */
5870 /*---------------------------------------------------------------*/
5871 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5872 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5873 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5882 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5883 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5885 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5886 for (i = 0; i < 16; i++) {
5887 s390_std (code, i, 0, s390_r13,
5888 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5889 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5890 fpOffset += sizeof(double);
5893 /*---------------------------------------------------------------*/
5894 /* Restore the parameter registers now that we've set up the lmf */
5895 /*---------------------------------------------------------------*/
5896 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5897 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5900 if (cfg->method->save_lmf)
5901 argsClobbered = TRUE;
5903 if (tracing) {
5904 argsClobbered = TRUE;
5905 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5908 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5909 argsClobbered = TRUE;
5912 * Optimize the common case of the first bblock making a call with the same
5913 * arguments as the method. This works because the arguments are still in their
5914 * original argument registers.
5916 if (!argsClobbered) {
5917 MonoBasicBlock *first_bb = cfg->bb_entry;
5918 MonoInst *next;
5919 int filter = FILTER_IL_SEQ_POINT;
5921 next = mono_bb_first_inst (first_bb, filter);
5922 if (!next && first_bb->next_bb) {
5923 first_bb = first_bb->next_bb;
5924 next = mono_bb_first_inst (first_bb, filter);
5927 if (first_bb->in_count > 1)
5928 next = NULL;
5930 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5931 ArgInfo *ainfo = cinfo->args + i;
5932 gboolean match = FALSE;
5934 inst = cfg->args [i];
5935 if (inst->opcode != OP_REGVAR) {
5936 switch (ainfo->regtype) {
5937 case RegTypeGeneral: {
5938 if (((next->opcode == OP_LOAD_MEMBASE) ||
5939 (next->opcode == OP_LOADI4_MEMBASE)) &&
5940 next->inst_basereg == inst->inst_basereg &&
5941 next->inst_offset == inst->inst_offset) {
5942 if (next->dreg == ainfo->reg) {
5943 NULLIFY_INS (next);
5944 match = TRUE;
5945 } else {
5946 next->opcode = OP_MOVE;
5947 next->sreg1 = ainfo->reg;
5948 /* Only continue if the instruction doesn't change argument regs */
5949 if (next->dreg == ainfo->reg)
5950 match = TRUE;
5953 break;
5955 default:
5956 break;
5958 } else {
5959 /* Argument allocated to (non-volatile) register */
5960 switch (ainfo->regtype) {
5961 case RegTypeGeneral:
5962 if (next->opcode == OP_MOVE &&
5963 next->sreg1 == inst->dreg &&
5964 next->dreg == ainfo->reg) {
5965 NULLIFY_INS (next);
5966 match = TRUE;
5968 break;
5969 default:
5970 break;
5974 if (match) {
5975 next = mono_inst_next (next, filter);
5976 if (!next)
5977 break;
5982 cfg->code_len = code - cfg->native_code;
5983 g_assert (cfg->code_len < cfg->code_size);
5985 return code;
5988 /*========================= End of Function ========================*/
5990 /*------------------------------------------------------------------*/
5991 /* */
5992 /* Name - mono_arch_emit_epilog */
5993 /* */
5994 /* Function - Emit the instructions for a function epilog. */
5995 /* */
5996 /*------------------------------------------------------------------*/
5998 void
5999 mono_arch_emit_epilog (MonoCompile *cfg)
6001 MonoMethod *method = cfg->method;
6002 int tracing = 0;
6003 guint8 *code;
6004 int max_epilog_size = 96;
6006 if (cfg->method->save_lmf)
6007 max_epilog_size += 128;
6009 if (mono_jit_trace_calls != NULL)
6010 max_epilog_size += 128;
6011 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6012 max_epilog_size += 128;
6014 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6015 cfg->code_size *= 2;
6016 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6017 cfg->stat_code_reallocs++;
6020 code = cfg->native_code + cfg->code_len;
6022 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6023 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6024 tracing = 1;
6027 if (method->save_lmf)
6028 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6030 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6031 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6032 } else
6033 code = backUpStackPtr(cfg, code);
6035 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6036 s390_br (code, s390_r14);
6038 cfg->code_len = code - cfg->native_code;
6040 g_assert (cfg->code_len < cfg->code_size);
6044 /*========================= End of Function ========================*/
6046 /*------------------------------------------------------------------*/
6047 /* */
6048 /* Name - mono_arch_emit_exceptions */
6049 /* */
6050 /* Function - Emit the blocks to handle exception conditions. */
6051 /* */
6052 /*------------------------------------------------------------------*/
6054 void
6055 mono_arch_emit_exceptions (MonoCompile *cfg)
6057 MonoJumpInfo *patch_info;
6058 guint8 *code;
6059 int nThrows = 0,
6060 exc_count = 0,
6061 iExc;
6062 guint32 code_size;
6063 MonoClass *exc_classes [MAX_EXC];
6064 guint8 *exc_throw_start [MAX_EXC];
6066 for (patch_info = cfg->patch_info;
6067 patch_info;
6068 patch_info = patch_info->next) {
6069 if (patch_info->type == MONO_PATCH_INFO_EXC)
6070 exc_count++;
6073 code_size = exc_count * 48;
6075 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6076 cfg->code_size *= 2;
6077 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6078 cfg->stat_code_reallocs++;
6081 code = cfg->native_code + cfg->code_len;
6083 /*---------------------------------------------------------------------*/
6084 /* Add code to raise exceptions */
6085 /*---------------------------------------------------------------------*/
6086 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6087 switch (patch_info->type) {
6088 case MONO_PATCH_INFO_EXC: {
6089 guint8 *ip = patch_info->ip.i + cfg->native_code;
6090 MonoClass *exc_class;
6091 guint64 throw_ip;
6093 /*-----------------------------------------------------*/
6094 /* Patch the branch in epilog to come here */
6095 /*-----------------------------------------------------*/
6096 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6098 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6099 "System",
6100 patch_info->data.name);
6101 throw_ip = patch_info->ip.i;
6103 for (iExc = 0; iExc < nThrows; ++iExc)
6104 if (exc_classes [iExc] == exc_class)
6105 break;
6107 if (iExc < nThrows) {
6108 s390_jcl (code, S390_CC_UN,
6109 (guint64) exc_throw_start [iExc]);
6110 patch_info->type = MONO_PATCH_INFO_NONE;
6111 } else {
6113 if (nThrows < MAX_EXC) {
6114 exc_classes [nThrows] = exc_class;
6115 exc_throw_start [nThrows] = code;
6118 /*---------------------------------------------*/
6119 /* Patch the parameter passed to the handler */
6120 /*---------------------------------------------*/
6121 S390_SET (code, s390_r2, exc_class->type_token);
6122 /*---------------------------------------------*/
6123 /* Load return address & parameter register */
6124 /*---------------------------------------------*/
6125 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6126 cfg->native_code + 8), code));
6127 /*---------------------------------------------*/
6128 /* Reuse the current patch to set the jump */
6129 /*---------------------------------------------*/
6130 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6131 patch_info->data.name = "mono_arch_throw_corlib_exception";
6132 patch_info->ip.i = code - cfg->native_code;
6133 S390_BR_TEMPLATE (code, s390_r1);
6135 break;
6137 default:
6138 /* do nothing */
6139 break;
6143 cfg->code_len = code - cfg->native_code;
6145 g_assert (cfg->code_len < cfg->code_size);
6149 /*========================= End of Function ========================*/
6151 /*------------------------------------------------------------------*/
6152 /* */
6153 /* Name - mono_arch_finish_init */
6154 /* */
6155 /* Function - Setup the JIT's Thread Level Specific Data. */
6156 /* */
6157 /*------------------------------------------------------------------*/
6159 void
6160 mono_arch_finish_init (void)
6162 appdomain_tls_offset = mono_domain_get_tls_offset();
6163 lmf_tls_offset = mono_get_lmf_tls_offset();
6164 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6167 /*========================= End of Function ========================*/
6169 /*------------------------------------------------------------------*/
6170 /* */
6171 /* Name - mono_arch_free_jit_tls_data */
6172 /* */
6173 /* Function - Free tls data. */
6174 /* */
6175 /*------------------------------------------------------------------*/
6177 void
6178 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6182 /*========================= End of Function ========================*/
6184 /*------------------------------------------------------------------*/
6185 /* */
6186 /* Name - mono_arch_emit_inst_for_method */
6187 /* */
6188 /*------------------------------------------------------------------*/
6190 MonoInst*
6191 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6193 return NULL;
6196 /*========================= End of Function ========================*/
6198 /*------------------------------------------------------------------*/
6199 /* */
6200 /* Name - mono_arch_decompose_opts */
6201 /* */
6202 /* Function - Decompose opcode into a System z opcode. */
6203 /* */
6204 /*------------------------------------------------------------------*/
6206 void
6207 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6210 * Have to rename these to avoid being decomposed normally, since the normal
6211 * decomposition does not work on S390.
6213 switch (ins->opcode) {
6214 case OP_ISUB_OVF:
6215 ins->opcode = OP_S390_ISUB_OVF;
6216 break;
6217 case OP_ISUB_OVF_UN:
6218 ins->opcode = OP_S390_ISUB_OVF_UN;
6219 break;
6220 case OP_IADD_OVF:
6221 ins->opcode = OP_S390_IADD_OVF;
6222 break;
6223 case OP_IADD_OVF_UN:
6224 ins->opcode = OP_S390_IADD_OVF_UN;
6225 break;
6226 case OP_LADD_OVF:
6227 ins->opcode = OP_S390_LADD_OVF;
6228 break;
6229 case OP_LADD_OVF_UN:
6230 ins->opcode = OP_S390_LADD_OVF_UN;
6231 break;
6232 case OP_LSUB_OVF:
6233 ins->opcode = OP_S390_LSUB_OVF;
6234 break;
6235 case OP_LSUB_OVF_UN:
6236 ins->opcode = OP_S390_LSUB_OVF_UN;
6237 break;
6238 default:
6239 break;
6243 /*========================= End of Function ========================*/
6245 /*------------------------------------------------------------------*/
6246 /* */
6247 /* Name - mono_arch_print_tree */
6248 /* */
6249 /* Function - Print platform-specific opcode details. */
6250 /* */
6251 /* Returns - 1 - opcode details have been printed */
6252 /* 0 - opcode details have not been printed */
6253 /* */
6254 /*------------------------------------------------------------------*/
6256 gboolean
6257 mono_arch_print_tree (MonoInst *tree, int arity)
6259 gboolean done;
6261 switch (tree->opcode) {
6262 case OP_S390_LOADARG:
6263 case OP_S390_ARGREG:
6264 case OP_S390_ARGPTR:
6265 printf ("[0x%lx(%s)]", tree->inst_offset,
6266 mono_arch_regname (tree->inst_basereg));
6267 done = 1;
6268 break;
6269 case OP_S390_STKARG:
6270 printf ("[0x%lx(previous_frame)]",
6271 tree->inst_offset);
6272 done = 1;
6273 break;
6274 case OP_S390_MOVE:
6275 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6276 tree->inst_offset, tree->backend.size,
6277 mono_arch_regname(tree->dreg),
6278 tree->inst_imm,
6279 mono_arch_regname(tree->sreg1));
6280 done = 1;
6281 break;
6282 case OP_S390_SETF4RET:
6283 printf ("[f%s,f%s]",
6284 mono_arch_regname (tree->dreg),
6285 mono_arch_regname (tree->sreg1));
6286 done = 1;
6287 break;
6288 case OP_TLS_GET:
6289 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6290 tree->inst_imm,
6291 mono_arch_regname (tree->sreg1));
6292 done = 1;
6293 break;
6294 case OP_S390_BKCHAIN:
6295 printf ("[previous_frame(%s)]",
6296 mono_arch_regname (tree->sreg1));
6297 done = 1;
6298 default:
6299 done = 0;
6301 return (done);
6304 /*========================= End of Function ========================*/
6306 /*------------------------------------------------------------------*/
6307 /* */
6308 /* Name - mono_arch_regalloc_cost */
6309 /* */
6310 /* Function - Determine the cost, in the number of memory */
6311 /* references, of the action of allocating the var- */
6312 /* iable VMV into a register during global register */
6313 /* allocation. */
6314 /* */
6315 /* Returns - Cost */
6316 /* */
6317 /*------------------------------------------------------------------*/
6319 guint32
6320 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6322 /* FIXME: */
6323 return 2;
6326 /*========================= End of Function ========================*/
6328 /*------------------------------------------------------------------*/
6329 /* */
6330 /* Name - mono_arch_flush_register_windows */
6331 /* */
6332 /* Function - */
6333 /* */
6334 /* Returns - */
6335 /* */
6336 /*------------------------------------------------------------------*/
6338 void
6339 mono_arch_flush_register_windows (void)
6343 /*========================= End of Function ========================*/
6345 /*------------------------------------------------------------------*/
6346 /* */
6347 /* Name - mono_arch_is_inst_imm */
6348 /* */
6349 /* Function - Determine if operand qualifies as an immediate */
6350 /* value. For s390 this is a value -32768-32768 */
6351 /* */
6352 /* Returns - True|False - is [not] immediate value. */
6353 /* */
6354 /*------------------------------------------------------------------*/
6356 gboolean
6357 mono_arch_is_inst_imm (gint64 imm)
6359 return s390_is_imm32 (imm);
6362 /*========================= End of Function ========================*/
6364 /*------------------------------------------------------------------*/
6365 /* */
6366 /* Name - mono_arch_get_patch_offset */
6367 /* */
6368 /* Function - Dummy entry point until s390x supports aot. */
6369 /* */
6370 /* Returns - Offset for patch. */
6371 /* */
6372 /*------------------------------------------------------------------*/
6374 guint32
6375 mono_arch_get_patch_offset (guint8 *code)
6377 return 0;
6380 /*========================= End of Function ========================*/
6382 /*------------------------------------------------------------------*/
6383 /* */
6384 /* Name - mono_arch_context_get_int_reg. */
6385 /* */
6386 /* Function - */
6387 /* */
6388 /* Returns - Return a register from the context. */
6389 /* */
6390 /*------------------------------------------------------------------*/
6392 mgreg_t
6393 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6395 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6398 /*========================= End of Function ========================*/
6400 /*------------------------------------------------------------------*/
6401 /* */
6402 /* Name - mono_arch_context_set_int_reg. */
6403 /* */
6404 /* Function - Set a value in a specified register. */
6405 /* */
6406 /*------------------------------------------------------------------*/
6408 void
6409 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6411 ctx->uc_mcontext.gregs[reg] = val;
6414 /*========================= End of Function ========================*/
6416 /*------------------------------------------------------------------*/
6417 /* */
6418 /* Name - mono_arch_get_this_arg_from_call. */
6419 /* */
6420 /* Function - */
6421 /* */
6422 /*------------------------------------------------------------------*/
6424 gpointer
6425 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6427 return (gpointer) regs [s390_r2];
6430 /*========================= End of Function ========================*/
6432 /*------------------------------------------------------------------*/
6433 /* */
6434 /* Name - mono_arch_install_handler_block_guard */
6435 /* */
6436 /* Function - */
6437 /* */
6438 /*------------------------------------------------------------------*/
6440 gpointer
6441 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6442 MonoContext *ctx, gpointer new_value)
6444 int offset;
6445 gpointer *sp, old_value;
6446 char *bp;
6448 offset = clause->exvar_offset;
6450 /*Load the spvar*/
6451 bp = MONO_CONTEXT_GET_BP (ctx);
6452 sp = *(gpointer*)(bp + offset);
6454 old_value = *sp;
6455 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6456 return old_value;
6458 *sp = new_value;
6460 return old_value;
6463 /*========================= End of Function ========================*/
6465 /*------------------------------------------------------------------*/
6466 /* */
6467 /* Name - get_delegate_invoke_impl. */
6468 /* */
6469 /* Function - */
6470 /* */
6471 /*------------------------------------------------------------------*/
6473 static gpointer
6474 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6476 guint8 *code, *start;
6478 if (has_target) {
6479 int size = 32;
6481 start = code = mono_global_codeman_reserve (size);
6483 /* Replace the this argument with the target */
6484 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6485 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6486 s390_br (code, s390_r1);
6487 g_assert ((code - start) <= size);
6489 mono_arch_flush_icache (start, size);
6490 } else {
6491 int size, i;
6493 size = 32 + param_count * 8;
6494 start = code = mono_global_codeman_reserve (size);
6496 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6497 /* slide down the arguments */
6498 for (i = 0; i < param_count; ++i) {
6499 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6501 s390_br (code, s390_r1);
6503 g_assert ((code - start) <= size);
6505 mono_arch_flush_icache (start, size);
6508 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6510 if (has_target) {
6511 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6512 } else {
6513 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6514 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6515 g_free (name);
6518 return start;
6521 /*========================= End of Function ========================*/
6523 /*------------------------------------------------------------------*/
6524 /* */
6525 /* Name - mono_arch_get_delegate_invoke_impls. */
6526 /* */
6527 /* Function - */
6528 /* */
6529 /*------------------------------------------------------------------*/
6531 GSList*
6532 mono_arch_get_delegate_invoke_impls (void)
6534 GSList *res = NULL;
6535 MonoTrampInfo *info;
6536 int i;
6538 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6539 res = g_slist_prepend (res, info);
6541 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6542 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6543 res = g_slist_prepend (res, info);
6546 return res;
6549 /*========================= End of Function ========================*/
6551 /*------------------------------------------------------------------*/
6552 /* */
6553 /* Name - mono_arch_get_delegate_invoke_impl. */
6554 /* */
6555 /* Function - */
6556 /* */
6557 /*------------------------------------------------------------------*/
6559 gpointer
6560 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6562 guint8 *code, *start;
6564 /* FIXME: Support more cases */
6565 if (MONO_TYPE_ISSTRUCT (sig->ret))
6566 return NULL;
6568 if (has_target) {
6569 static guint8* cached = NULL;
6571 if (cached)
6572 return cached;
6574 if (mono_aot_only) {
6575 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6576 } else {
6577 MonoTrampInfo *info;
6578 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6579 mono_tramp_info_register (info, NULL);
6582 mono_memory_barrier ();
6584 cached = start;
6585 } else {
6586 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6587 int i;
6589 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6590 return NULL;
6591 for (i = 0; i < sig->param_count; ++i)
6592 if (!mono_is_regsize_var (sig->params [i]))
6593 return NULL;
6596 code = cache [sig->param_count];
6597 if (code)
6598 return code;
6600 if (mono_aot_only) {
6601 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6602 start = mono_aot_get_trampoline (name);
6603 g_free (name);
6604 } else {
6605 MonoTrampInfo *info;
6606 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6607 mono_tramp_info_register (info, NULL);
6610 mono_memory_barrier ();
6612 cache [sig->param_count] = start;
6614 return start;
6617 /*========================= End of Function ========================*/
6619 /*------------------------------------------------------------------*/
6620 /* */
6621 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6622 /* */
6623 /* Function - */
6624 /* */
6625 /*------------------------------------------------------------------*/
6627 gpointer
6628 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6629 int offset, gboolean load_imt_reg)
6631 guint8 *code, *start;
6632 int size = 40;
6634 start = code = mono_global_codeman_reserve (size);
6637 * Replace the "this" argument with the target
6639 s390_lgr (code, s390_r1, s390_r2);
6640 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6643 * Load the IMT register, if needed
6645 if (load_imt_reg) {
6646 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6650 * Load the vTable
6652 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6653 if (offset != 0) {
6654 s390_agfi(code, s390_r1, offset);
6656 s390_lg (code, s390_r1, 0, s390_r1, 0);
6657 s390_br (code, s390_r1);
6659 return(start);
6662 /*========================= End of Function ========================*/
6664 /*------------------------------------------------------------------*/
6665 /* */
6666 /* Name - mono_arch_build_imt_trampoline. */
6667 /* */
6668 /* Function - */
6669 /* */
6670 /*------------------------------------------------------------------*/
6672 gpointer
6673 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6674 MonoIMTCheckItem **imt_entries, int count,
6675 gpointer fail_tramp)
6677 int i;
6678 int size = 0;
6679 guchar *code, *start;
6680 char trampName[64];
6682 for (i = 0; i < count; ++i) {
6683 MonoIMTCheckItem *item = imt_entries [i];
6684 if (item->is_equals) {
6685 if (item->check_target_idx) {
6686 if (!item->compare_done)
6687 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6688 if (item->has_target_code)
6689 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6690 else
6691 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6692 LOAD_SIZE;
6693 } else {
6694 if (fail_tramp) {
6695 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6696 2 * LOADCON_SIZE;
6697 if (!item->has_target_code)
6698 item->chunk_size += LOAD_SIZE;
6699 } else {
6700 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6701 #if ENABLE_WRONG_METHOD_CHECK
6702 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6703 #endif
6706 } else {
6707 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6708 imt_entries [item->check_target_idx]->compare_done = TRUE;
6710 size += item->chunk_size;
6713 if (fail_tramp)
6714 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6715 else
6716 code = mono_domain_code_reserve (domain, size);
6718 start = code;
6720 for (i = 0; i < count; ++i) {
6721 MonoIMTCheckItem *item = imt_entries [i];
6722 item->code_target = (guint8 *) code;
6723 if (item->is_equals) {
6724 if (item->check_target_idx) {
6725 if (!item->compare_done) {
6726 S390_SET (code, s390_r0, item->key);
6727 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6729 item->jmp_code = (guint8*) code;
6730 s390_jcl (code, S390_CC_NE, 0);
6732 if (item->has_target_code) {
6733 S390_SET (code, s390_r1, item->value.target_code);
6734 } else {
6735 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6736 s390_lg (code, s390_r1, 0, s390_r1, 0);
6738 s390_br (code, s390_r1);
6739 } else {
6740 if (fail_tramp) {
6741 gint64 target;
6743 S390_SET (code, s390_r0, item->key);
6744 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6745 item->jmp_code = (guint8*) code;
6746 s390_jcl (code, S390_CC_NE, 0);
6747 if (item->has_target_code) {
6748 S390_SET (code, s390_r1, item->value.target_code);
6749 } else {
6750 g_assert (vtable);
6751 S390_SET (code, s390_r1,
6752 (&(vtable->vtable [item->value.vtable_slot])));
6753 s390_lg (code, s390_r1, 0, s390_r1, 0);
6755 s390_br (code, s390_r1);
6756 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6757 s390_patch_rel(item->jmp_code+2, target);
6758 S390_SET (code, s390_r1, fail_tramp);
6759 s390_br (code, s390_r1);
6760 item->jmp_code = NULL;
6761 } else {
6762 /* enable the commented code to assert on wrong method */
6763 #if ENABLE_WRONG_METHOD_CHECK
6764 g_assert_not_reached ();
6765 #endif
6766 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6767 s390_lg (code, s390_r1, 0, s390_r1, 0);
6768 s390_br (code, s390_r1);
6771 } else {
6772 S390_SET (code, s390_r0, item->key);
6773 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6774 item->jmp_code = (guint8 *) code;
6775 s390_jcl (code, S390_CC_GE, 0);
6779 * patch the branches to get to the target items
6781 for (i = 0; i < count; ++i) {
6782 MonoIMTCheckItem *item = imt_entries [i];
6783 if (item->jmp_code) {
6784 if (item->check_target_idx) {
6785 gint64 offset;
6786 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6787 item->jmp_code);
6788 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6793 mono_arch_flush_icache ((guint8*)start, (code - start));
6794 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6796 if (!fail_tramp)
6797 mono_stats.imt_trampolines_size += (code - start);
6799 g_assert (code - start <= size);
6801 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6802 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6804 return (start);
6807 /*========================= End of Function ========================*/
6809 /*------------------------------------------------------------------*/
6810 /* */
6811 /* Name - mono_arch_find_imt_method. */
6812 /* */
6813 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6814 /* found in the save area. */
6815 /* */
6816 /*------------------------------------------------------------------*/
6818 MonoMethod*
6819 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6821 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6824 /*========================= End of Function ========================*/
6826 /*------------------------------------------------------------------*/
6827 /* */
6828 /* Name - mono_arch_find_static_call_vtable */
6829 /* */
6830 /* Function - Find the static call vtable. */
6831 /* */
6832 /*------------------------------------------------------------------*/
6834 MonoVTable*
6835 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6837 mgreg_t *r = (mgreg_t*)regs;
6839 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6842 /*========================= End of Function ========================*/
6844 /*------------------------------------------------------------------*/
6845 /* */
6846 /* Name - mono_arch_get_cie_program */
6847 /* */
6848 /* Function - Find the static call vtable. */
6849 /* */
6850 /*------------------------------------------------------------------*/
6852 GSList*
6853 mono_arch_get_cie_program (void)
6855 GSList *l = NULL;
6857 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6859 return(l);
6862 /*========================= End of Function ========================*/
6864 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6866 /*------------------------------------------------------------------*/
6867 /* */
6868 /* Name - mono_arch_set_breakpoint. */
6869 /* */
6870 /* Function - Set a breakpoint at the native code corresponding */
6871 /* to JI at NATIVE_OFFSET. The location should */
6872 /* contain code emitted by OP_SEQ_POINT. */
6873 /* */
6874 /*------------------------------------------------------------------*/
6876 void
6877 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6879 guint8 *code = ip;
6881 breakpointCode.pTrigger = bp_trigger_page;
6882 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6883 code += BREAKPOINT_SIZE;
6886 /*========================= End of Function ========================*/
6888 /*------------------------------------------------------------------*/
6889 /* */
6890 /* Name - mono_arch_clear_breakpoint. */
6891 /* */
6892 /* Function - Clear the breakpoint at IP. */
6893 /* */
6894 /*------------------------------------------------------------------*/
6896 void
6897 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6899 guint8 *code = ip;
6900 int i;
6902 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6903 s390_nop(code);
6906 /*========================= End of Function ========================*/
6908 /*------------------------------------------------------------------*/
6909 /* */
6910 /* Name - mono_arch_is_breakpoint_event. */
6911 /* */
6912 /* Function - */
6913 /* */
6914 /*------------------------------------------------------------------*/
6916 gboolean
6917 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6919 siginfo_t* sinfo = (siginfo_t*) info;
6922 * Sometimes the address is off by 4
6924 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6925 return TRUE;
6926 else
6927 return FALSE;
6930 /*========================= End of Function ========================*/
6932 /*------------------------------------------------------------------*/
6933 /* */
6934 /* Name - mono_arch_skip_breakpoint. */
6935 /* */
6936 /* Function - Modify the CTX so the IP is placed after the */
6937 /* breakpoint instruction, so when we resume, the */
6938 /* instruction is not executed again. */
6939 /* */
6940 /*------------------------------------------------------------------*/
6942 void
6943 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6945 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6948 /*========================= End of Function ========================*/
6950 /*------------------------------------------------------------------*/
6951 /* */
6952 /* Name - mono_arch_start_single_stepping. */
6953 /* */
6954 /* Function - Start single stepping. */
6955 /* */
6956 /*------------------------------------------------------------------*/
6958 void
6959 mono_arch_start_single_stepping (void)
6961 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6964 /*========================= End of Function ========================*/
6966 /*------------------------------------------------------------------*/
6967 /* */
6968 /* Name - mono_arch_stop_single_stepping. */
6969 /* */
6970 /* Function - Stop single stepping. */
6971 /* */
6972 /*------------------------------------------------------------------*/
6974 void
6975 mono_arch_stop_single_stepping (void)
6977 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6980 /*========================= End of Function ========================*/
6982 /*------------------------------------------------------------------*/
6983 /* */
6984 /* Name - mono_arch_is_single_step_event. */
6985 /* */
6986 /* Function - Return whether the machine state in sigctx cor- */
6987 /* responds to a single step event. */
6988 /* */
6989 /*------------------------------------------------------------------*/
6991 gboolean
6992 mono_arch_is_single_step_event (void *info, void *sigctx)
6994 siginfo_t* sinfo = (siginfo_t*) info;
6997 * Sometimes the address is off by 4
6999 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7000 return TRUE;
7001 else
7002 return FALSE;
7005 /*========================= End of Function ========================*/
7007 /*------------------------------------------------------------------*/
7008 /* */
7009 /* Name - mono_arch_skip_single_step. */
7010 /* */
7011 /* Function - Modify the ctx so the IP is placed after the */
7012 /* single step trigger instruction, so that the */
7013 /* instruction is not executed again. */
7014 /* */
7015 /*------------------------------------------------------------------*/
7017 void
7018 mono_arch_skip_single_step (MonoContext *ctx)
7020 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7023 /*========================= End of Function ========================*/
7025 /*------------------------------------------------------------------*/
7026 /* */
7027 /* Name - mono_arch_create_seq_point_info. */
7028 /* */
7029 /* Function - Return a pointer to a data struction which is */
7030 /* used by the sequence point implementation in */
7031 /* AOTed code. */
7032 /* */
7033 /*------------------------------------------------------------------*/
7035 gpointer
7036 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7038 NOT_IMPLEMENTED;
7039 return NULL;
7042 /*========================= End of Function ========================*/
7044 /*------------------------------------------------------------------*/
7045 /* */
7046 /* Name - mono_arch_init_lmf_ext. */
7047 /* */
7048 /* Function - */
7049 /* */
7050 /*------------------------------------------------------------------*/
7052 void
7053 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7055 ext->lmf.previous_lmf = prev_lmf;
7056 /* Mark that this is a MonoLMFExt */
7057 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7058 ext->lmf.ebp = (gssize)ext;
7061 /*========================= End of Function ========================*/
7063 #endif
7065 /*------------------------------------------------------------------*/
7066 /* */
7067 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7068 /* */
7069 /* Function - If this CPU supports vector operations then it */
7070 /* supports the equivalent of SSE1-4. */
7071 /* */
7072 /*------------------------------------------------------------------*/
7074 guint32
7075 mono_arch_cpu_enumerate_simd_versions (void)
7077 guint32 sseOpts = 0;
7079 if (mono_hwcap_s390x_has_vec)
7080 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7081 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7082 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7083 SIMD_VERSION_SSE4a);
7085 return (sseOpts);
7088 /*========================= End of Function ========================*/
7090 /*------------------------------------------------------------------*/
7091 /* */
7092 /* Name - mono_arch_opcode_supported. */
7093 /* */
7094 /* Function - Check if a given return code is supported. */
7095 /* */
7096 /*------------------------------------------------------------------*/
7098 gboolean
7099 mono_arch_opcode_supported (int opcode)
7101 switch (opcode) {
7102 case OP_ATOMIC_ADD_I4:
7103 case OP_ATOMIC_ADD_I8:
7104 case OP_ATOMIC_EXCHANGE_I4:
7105 case OP_ATOMIC_EXCHANGE_I8:
7106 return TRUE;
7107 default:
7108 return FALSE;
7112 /*========================= End of Function ========================*/