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