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