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