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