2f3cd3ebca373f285a384dd5161b46c1baee8f94
[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_I1:
1631                 case MONO_TYPE_U1:
1632                 case MONO_TYPE_I2:
1633                 case MONO_TYPE_U2:
1634                 case MONO_TYPE_I4:
1635                 case MONO_TYPE_U4:
1636                 case MONO_TYPE_I:
1637                 case MONO_TYPE_U:
1638                 case MONO_TYPE_OBJECT:
1639                 case MONO_TYPE_PTR:
1640                 case MONO_TYPE_FNPTR:
1641                         cinfo->ret.reg = s390_r2;
1642                         sz->code_size += 4;
1643                         break;
1644                 case MONO_TYPE_R4:
1645                 case MONO_TYPE_R8:
1646                         cinfo->ret.reg = s390_f0;
1647                         sz->code_size += 4;
1648                         break;
1649                 case MONO_TYPE_I8:
1650                 case MONO_TYPE_U8:
1651                         cinfo->ret.reg = s390_r2;
1652                         sz->code_size += 4;
1653                         break;
1654                 case MONO_TYPE_GENERICINST:
1655                         if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1656                                 cinfo->ret.reg = s390_r2;
1657                                 sz->code_size += 4;
1658                                 break;
1659                         }
1660                         /* Fall through */
1661                 case MONO_TYPE_VALUETYPE: {
1662                         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1663                         if (klass->enumtype) {
1664                                 simpleType = mono_class_enum_basetype (klass)->type;
1665                                 goto enum_retvalue;
1666                         }
1667                         size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1668         
1669                         cinfo->struct_ret = 1;
1670                         cinfo->ret.size   = size;
1671                         cinfo->ret.vtsize = size;
1672                         break;
1673                 }
1674                 case MONO_TYPE_TYPEDBYREF:
1675                         size = sizeof (MonoTypedRef);
1676                         cinfo->struct_ret = 1;
1677                         cinfo->ret.size   = size;
1678                         cinfo->ret.vtsize = size;
1679                         break;
1680                 case MONO_TYPE_VOID:
1681                         break;
1682                 default:
1683                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
1684         }
1685
1686
1687         pstart = 0;
1688         /*
1689          * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1690          * the first argument, allowing 'this' to be always passed in the first arg reg.
1691          * Also do this if the first argument is a reference type, since virtual calls
1692          * are sometimes made using calli without sig->hasthis set, like in the delegate
1693          * invoke wrappers.
1694          */
1695         if (cinfo->struct_ret && !is_pinvoke && 
1696             (sig->hasthis || 
1697              (sig->param_count > 0 && 
1698               MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1699                 if (sig->hasthis) {
1700                         cinfo->args[nParm].size = sizeof (gpointer);
1701                         add_general (&gr, sz, cinfo->args + nParm);
1702                 } else {
1703                         cinfo->args[nParm].size = sizeof (gpointer);
1704                         add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1705                         pstart = 1;
1706                 }
1707                 nParm ++;
1708                 cinfo->vret_arg_index = 1;
1709                 cinfo->ret.reg = gr;
1710                 gr ++;
1711         } else {
1712                 /* this */
1713                 if (sig->hasthis) {
1714                         cinfo->args[nParm].size = sizeof (gpointer);
1715                         add_general (&gr, sz, cinfo->args + nParm);
1716                         nParm ++;
1717                 }
1718
1719                 if (cinfo->struct_ret) {
1720                         cinfo->ret.reg = gr;
1721                         gr ++;
1722                 }
1723         }
1724
1725         if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1726                 gr = S390_LAST_ARG_REG + 1;
1727                 fr = S390_LAST_FPARG_REG + 1;
1728
1729                 /* Emit the signature cookie just before the implicit arguments */
1730                 add_general (&gr, sz, &cinfo->sigCookie);
1731         }
1732
1733         /*----------------------------------------------------------*/
1734         /* We determine the size of the parameter code and stack    */
1735         /* requirements by checking the types and sizes of the      */
1736         /* parameters.                                              */
1737         /*----------------------------------------------------------*/
1738
1739         for (i = pstart; i < sig->param_count; ++i) {
1740                 MonoType *ptype;
1741
1742                 /*--------------------------------------------------*/
1743                 /* Handle vararg type calls. All args are put on    */
1744                 /* the stack.                                       */
1745                 /*--------------------------------------------------*/
1746                 if ((sig->call_convention == MONO_CALL_VARARG) &&
1747                     (i == sig->sentinelpos)) {
1748                         gr = S390_LAST_ARG_REG + 1;
1749                         fr = S390_LAST_FPARG_REG + 1;
1750                         add_general (&gr, sz, &cinfo->sigCookie);
1751                 }
1752
1753                 if (sig->params [i]->byref) {
1754                         add_general (&gr, sz, cinfo->args+nParm);
1755                         cinfo->args[nParm].size = sizeof(gpointer);
1756                         nParm++;
1757                         continue;
1758                 }
1759
1760                 ptype = mini_get_underlying_type (sig->params [i]);
1761                 simpleType = ptype->type;
1762                 cinfo->args[nParm].type = simpleType;
1763                 switch (simpleType) {
1764                 case MONO_TYPE_I1:
1765                 case MONO_TYPE_U1:
1766                         cinfo->args[nParm].size = sizeof(char);
1767                         add_general (&gr, sz, cinfo->args+nParm);
1768                         nParm++;
1769                         break;
1770                 case MONO_TYPE_I2:
1771                 case MONO_TYPE_U2:
1772                         cinfo->args[nParm].size = sizeof(short);
1773                         add_general (&gr, sz, cinfo->args+nParm);
1774                         nParm++;
1775                         break;
1776                 case MONO_TYPE_I4:
1777                 case MONO_TYPE_U4:
1778                         cinfo->args[nParm].size = sizeof(int);
1779                         add_general (&gr, sz, cinfo->args+nParm);
1780                         nParm++;
1781                         break;
1782                 case MONO_TYPE_I:
1783                 case MONO_TYPE_U:
1784                 case MONO_TYPE_PTR:
1785                 case MONO_TYPE_FNPTR:
1786                 case MONO_TYPE_OBJECT:
1787                         cinfo->args[nParm].size = sizeof(gpointer);
1788                         add_general (&gr, sz, cinfo->args+nParm);
1789                         nParm++;
1790                         break;
1791                 case MONO_TYPE_I8:
1792                 case MONO_TYPE_U8:
1793                         cinfo->args[nParm].size = sizeof(long long);
1794                         add_general (&gr, sz, cinfo->args+nParm);
1795                         nParm++;
1796                         break;
1797                 case MONO_TYPE_R4:
1798                         cinfo->args[nParm].size = sizeof(float);
1799                         add_float (&fr, sz, cinfo->args+nParm);
1800                         nParm++;
1801                         break;
1802                 case MONO_TYPE_R8:
1803                         cinfo->args[nParm].size = sizeof(double);
1804                         add_float (&fr, sz, cinfo->args+nParm);
1805                         nParm++;
1806                         break;
1807                 case MONO_TYPE_GENERICINST:
1808                         if (!mono_type_generic_inst_is_valuetype (ptype)) {
1809                                 cinfo->args[nParm].size = sizeof(gpointer);
1810                                 add_general (&gr, sz, cinfo->args+nParm);
1811                                 nParm++;
1812                                 break;
1813                         }
1814                         /* Fall through */
1815                 case MONO_TYPE_VALUETYPE: {
1816                         MonoMarshalType *info;
1817                         MonoClass *klass = mono_class_from_mono_type (ptype);
1818
1819                         if (sig->pinvoke)
1820                                 size = mono_class_native_size(klass, NULL);
1821                         else
1822                                 size = mono_class_value_size(klass, NULL);
1823
1824                         if (simpleType != MONO_TYPE_GENERICINST) {
1825                                 info = mono_marshal_load_type_info(klass);
1826
1827                                 if ((info->native_size == sizeof(float)) &&
1828                                     (info->num_fields  == 1) &&
1829                                     (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1830                                         cinfo->args[nParm].size = sizeof(float);
1831                                         add_float(&fr, sz, cinfo->args+nParm);
1832                                         nParm ++;
1833                                         break;
1834                                 }
1835
1836                                 if ((info->native_size == sizeof(double)) &&
1837                                     (info->num_fields  == 1) &&
1838                                     (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1839                                         cinfo->args[nParm].size = sizeof(double);
1840                                         add_float(&fr, sz, cinfo->args+nParm);
1841                                         nParm ++;
1842                                         break;
1843                                 }
1844                         }
1845
1846                         cinfo->args[nParm].vtsize  = 0;
1847                         cinfo->args[nParm].size    = 0;
1848
1849                         switch (size) {
1850                                 /*----------------------------------*/
1851                                 /* On S/390, structures of size 1,  */
1852                                 /* 2, 4, and 8 bytes are passed in  */
1853                                 /* (a) register(s).                 */
1854                                 /*----------------------------------*/
1855                                 case 0:
1856                                 case 1:
1857                                 case 2:
1858                                 case 4:
1859                                 case 8:
1860                                         add_general(&gr, sz, cinfo->args+nParm);
1861                                         cinfo->args[nParm].size    = size;
1862                                         cinfo->args[nParm].regtype = RegTypeStructByVal; 
1863                                         nParm++;
1864                                         sz->local_size            += sizeof(long);
1865                                         break;
1866                                 default:
1867                                         add_stackParm(&gr, sz, cinfo->args+nParm, size);
1868                                         nParm++;
1869                         }
1870                 }
1871                         break;
1872                 case MONO_TYPE_TYPEDBYREF: {
1873                         int size = sizeof (MonoTypedRef);
1874
1875                         cinfo->args[nParm].vtsize  = 0;
1876                         cinfo->args[nParm].size    = 0;
1877
1878                         switch (size) {
1879                                 /*----------------------------------*/
1880                                 /* On S/390, structures of size 1,  */
1881                                 /* 2, 4, and 8 bytes are passed in  */
1882                                 /* (a) register(s).                 */
1883                                 /*----------------------------------*/
1884                                 case 0:
1885                                 case 1:
1886                                 case 2:
1887                                 case 4:
1888                                 case 8:
1889                                         add_general(&gr, sz, cinfo->args+nParm);
1890                                         cinfo->args[nParm].size    = size;
1891                                         cinfo->args[nParm].regtype = RegTypeStructByVal; 
1892                                         nParm++;
1893                                         sz->local_size            += sizeof(long);
1894                                         break;
1895                                 default:
1896                                         add_stackParm(&gr, sz, cinfo->args+nParm, size);
1897                                         nParm++;
1898                         }
1899                 }
1900                         break;
1901                 default:
1902                         g_error ("Can't trampoline 0x%x", ptype);
1903                 }
1904         }
1905
1906         /*----------------------------------------------------------*/
1907         /* Handle the case where there are no implicit arguments    */
1908         /*----------------------------------------------------------*/
1909         if ((sig->call_convention == MONO_CALL_VARARG) &&
1910             (nParm > 0) &&
1911             (!sig->pinvoke) &&
1912             (sig->param_count == sig->sentinelpos)) {
1913                 gr = S390_LAST_ARG_REG + 1;
1914                 fr = S390_LAST_FPARG_REG + 1;
1915                 add_general (&gr, sz, &cinfo->sigCookie);
1916         }
1917
1918         /*----------------------------------------------------------*/
1919         /* If we are passing a structure back then if it won't be   */
1920         /* in a register(s) then we make room at the end of the     */
1921         /* parameters that may have been placed on the stack        */
1922         /*----------------------------------------------------------*/
1923         if (cinfo->struct_ret) {
1924                 cinfo->ret.offset = sz->stack_size;
1925                 switch (cinfo->ret.size) {
1926                 case 0:
1927                 case 1:
1928                 case 2:
1929                 case 4:
1930                 case 8:
1931                         break;
1932                 default:
1933                         sz->stack_size   += S390_ALIGN(cinfo->ret.size, align);
1934                 }
1935         }
1936
1937         cinfo->lastgr   = gr;
1938         sz->stack_size  = sz->stack_size + sz->local_size + sz->parm_size + 
1939                           sz->offset;
1940         sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1941
1942         return (cinfo);
1943 }
1944
1945 /*========================= End of Function ========================*/
1946
1947 /*------------------------------------------------------------------*/
1948 /*                                                                  */
1949 /* Name         - mono_arch_allocate_vars                           */
1950 /*                                                                  */
1951 /* Function     - Set var information according to the calling      */
1952 /*                convention for S/390. The local var stuff should  */
1953 /*                most likely be split in another method.           */
1954 /*                                                                  */
1955 /* Parameter    - @m - Compile unit.                                */
1956 /*                                                                  */
1957 /*------------------------------------------------------------------*/
1958
1959 void
1960 mono_arch_allocate_vars (MonoCompile *cfg)
1961 {
1962         MonoMethodSignature *sig;
1963         MonoMethodHeader *header;
1964         MonoInst *inst;
1965         CallInfo *cinfo;
1966         int iParm, iVar, offset, align, size, curinst;
1967         int frame_reg = STK_BASE;
1968         int sArg, eArg;
1969
1970         header  = cfg->header;
1971
1972         cfg->flags |= MONO_CFG_HAS_SPILLUP;
1973
1974         /*---------------------------------------------------------*/    
1975         /* We use the frame register also for any method that has  */ 
1976         /* filter clauses. This way, when the handlers are called, */
1977         /* the code will reference local variables using the frame */
1978         /* reg instead of the stack pointer: if we had to restore  */
1979         /* the stack pointer, we'd corrupt the method frames that  */
1980         /* are already on the stack (since filters get called      */
1981         /* before stack unwinding happens) when the filter code    */
1982         /* would call any method.                                  */
1983         /*---------------------------------------------------------*/    
1984         if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1985                 frame_reg = s390_r11;
1986
1987         cfg->frame_reg = frame_reg;
1988
1989         cfg->arch.bkchain_reg = -1;
1990
1991         if (frame_reg != STK_BASE) 
1992                 cfg->used_int_regs |= (1 << frame_reg);         
1993
1994         if (cfg->uses_rgctx_reg)
1995                 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1996
1997         sig     = mono_method_signature (cfg->method);
1998         
1999         cinfo   = get_call_info (cfg, cfg->mempool, sig);
2000
2001         if (!cinfo->struct_ret) {
2002                 switch (mini_get_underlying_type (sig->ret)->type) {
2003                 case MONO_TYPE_VOID:
2004                         break;
2005                 default:
2006                         cfg->ret->opcode = OP_REGVAR;
2007                         cfg->ret->dreg   = s390_r2;
2008                         break;
2009                 }
2010         }
2011
2012         /*--------------------------------------------------------------*/
2013         /* local vars are at a positive offset from the stack pointer   */
2014         /* also note that if the function uses alloca, we use s390_r11  */
2015         /* to point at the local variables.                             */
2016         /* add parameter area size for called functions                 */
2017         /*--------------------------------------------------------------*/
2018         if (cfg->param_area == 0)
2019                 offset = S390_MINIMAL_STACK_SIZE;
2020         else
2021                 offset = cfg->param_area;
2022
2023         cfg->sig_cookie = 0;
2024
2025         if (cinfo->struct_ret) {
2026                 inst               = cfg->vret_addr;
2027                 offset             = S390_ALIGN(offset, sizeof(gpointer));
2028                 inst->inst_offset  = offset;
2029                 inst->opcode       = OP_REGOFFSET;
2030                 inst->inst_basereg = frame_reg;
2031                 offset            += sizeof(gpointer);
2032                 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2033                         printf ("vret_addr =");
2034                         mono_print_ins (cfg->vret_addr);
2035                 }
2036         }
2037
2038         if (sig->hasthis) {
2039                 inst = cfg->args [0];
2040                 if (inst->opcode != OP_REGVAR) {
2041                         inst->opcode       = OP_REGOFFSET;
2042                         inst->inst_basereg = frame_reg;
2043                         offset             = S390_ALIGN(offset, sizeof(gpointer));
2044                         inst->inst_offset  = offset;
2045                         offset            += sizeof (gpointer);
2046                 }
2047                 curinst = sArg = 1;
2048         } else {
2049                 curinst = sArg = 0;
2050         }
2051
2052         eArg = sig->param_count + sArg;
2053
2054         if (sig->call_convention == MONO_CALL_VARARG)
2055                 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2056
2057         for (iParm = sArg; iParm < eArg; ++iParm) {
2058                 inst = cfg->args [curinst];
2059                 if (inst->opcode != OP_REGVAR) {
2060                         switch (cinfo->args[iParm].regtype) {
2061                         case RegTypeStructByAddr : {
2062                                 MonoInst *indir;
2063
2064                                 size = sizeof (gpointer);
2065
2066                                 inst->opcode       = OP_REGOFFSET;
2067                                 inst->inst_basereg = frame_reg;
2068                                 offset             = S390_ALIGN (offset, sizeof (gpointer));
2069                                 inst->inst_offset  = offset;
2070
2071                                 /* Add a level of indirection */
2072                                 MONO_INST_NEW (cfg, indir, 0);
2073                                 *indir          = *inst;
2074                                 inst->opcode    = OP_VTARG_ADDR;
2075                                 inst->inst_left = indir;
2076                         }
2077                                 break;
2078                         case RegTypeStructByAddrOnStack : {
2079                                 MonoInst *indir;
2080
2081                                 size = sizeof (gpointer);
2082
2083                                 /* Similar to the == STK_BASE case below */
2084                                 cfg->arch.bkchain_reg = s390_r12;
2085                                 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2086
2087                                 inst->opcode = OP_REGOFFSET;
2088                                 inst->dreg = mono_alloc_preg (cfg);
2089                                 inst->inst_basereg = cfg->arch.bkchain_reg;
2090                                 inst->inst_offset = cinfo->args [iParm].offset;
2091
2092                                 /* Add a level of indirection */
2093                                 MONO_INST_NEW (cfg, indir, 0);
2094                                 *indir = *inst;
2095                                 inst->opcode = OP_VTARG_ADDR;
2096                                 inst->inst_left = indir;
2097                                 break;
2098                         }
2099                         case RegTypeStructByVal :
2100                                 size               = cinfo->args[iParm].size;
2101                                 offset             = S390_ALIGN(offset, size);
2102                                 inst->opcode       = OP_REGOFFSET;
2103                                 inst->inst_basereg = frame_reg;
2104                                 inst->inst_offset  = offset;
2105                                 break;
2106                         default :
2107                                 if (cinfo->args [iParm].reg == STK_BASE) {
2108                                         /*
2109                                          * These arguments are in the previous frame, so we can't 
2110                                          * compute their offset from the current frame pointer right
2111                                          * now, since cfg->stack_offset is not yet known, so dedicate a 
2112                                          * register holding the previous frame pointer.
2113                                          */
2114                                         cfg->arch.bkchain_reg = s390_r12;
2115                                         cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2116
2117                                         inst->opcode       = OP_REGOFFSET;
2118                                         inst->inst_basereg = cfg->arch.bkchain_reg;
2119                                         size               = (cinfo->args[iParm].size < 8
2120                                                                           ? 8 - cinfo->args[iParm].size
2121                                                                           : 0);
2122                                         inst->inst_offset  = cinfo->args [iParm].offset + size;
2123                                         size = sizeof (long);
2124                                 } else {
2125                                         inst->opcode       = OP_REGOFFSET;
2126                                         inst->inst_basereg = frame_reg;
2127                                         size               = (cinfo->args[iParm].size < 8
2128                                                                           ? sizeof(int)  
2129                                                                           : sizeof(long));
2130                                         offset             = S390_ALIGN(offset, size);
2131                                         if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) 
2132                                                 inst->inst_offset  = offset;
2133                                         else
2134                                                 inst->inst_offset  = offset + (8 - size);
2135                                 }
2136                                 break;
2137                         }
2138 #if 0
2139                         if ((sig->call_convention == MONO_CALL_VARARG) && 
2140                             (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2141                             (iParm < sig->sentinelpos)) 
2142                                 cfg->sig_cookie += size;
2143 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2144 #endif
2145
2146                         offset += MAX(size, 8);
2147                 }
2148                 curinst++;
2149         }
2150
2151         cfg->locals_min_stack_offset = offset;
2152
2153         curinst = cfg->locals_start;
2154         for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2155                 inst = cfg->varinfo [iVar];
2156                 if ((inst->flags & MONO_INST_IS_DEAD) || 
2157                     (inst->opcode == OP_REGVAR))
2158                         continue;
2159
2160                 /*--------------------------------------------------*/
2161                 /* inst->backend.is_pinvoke indicates native sized  */
2162                 /* value typs this is used by the pinvoke wrappers  */
2163                 /* when they call functions returning structure     */
2164                 /*--------------------------------------------------*/
2165                 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2166                         size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype), 
2167                                                        (guint32 *) &align);
2168                 else
2169                         size = mono_type_size (inst->inst_vtype, &align);
2170
2171                 offset             = S390_ALIGN(offset, align);
2172                 inst->inst_offset  = offset;
2173                 inst->opcode       = OP_REGOFFSET;
2174                 inst->inst_basereg = frame_reg;
2175                 offset            += size;
2176                 DEBUG (g_print("allocating local %d to %ld, size: %d\n", 
2177                                 iVar, inst->inst_offset, size));
2178         }
2179
2180         cfg->locals_max_stack_offset = offset;
2181
2182         /*------------------------------------------------------*/
2183         /* Allow space for the trace method stack area if needed*/
2184         /*------------------------------------------------------*/
2185         if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2186                 offset += S390_TRACE_STACK_SIZE;
2187
2188         /*------------------------------------------------------*/
2189         /* Reserve space to save LMF and caller saved registers */
2190         /*------------------------------------------------------*/
2191         if (cfg->method->save_lmf)
2192                 offset += sizeof (MonoLMF);
2193
2194         /*------------------------------------------------------*/
2195         /* align the offset                                     */
2196         /*------------------------------------------------------*/
2197         cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2198
2199         /*------------------------------------------------------*/
2200         /* Fix offsets for args whose value is in parent frame  */
2201         /*------------------------------------------------------*/
2202         for (iParm = sArg; iParm < eArg; ++iParm) {
2203                 inst = cfg->args [iParm];
2204
2205                 if (inst->opcode == OP_S390_STKARG) {
2206                         inst->opcode = OP_REGOFFSET;
2207                         inst->inst_offset += cfg->stack_offset;
2208                 }
2209         }
2210 }
2211
2212 /*========================= End of Function ========================*/
2213
2214 /*------------------------------------------------------------------*/
2215 /*                                                                  */
2216 /* Name         - mono_arch_create_vars                             */
2217 /*                                                                  */
2218 /*------------------------------------------------------------------*/
2219
2220 void
2221 mono_arch_create_vars (MonoCompile *cfg)
2222 {
2223         MonoMethodSignature *sig;
2224         CallInfo *cinfo;
2225
2226         sig = mono_method_signature (cfg->method);
2227
2228         cinfo = get_call_info (cfg, cfg->mempool, sig);
2229
2230         if (cinfo->struct_ret) {
2231                 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2232                 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2233                         printf ("vret_addr = ");
2234                         mono_print_ins (cfg->vret_addr);
2235                 }
2236         }
2237 }
2238
2239 /*========================= End of Function ========================*/
2240
2241 /*------------------------------------------------------------------*/
2242 /*                                                                  */
2243 /* Name         - add_outarg_reg2.                                  */
2244 /*                                                                  */
2245 /*------------------------------------------------------------------*/
2246
2247 static void
2248 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2249 {
2250         MonoInst *ins;
2251
2252         switch (storage) {
2253         case RegTypeGeneral:
2254                 MONO_INST_NEW (cfg, ins, OP_MOVE);
2255                 ins->dreg = mono_alloc_ireg (cfg);
2256                 ins->sreg1 = tree->dreg;
2257                 MONO_ADD_INS (cfg->cbb, ins);
2258                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2259                 break;
2260         case RegTypeFP:
2261                 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2262                 ins->dreg = mono_alloc_freg (cfg);
2263                 ins->sreg1 = tree->dreg;
2264                 MONO_ADD_INS (cfg->cbb, ins);
2265                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2266                 break;
2267         case RegTypeFPR4:
2268                 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2269                 ins->dreg = mono_alloc_freg (cfg);
2270                 ins->sreg1 = tree->dreg;
2271                 MONO_ADD_INS (cfg->cbb, ins);
2272                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2273                 break;
2274         default:
2275                 g_assert_not_reached ();
2276         }
2277 }
2278
2279 /*========================= End of Function ========================*/
2280
2281 /*------------------------------------------------------------------*/
2282 /*                                                                  */
2283 /* Name         - emit_sig_cookie.                                  */
2284 /*                                                                  */
2285 /*------------------------------------------------------------------*/
2286
2287 static void
2288 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2289 {
2290         MonoMethodSignature *tmpSig;
2291         MonoInst *sig_arg;
2292                         
2293         cfg->disable_aot = TRUE;
2294
2295         /*----------------------------------------------------------*/
2296         /* mono_ArgIterator_Setup assumes the signature cookie is   */
2297         /* passed first and all the arguments which were before it  */
2298         /* passed on the stack after the signature. So compensate   */
2299         /* by passing a different signature.                        */
2300         /*----------------------------------------------------------*/
2301         tmpSig = mono_metadata_signature_dup (call->signature);
2302         tmpSig->param_count -= call->signature->sentinelpos;
2303         tmpSig->sentinelpos  = 0;
2304         if (tmpSig->param_count > 0)
2305                 memcpy (tmpSig->params, 
2306                         call->signature->params + call->signature->sentinelpos, 
2307                         tmpSig->param_count * sizeof(MonoType *));
2308
2309         MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2310         sig_arg->dreg = mono_alloc_ireg (cfg);
2311         sig_arg->inst_p0 = tmpSig;
2312         MONO_ADD_INS (cfg->cbb, sig_arg);
2313
2314         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE, 
2315                                      cinfo->sigCookie.offset, sig_arg->dreg);
2316 }
2317
2318 /*========================= End of Function ========================*/
2319
2320 /*------------------------------------------------------------------*/
2321 /*                                                                  */
2322 /* Name         - mono_arch_emit_call                               */
2323 /*                                                                  */
2324 /*------------------------------------------------------------------*/
2325
2326 void
2327 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2328 {
2329         MonoInst *in;
2330         MonoMethodSignature *sig;
2331         MonoInst *ins;
2332         int i, n, lParamArea;
2333         CallInfo *cinfo;
2334         ArgInfo *ainfo = NULL;
2335         int stackSize;    
2336         MonoMethodHeader *header;
2337         int frmReg;
2338
2339         sig = call->signature;
2340         n = sig->param_count + sig->hasthis;
2341         DEBUG (g_print ("Call requires: %d parameters\n",n));
2342         
2343         cinfo = get_call_info (cfg, cfg->mempool, sig);
2344
2345         stackSize         = cinfo->sz.stack_size + cinfo->sz.local_size + 
2346                             cinfo->sz.parm_size + cinfo->sz.offset;
2347         call->stack_usage = MAX(stackSize, call->stack_usage);
2348         lParamArea        = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2349         cfg->param_area   = MAX(((signed) cfg->param_area), lParamArea);
2350         cfg->flags       |= MONO_CFG_HAS_CALLS;
2351
2352         if (cinfo->struct_ret) {
2353                 MONO_INST_NEW (cfg, ins, OP_MOVE);
2354                 ins->sreg1 = call->vret_var->dreg;
2355                 ins->dreg = mono_alloc_preg (cfg);
2356                 MONO_ADD_INS (cfg->cbb, ins);
2357                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2358         }
2359
2360         header = cfg->header;
2361         if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2362                 frmReg = s390_r11;
2363         else
2364                 frmReg = STK_BASE;
2365
2366         for (i = 0; i < n; ++i) {
2367                 MonoType *t;
2368
2369                 ainfo = cinfo->args + i;
2370                 if (i >= sig->hasthis)
2371                         t = sig->params [i - sig->hasthis];
2372                 else
2373                         t = &mono_defaults.int_class->byval_arg;
2374                 t = mini_get_underlying_type (t);
2375
2376                 in = call->args [i];
2377
2378                 if ((sig->call_convention == MONO_CALL_VARARG) &&
2379                     (!sig->pinvoke) &&
2380                     (i == sig->sentinelpos)) {
2381                         emit_sig_cookie (cfg, call, cinfo);
2382                 }
2383
2384                 switch (ainfo->regtype) {
2385                 case RegTypeGeneral:
2386                         add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2387                         break;
2388                 case RegTypeFP:
2389                         if (MONO_TYPE_ISSTRUCT (t)) {
2390                                 /* Valuetype passed in one fp register */
2391                                 ainfo->regtype = RegTypeStructByValInFP;
2392                                 /* Fall through */
2393                         } else {
2394                                 if (ainfo->size == 4)
2395                                         ainfo->regtype = RegTypeFPR4;
2396                                 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2397                                 break;
2398                         }
2399                 case RegTypeStructByVal:
2400                 case RegTypeStructByAddr:
2401                 case RegTypeStructByAddrOnStack: {
2402                         guint32 align;
2403                         guint32 size;
2404
2405                         if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2406                                 size = sizeof (MonoTypedRef);
2407                                 align = sizeof (gpointer);
2408                         }
2409                         else
2410                                 if (sig->pinvoke)
2411                                         size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2412                                 else {
2413                                         /* 
2414                                          * Other backends use mono_type_stack_size (), but that
2415                                          * aligns the size to 8, which is larger than the size of
2416                                          * the source, leading to reads of invalid memory if the
2417                                          * source is at the end of address space.
2418                                          */
2419                                         size = mono_class_value_size (in->klass, &align);
2420                                 }
2421
2422                         g_assert (in->klass);
2423
2424                         ainfo->offparm += cinfo->sz.offStruct;
2425
2426                         MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2427                         ins->sreg1 = in->dreg;
2428                         ins->klass = in->klass;
2429                         ins->backend.size = ainfo->size;
2430                         ins->inst_p0 = call;
2431                         ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2432                         memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2433
2434                         MONO_ADD_INS (cfg->cbb, ins);
2435
2436                         if (ainfo->regtype == RegTypeStructByAddr) {
2437                                 /* 
2438                                  * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2439                                  * use the normal OUTARG opcodes to pass the address of the location to
2440                                  * the callee.
2441                                  */
2442                                 int treg = mono_alloc_preg (cfg);
2443                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg, 
2444                                                          frmReg, ainfo->offparm);
2445                                 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2446                         } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2447                                 /* The address of the valuetype is passed on the stack */
2448                                 int treg = mono_alloc_preg (cfg);
2449                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg, 
2450                                                          frmReg, ainfo->offparm);
2451                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2452                                                              ainfo->reg, ainfo->offset, treg);
2453
2454                                 if (cfg->compute_gc_maps) {
2455                                         MonoInst *def;
2456
2457                                         EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2458                                 }
2459                         }
2460                         break;
2461                 }
2462                 case RegTypeBase:
2463                         if (!t->byref && t->type == MONO_TYPE_R4) {
2464                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, 
2465                                                              STK_BASE, ainfo->offset + 4,
2466                                                              in->dreg);
2467                         } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2468                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, 
2469                                                              STK_BASE, ainfo->offset,
2470                                                              in->dreg);
2471                         } else {
2472                                 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2473                                 ins->inst_destbasereg = STK_BASE;
2474                                 ins->inst_offset = ainfo->offset;
2475                                 ins->sreg1 = in->dreg;
2476
2477 #if 0
2478                                 /* This is needed by MonoTypedRef->value to point to the correct data */
2479                                 if ((sig->call_convention == MONO_CALL_VARARG) &&
2480                                         (i >= sig->sentinelpos)) {
2481                                         switch (ainfo->size) {
2482                                         case 1:
2483                                                 ins->opcode = OP_STOREI1_MEMBASE_REG;
2484                                                 break;
2485                                         case 2:
2486                                                 ins->opcode = OP_STOREI2_MEMBASE_REG;
2487                                                 break;
2488                                         case 4:
2489                                                 ins->opcode = OP_STOREI4_MEMBASE_REG;
2490                                                 break;
2491                                         default:
2492                                                 break;
2493                                         }
2494                                 }
2495 #endif
2496
2497                                 MONO_ADD_INS (cfg->cbb, ins);
2498                         }
2499                         break;
2500                 default:
2501                         g_assert_not_reached ();
2502                         break;
2503                 }
2504         }
2505
2506         /*
2507          * Handle the case where there are no implicit arguments 
2508          */
2509         if ((sig->call_convention == MONO_CALL_VARARG) &&
2510             (!sig->pinvoke) &&
2511             (i == sig->sentinelpos)) {
2512                 emit_sig_cookie (cfg, call, cinfo);
2513         }
2514 }
2515
2516 /*========================= End of Function ========================*/
2517
2518 /*------------------------------------------------------------------*/
2519 /*                                                                  */
2520 /* Name         - mono_arch_emit_outarg_vt                          */
2521 /*                                                                  */
2522 /*------------------------------------------------------------------*/
2523
2524 void
2525 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2526 {
2527         MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2528         ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2529         int size = ins->backend.size;
2530
2531         if (ainfo->regtype == RegTypeStructByVal) {
2532                 /*
2533                                 arg->ins.sreg1  = ainfo->reg;
2534                                 arg->ins.opcode = OP_OUTARG_VT;
2535                                 arg->size       = ainfo->size;
2536                                 arg->offset     = ainfo->offset;
2537                                 arg->offPrm     = ainfo->offparm + cinfo->sz.offStruct;
2538                 */
2539                 if (ainfo->reg != STK_BASE) {
2540                         MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2541                 } else {
2542                         MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2543                                                           src->dreg, 0);
2544                 }       
2545         } else if (ainfo->regtype == RegTypeStructByValInFP) {
2546                 int dreg = mono_alloc_freg (cfg);
2547
2548                 if (ainfo->size == 4) {
2549                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2550                         MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2551                 } else {
2552                         g_assert (ainfo->size == 8);
2553
2554                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2555                 }
2556
2557                 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2558         } else {
2559                 MonoError error;
2560                 MonoMethodHeader *header;
2561                 int srcReg;
2562
2563                 header = mono_method_get_header_checked (cfg->method, &error);
2564                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2565                 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2566                         srcReg = s390_r11;
2567                 else
2568                         srcReg = STK_BASE;
2569
2570                 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2571                                                          src->dreg, 0, size);
2572
2573                 if (cfg->compute_gc_maps) {
2574                         MonoInst *def;
2575
2576                         EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2577                 }
2578         }
2579 }
2580
2581 /*========================= End of Function ========================*/
2582
2583 /*------------------------------------------------------------------*/
2584 /*                                                                  */
2585 /* Name         - mono_arch_emit_setret                             */
2586 /*                                                                  */
2587 /*------------------------------------------------------------------*/
2588
2589 void
2590 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2591 {
2592         MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2593
2594         if (!ret->byref) {
2595                 if (ret->type == MONO_TYPE_R4) {
2596                         MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2597                         return;
2598                 } else if (ret->type == MONO_TYPE_R8) {
2599                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2600                         return;
2601                 }
2602         }
2603                         
2604         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2605 }
2606
2607 /*========================= End of Function ========================*/
2608
2609 /*------------------------------------------------------------------*/
2610 /*                                                                  */
2611 /* Name         - mono_arch_instrument_mem_needs                    */
2612 /*                                                                  */
2613 /* Function     - Allow tracing to work with this interface (with   */
2614 /*                an optional argument).                            */
2615 /*                                                                  */
2616 /*------------------------------------------------------------------*/
2617
2618 void
2619 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2620 {
2621         /* no stack room needed now (may be needed for FASTCALL-trace support) */
2622         *stack = 0;
2623         /* split prolog-epilog requirements? */
2624         *code = 50; /* max bytes needed: check this number */
2625 }
2626
2627 /*========================= End of Function ========================*/
2628
2629 /*------------------------------------------------------------------*/
2630 /*                                                                  */
2631 /* Name         - mono_arch_instrument_prolog                       */
2632 /*                                                                  */
2633 /* Function     - Create an "instrumented" prolog.                  */
2634 /*                                                                  */
2635 /*------------------------------------------------------------------*/
2636
2637 void*
2638 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, 
2639                              gboolean enable_arguments)
2640 {
2641         guchar  *code = p;
2642         int     parmOffset, 
2643                 fpOffset,
2644                 baseReg;
2645
2646         parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2647         if (cfg->method->save_lmf)
2648                 parmOffset -= sizeof(MonoLMF);
2649         fpOffset   = parmOffset + (5*sizeof(gpointer));
2650         baseReg = STK_BASE;
2651
2652         s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2653         s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2654         s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2655         s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2656         s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2657         S390_SET  (code, s390_r1, func);
2658         S390_SET  (code, s390_r2, cfg->method);
2659         s390_lay  (code, s390_r3, 0, STK_BASE, parmOffset);
2660         s390_lgr  (code, s390_r4, STK_BASE);
2661         s390_aghi (code, s390_r4, cfg->stack_usage);
2662         s390_basr (code, s390_r14, s390_r1);
2663         s390_ldy  (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2664         s390_ldy  (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2665         s390_ldy  (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2666         s390_ldy  (code, s390_f0, 0, STK_BASE, fpOffset);
2667         s390_lmg  (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2668
2669         return code;
2670 }
2671
2672 /*========================= End of Function ========================*/
2673
2674 /*------------------------------------------------------------------*/
2675 /*                                                                  */
2676 /* Name         - mono_arch_instrument_epilog                       */
2677 /*                                                                  */
2678 /* Function     - Create an epilog that will handle the returned    */
2679 /*                values used in instrumentation.                   */
2680 /*                                                                  */
2681 /*------------------------------------------------------------------*/
2682
2683 void*
2684 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2685 {
2686         guchar     *code = p;
2687         int        save_mode = SAVE_NONE,
2688                    saveOffset,
2689                    offset;
2690         MonoMethod *method = cfg->method;
2691         int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2692
2693         offset = code - cfg->native_code;
2694         /*-----------------------------------------*/
2695         /* We need about 128 bytes of instructions */
2696         /*-----------------------------------------*/
2697         if (offset > (cfg->code_size - 128)) {
2698                 cfg->code_size *= 2;
2699                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2700                 code = cfg->native_code + offset;
2701         }
2702
2703         saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2704         if (method->save_lmf)
2705                 saveOffset -= sizeof(MonoLMF);
2706
2707 handle_enum:
2708         switch (rtype) {
2709         case MONO_TYPE_VOID:
2710                 /* special case string .ctor icall */
2711                 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2712                         save_mode = SAVE_ONE;
2713                 else
2714                         save_mode = SAVE_NONE;
2715                 break;
2716         case MONO_TYPE_I8:
2717         case MONO_TYPE_U8:
2718                 save_mode = SAVE_ONE;
2719                 break;
2720         case MONO_TYPE_R4:
2721                 save_mode = SAVE_R4;
2722                 break;
2723         case MONO_TYPE_R8:
2724                 save_mode = SAVE_R8;
2725                 break;
2726         case MONO_TYPE_VALUETYPE:
2727                 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2728                         rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2729                         goto handle_enum;
2730                 }
2731                 save_mode = SAVE_STRUCT;
2732                 break;
2733         default:
2734                 save_mode = SAVE_ONE;
2735                 break;
2736         }
2737
2738         switch (save_mode) {
2739         case SAVE_ONE:
2740                 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2741                 if (enable_arguments) {
2742                         s390_lgr (code, s390_r3, s390_r2);
2743                 }
2744                 break;
2745         case SAVE_R4:
2746                 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2747                 if (enable_arguments) {
2748                         s390_ldebr (code, s390_f0, s390_f0);
2749                 }
2750                 break;
2751         case SAVE_R8:
2752                 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2753                 break;
2754         case SAVE_STRUCT:
2755                 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2756                 if (enable_arguments) {
2757                         s390_lg (code, s390_r3, 0, cfg->frame_reg, 
2758                                  S390_MINIMAL_STACK_SIZE+cfg->param_area);
2759                 }
2760                 break;
2761         case SAVE_NONE:
2762         default:
2763                 break;
2764         }
2765
2766         S390_SET  (code, s390_r1, func);
2767         S390_SET  (code, s390_r2, cfg->method);
2768         s390_basr (code, s390_r14, s390_r1);
2769
2770         switch (save_mode) {
2771         case SAVE_ONE:
2772                 s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2773                 break;
2774         case SAVE_R4:
2775         case SAVE_R8:
2776                 s390_ld  (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2777                 break;
2778         case SAVE_STRUCT:
2779                 s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2780                 break;
2781         case SAVE_NONE:
2782         default:
2783                 break;
2784         }
2785
2786         return code;
2787 }
2788
2789 /*========================= End of Function ========================*/
2790
2791 /*------------------------------------------------------------------*/
2792 /*                                                                  */
2793 /* Name         - mono_arch_peephole_pass_1                         */
2794 /*                                                                  */
2795 /* Function     - Form a peephole pass at the code looking for      */
2796 /*                simple optimizations.                             */
2797 /*                                                                  */
2798 /*------------------------------------------------------------------*/
2799
2800 void
2801 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2802 {
2803 }
2804
2805 /*========================= End of Function ========================*/
2806
2807 /*------------------------------------------------------------------*/
2808 /*                                                                  */
2809 /* Name         - mono_arch_peephole_pass_2                         */
2810 /*                                                                  */
2811 /* Function     - Form a peephole pass at the code looking for      */
2812 /*                simple optimizations.                             */
2813 /*                                                                  */
2814 /*------------------------------------------------------------------*/
2815
2816 void
2817 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2818 {
2819         MonoInst *ins, *n;
2820
2821         MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2822                 mono_peephole_ins (bb, ins);
2823         }
2824 }
2825
2826 /*========================= End of Function ========================*/
2827
2828 /*------------------------------------------------------------------*/
2829 /*                                                                  */
2830 /* Name         - mono_arch_lowering_pass.                          */
2831 /*                                                                  */
2832 /*------------------------------------------------------------------*/
2833
2834 void
2835 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2836 {
2837         MonoInst *ins, *next;
2838
2839         MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2840                 switch (ins->opcode) {
2841                 case OP_DIV_IMM:
2842                 case OP_REM_IMM:
2843                 case OP_IDIV_IMM:
2844                 case OP_IREM_IMM:
2845                 case OP_IDIV_UN_IMM:
2846                 case OP_IREM_UN_IMM:
2847                 case OP_LAND_IMM:
2848                 case OP_LOR_IMM:
2849                 case OP_LREM_IMM:
2850                 case OP_LXOR_IMM:
2851                 case OP_LOCALLOC_IMM:
2852                         mono_decompose_op_imm (cfg, bb, ins);
2853                         break;
2854                 case OP_LADD_IMM:
2855                         if (!s390_is_imm16 (ins->inst_imm))
2856                                 /* This is created by the memcpy code which ignores is_inst_imm */
2857                                 mono_decompose_op_imm (cfg, bb, ins);
2858                         break;
2859                 default:
2860                         break;
2861                 }
2862         }
2863
2864         bb->max_vreg = cfg->next_vreg;
2865 }
2866
2867 /*========================= End of Function ========================*/
2868
2869 /*------------------------------------------------------------------*/
2870 /*                                                                  */
2871 /* Name         - emit_float_to_int                                 */
2872 /*                                                                  */
2873 /* Function     - Create instructions which will convert a floating */
2874 /*                point value to integer.                           */
2875 /*                                                                  */
2876 /*------------------------------------------------------------------*/
2877
2878 static guchar*
2879 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2880 {
2881         /* sreg is a float, dreg is an integer reg. */
2882         if (is_signed) {
2883                 s390_cgdbr (code, dreg, 5, sreg);
2884                 switch (size) {
2885                 case 1:
2886                         s390_ltgr (code, dreg, dreg);
2887                         s390_jnl  (code, 4);
2888                         s390_oill (code, dreg, 0x80);
2889                         s390_lghi (code, s390_r0, 0xff);
2890                         s390_ngr  (code, dreg, s390_r0);
2891                         break;
2892                 case 2:
2893                         s390_ltgr (code, dreg, dreg);
2894                         s390_jnl  (code, 4);
2895                         s390_oill (code, dreg, 0x8000);
2896                         s390_llill(code, s390_r0, 0xffff);
2897                         s390_ngr  (code, dreg, s390_r0);
2898                         break;
2899                 }
2900         } else {
2901                 short *o[1];
2902                 S390_SET    (code, s390_r13, 0x41e0000000000000llu);
2903                 s390_ldgr   (code, s390_f14, s390_r13);
2904                 s390_ldr    (code, s390_f15, sreg);
2905                 s390_cdbr   (code, s390_f15, s390_f14);
2906                 s390_jl     (code, 0); CODEPTR (code, o[0]);
2907                 S390_SET    (code, s390_r13, 0x41f0000000000000llu);
2908                 s390_ldgr   (code, s390_f14, s390_r13);
2909                 s390_sdbr   (code, s390_f15, s390_f14);
2910                 s390_cfdbr  (code, dreg, 7, s390_f15);
2911                 s390_j      (code, 4);
2912                 PTRSLOT (code, o[0]);
2913                 s390_cfdbr  (code, dreg, 5, sreg);
2914                 switch (size) {
2915                 case 1: 
2916                         s390_lghi (code, s390_r0, 0xff);
2917                         s390_ngr  (code, dreg, s390_r0);
2918                         break;
2919                 case 2:
2920                         s390_llill(code, s390_r0, 0xffff);
2921                         s390_ngr  (code, dreg, s390_r0);
2922                         break;
2923                 }
2924         }
2925         return code;
2926 }
2927
2928 /*========================= End of Function ========================*/
2929
2930 /*------------------------------------------------------------------*/
2931 /*                                                                  */
2932 /* Name         - gboolean_is_unsigned.                             */
2933 /*                                                                  */
2934 /* Function     - Return TRUE if next opcode is checking for un-    */
2935 /*                signed value.                                     */
2936 /*                                                                  */
2937 /*------------------------------------------------------------------*/
2938
2939 static 
2940 gboolean is_unsigned (MonoInst *next)
2941 {
2942         if ((next) && 
2943                 (((next->opcode >= OP_IBNE_UN) &&
2944                   (next->opcode <= OP_IBLT_UN)) || 
2945                  ((next->opcode >= OP_LBNE_UN) &&
2946                   (next->opcode <= OP_LBLT_UN)) ||
2947                  ((next->opcode >= OP_COND_EXC_NE_UN) &&
2948                   (next->opcode <= OP_COND_EXC_LT_UN)) ||
2949                  ((next->opcode >= OP_COND_EXC_INE_UN) &&
2950                   (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2951                  ((next->opcode == OP_CLT_UN) ||
2952                   (next->opcode == OP_CGT_UN)) ||
2953                  ((next->opcode == OP_ICLT_UN) ||
2954                   (next->opcode == OP_ICGT_UN) ||
2955                   (next->opcode == OP_LCLT_UN) ||
2956                   (next->opcode == OP_LCGT_UN))))
2957                 return TRUE;
2958         else
2959                 return FALSE;
2960 }
2961
2962 /*========================= End of Function ========================*/
2963
2964 /*------------------------------------------------------------------*/
2965 /*                                                                  */
2966 /* Name         - mono_arch_output_basic_block                      */
2967 /*                                                                  */
2968 /* Function     - Perform the "real" work of emitting instructions  */
2969 /*                that will do the work of in the basic block.      */
2970 /*                                                                  */
2971 /*------------------------------------------------------------------*/
2972
2973 void
2974 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2975 {
2976         MonoInst *ins;
2977         MonoCallInst *call;
2978         guint offset;
2979         guint8 *code = cfg->native_code + cfg->code_len;
2980         guint last_offset = 0;
2981         int max_len, src2;
2982
2983         /* we don't align basic blocks of loops on s390 */
2984
2985         if (cfg->verbose_level > 2)
2986                 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2987
2988         if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2989                 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2990                 g_assert (!mono_compile_aot);
2991                 cov->data [bb->dfn].cil_code = bb->cil_code;
2992                 /* This is not thread save, but good enough */
2993                 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2994                 s390_alsi (code, 0, s390_r1, 1);
2995         }
2996
2997         MONO_BB_FOR_EACH_INS (bb, ins) {
2998                 offset = code - cfg->native_code;
2999
3000                 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3001
3002                 if (offset > (cfg->code_size - max_len - 16)) {
3003                         cfg->code_size *= 2;
3004                         cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3005                         code = cfg->native_code + offset;
3006                 }
3007
3008                 mono_debug_record_line_number (cfg, ins, offset);
3009
3010                 switch (ins->opcode) {
3011                 case OP_STOREI1_MEMBASE_IMM: {
3012                         s390_lghi (code, s390_r0, ins->inst_imm);
3013                         S390_LONG (code, stcy, stc, s390_r0, 0, 
3014                                    ins->inst_destbasereg, ins->inst_offset);
3015                 }
3016                         break;
3017                 case OP_STOREI2_MEMBASE_IMM: {
3018                         s390_lghi (code, s390_r0, ins->inst_imm);
3019                         S390_LONG (code, sthy, sth, s390_r0, 0, 
3020                                    ins->inst_destbasereg, ins->inst_offset);
3021                 }
3022                         break;
3023                 case OP_STOREI4_MEMBASE_IMM: {
3024                         s390_lgfi (code, s390_r0, ins->inst_imm);
3025                         S390_LONG (code, sty, st, s390_r0, 0, 
3026                                    ins->inst_destbasereg, ins->inst_offset);
3027                 }
3028                         break;
3029                 case OP_STORE_MEMBASE_IMM:
3030                 case OP_STOREI8_MEMBASE_IMM: {
3031                         S390_SET (code, s390_r0, ins->inst_imm);
3032                         S390_LONG (code, stg, stg, s390_r0, 0, 
3033                                    ins->inst_destbasereg, ins->inst_offset);
3034                 }
3035                         break;
3036                 case OP_STOREI1_MEMBASE_REG: {
3037                         S390_LONG (code, stcy, stc, ins->sreg1, 0, 
3038                                    ins->inst_destbasereg, ins->inst_offset);
3039                 }
3040                         break;
3041                 case OP_STOREI2_MEMBASE_REG: {
3042                         S390_LONG (code, sthy, sth, ins->sreg1, 0, 
3043                                    ins->inst_destbasereg, ins->inst_offset);
3044                 }
3045                         break;
3046                 case OP_STOREI4_MEMBASE_REG: {
3047                         S390_LONG (code, sty, st, ins->sreg1, 0, 
3048                                    ins->inst_destbasereg, ins->inst_offset);
3049                 }
3050                         break;
3051                 case OP_STORE_MEMBASE_REG:
3052                 case OP_STOREI8_MEMBASE_REG: {
3053                         S390_LONG (code, stg, stg, ins->sreg1, 0, 
3054                                    ins->inst_destbasereg, ins->inst_offset);
3055                 }
3056                         break;
3057                 case OP_LOADU4_MEM:
3058                         g_assert_not_reached ();
3059                         break;
3060                 case OP_LOAD_MEMBASE:
3061                 case OP_LOADI8_MEMBASE: {
3062                         S390_LONG (code, lg, lg, ins->dreg, 0, 
3063                                    ins->inst_basereg, ins->inst_offset);
3064                 }
3065                         break;
3066                 case OP_LOADI4_MEMBASE: {
3067                         S390_LONG (code, lgf, lgf, ins->dreg, 0, 
3068                                    ins->inst_basereg, ins->inst_offset);
3069                 }
3070                         break;
3071                 case OP_LOADU4_MEMBASE: {
3072                         S390_LONG (code, llgf, llgf, ins->dreg, 0, 
3073                                    ins->inst_basereg, ins->inst_offset);
3074                 }
3075                         break;
3076                 case OP_LOADU1_MEMBASE: {
3077                         S390_LONG (code, llgc, llgc, ins->dreg, 0, 
3078                                    ins->inst_basereg, ins->inst_offset);
3079                 }
3080                         break;
3081                 case OP_LOADI1_MEMBASE: {
3082                         S390_LONG (code, lgb, lgb, ins->dreg, 0, 
3083                                    ins->inst_basereg, ins->inst_offset);
3084                 }
3085                         break;
3086                 case OP_LOADU2_MEMBASE: {
3087                         S390_LONG (code, llgh, llgh, ins->dreg, 0, 
3088                                    ins->inst_basereg, ins->inst_offset);
3089                 }
3090                         break;
3091                 case OP_LOADI2_MEMBASE: {
3092                         S390_LONG (code, lgh, lgh, ins->dreg, 0, 
3093                                    ins->inst_basereg, ins->inst_offset);
3094                 }
3095                         break;
3096                 case OP_LCONV_TO_I1: {
3097                         s390_lgbr (code, ins->dreg, ins->sreg1);
3098                 }
3099                         break;
3100                 case OP_LCONV_TO_I2: {
3101                         s390_lghr (code, ins->dreg, ins->sreg1);
3102                 }
3103                         break;
3104                 case OP_LCONV_TO_U1: {
3105                         s390_llgcr (code, ins->dreg, ins->sreg1);
3106                 }
3107                         break;
3108                 case OP_LCONV_TO_U2: {
3109                         s390_llghr (code, ins->dreg, ins->sreg1);
3110                 }
3111                         break;
3112                 case OP_ICONV_TO_I1: {
3113                         s390_lgbr  (code, ins->dreg, ins->sreg1);
3114                 }
3115                         break;
3116                 case OP_ICONV_TO_I2: {
3117                         s390_lghr  (code, ins->dreg, ins->sreg1);
3118                 }
3119                         break;
3120                 case OP_ICONV_TO_U1: {
3121                         s390_llgcr (code, ins->dreg, ins->sreg1);
3122                 }
3123                         break;
3124                 case OP_ICONV_TO_U2: {
3125                         s390_llghr (code, ins->dreg, ins->sreg1);
3126                 }
3127                         break;
3128                 case OP_COMPARE: 
3129                 case OP_LCOMPARE: {
3130                         if (is_unsigned (ins->next))
3131                                 s390_clgr (code, ins->sreg1, ins->sreg2);
3132                         else
3133                                 s390_cgr  (code, ins->sreg1, ins->sreg2);
3134                 }
3135                         break;
3136                 case OP_ICOMPARE: {
3137                         if (is_unsigned (ins->next))
3138                                 s390_clr  (code, ins->sreg1, ins->sreg2);
3139                         else
3140                                 s390_cr   (code, ins->sreg1, ins->sreg2);
3141                 }
3142                         break;
3143                 case OP_COMPARE_IMM:
3144                 case OP_LCOMPARE_IMM: {
3145                         S390_SET (code, s390_r0, ins->inst_imm);
3146                         if (is_unsigned (ins->next))
3147                                 s390_clgr (code, ins->sreg1, s390_r0);
3148                         else
3149                                 s390_cgr  (code, ins->sreg1, s390_r0);
3150                 }
3151                         break;
3152                 case OP_ICOMPARE_IMM: {
3153                         S390_SET (code, s390_r0, ins->inst_imm);
3154                         if (is_unsigned (ins->next))
3155                                 s390_clr  (code, ins->sreg1, s390_r0);
3156                         else
3157                                 s390_cr   (code, ins->sreg1, s390_r0);
3158                 }
3159                         break;
3160                 case OP_BREAK: {
3161                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS, 
3162                                              mono_break);
3163                         S390_CALL_TEMPLATE (code, s390_r14);
3164                 }
3165                         break;
3166                 case OP_ADDCC: {
3167                         CHECK_SRCDST_COM;
3168                         s390_agr  (code, ins->dreg, src2);
3169                 }
3170                         break;
3171                 case OP_LADD: {
3172                         CHECK_SRCDST_COM;
3173                         s390_agr   (code, ins->dreg, src2);
3174                 }
3175                         break;
3176                 case OP_ADC: {
3177                         CHECK_SRCDST_COM;
3178                         s390_alcgr (code, ins->dreg, src2);
3179                 }
3180                         break;
3181                 case OP_ADD_IMM: {
3182                         if (ins->dreg != ins->sreg1) {
3183                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3184                         }
3185                         if (s390_is_imm16 (ins->inst_imm)) {
3186                                 s390_aghi (code, ins->dreg, ins->inst_imm);
3187                         } else if (s390_is_imm32 (ins->inst_imm)) {
3188                                 s390_agfi (code, ins->dreg, ins->inst_imm);
3189                         } else {
3190                                 S390_SET  (code, s390_r0, ins->inst_imm);
3191                                 s390_agr  (code, ins->dreg, s390_r0);
3192                         }
3193                 }
3194                         break;
3195                 case OP_LADD_IMM: {
3196                         if (ins->dreg != ins->sreg1) {
3197                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3198                         }
3199                         g_assert (s390_is_imm16 (ins->inst_imm));
3200                         s390_aghi (code, ins->dreg, ins->inst_imm);
3201                 }
3202                         break;
3203                 case OP_ADC_IMM: {
3204                         if (ins->dreg != ins->sreg1) {
3205                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3206                         }
3207                         if (s390_is_imm16 (ins->inst_imm)) {
3208                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3209                                 s390_alcgr (code, ins->dreg, s390_r0);
3210                         } else {
3211                                 S390_SET   (code, s390_r0, ins->inst_imm);
3212                                 s390_alcgr (code, ins->dreg, s390_r0);
3213                         }
3214                 }
3215                         break;
3216                 case OP_IADD_OVF:
3217                 case OP_S390_IADD_OVF: {
3218                         CHECK_SRCDST_COM;
3219                         s390_ar    (code, ins->dreg, src2);
3220                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3221                         s390_lgfr  (code, ins->dreg, ins->dreg);
3222                 }
3223                         break;
3224                 case OP_IADD_OVF_UN:
3225                 case OP_S390_IADD_OVF_UN: {
3226                         CHECK_SRCDST_COM;
3227                         s390_algr  (code, ins->dreg, src2);
3228                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3229                         s390_llgfr (code, ins->dreg, ins->dreg);
3230                 }
3231                         break;
3232                 case OP_ADD_OVF_CARRY: {
3233                         CHECK_SRCDST_COM;
3234                         s390_lghi  (code, s390_r0, 0);
3235                         s390_lgr   (code, s390_r1, s390_r0);
3236                         s390_alcgr (code, s390_r0, s390_r1);
3237                         s390_agr   (code, ins->dreg, src2);
3238                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3239                         s390_agr   (code, ins->dreg, s390_r0);
3240                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3241                 }
3242                         break;
3243                 case OP_ADD_OVF_UN_CARRY: {
3244                         CHECK_SRCDST_COM;
3245                         s390_alcgr (code, ins->dreg, src2);
3246                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3247                 }
3248                         break;
3249                 case OP_SUBCC: {
3250                         CHECK_SRCDST_NCOM;
3251                         s390_sgr (code, ins->dreg, src2);
3252                 }
3253                         break;
3254                 case OP_LSUB: {
3255                         CHECK_SRCDST_NCOM;
3256                         s390_sgr  (code, ins->dreg, src2);
3257                 }
3258                         break;
3259                 case OP_SBB: {
3260                         CHECK_SRCDST_NCOM;
3261                         s390_slbgr(code, ins->dreg, src2);
3262                 }
3263                         break;
3264                 case OP_SUB_IMM: {
3265                         if (ins->dreg != ins->sreg1) {
3266                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3267                         }
3268                         if (s390_is_imm16 (-ins->inst_imm)) {
3269                                 s390_aghi  (code, ins->dreg, -ins->inst_imm);
3270                         } else if (s390_is_imm32 (-ins->inst_imm)) {
3271                                 s390_slgfi  (code, ins->dreg, ins->inst_imm);
3272                         } else {
3273                                 S390_SET  (code, s390_r0, ins->inst_imm);
3274                                 s390_slgr (code, ins->dreg, s390_r0);
3275                         }
3276                 }
3277                         break;
3278                 case OP_LSUB_IMM: {
3279                         if (ins->dreg != ins->sreg1) {
3280                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3281                         }
3282                         if (s390_is_imm16 (-ins->inst_imm)) {
3283                                 s390_aghi  (code, ins->dreg, -ins->inst_imm);
3284                         } else if (s390_is_imm32 (-ins->inst_imm)) {
3285                                 s390_slgfi (code, ins->dreg, ins->inst_imm);
3286                         } else {
3287                                 S390_SET  (code, s390_r0, ins->inst_imm);
3288                                 s390_slgr (code, ins->dreg, s390_r0);
3289                         }
3290                 }
3291                         break;
3292                 case OP_SBB_IMM: {
3293                         if (ins->dreg != ins->sreg1) {
3294                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3295                         }
3296                         if (s390_is_imm16 (-ins->inst_imm)) {
3297                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3298                                 s390_slbgr (code, ins->dreg, s390_r0);
3299                         } else {
3300                                 S390_SET  (code, s390_r0, ins->inst_imm);
3301                                 s390_slbgr(code, ins->dreg, s390_r0);
3302                         }
3303                 }
3304                         break;
3305                 case OP_SUB_OVF_CARRY: {
3306                         CHECK_SRCDST_NCOM;
3307                         s390_lghi  (code, s390_r0, 0);
3308                         s390_lgr   (code, s390_r1, s390_r0);
3309                         s390_slbgr (code, s390_r0, s390_r1);
3310                         s390_sgr   (code, ins->dreg, src2);
3311                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3312                         s390_agr   (code, ins->dreg, s390_r0);
3313                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3314                 }
3315                         break;
3316                 case OP_SUB_OVF_UN_CARRY: {
3317                         CHECK_SRCDST_NCOM;
3318                         s390_slbgr (code, ins->dreg, src2);
3319                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3320                 }
3321                         break;
3322                 case OP_LAND: {
3323                         if (ins->sreg1 == ins->dreg) {
3324                                 s390_ngr  (code, ins->dreg, ins->sreg2);
3325                         } 
3326                         else { 
3327                                 if (ins->sreg2 == ins->dreg) { 
3328                                         s390_ngr (code, ins->dreg, ins->sreg1);
3329                                 }
3330                                 else { 
3331                                         s390_lgr (code, ins->dreg, ins->sreg1);
3332                                         s390_ngr (code, ins->dreg, ins->sreg2);
3333                                 }
3334                         }
3335                 }
3336                         break;
3337                 case OP_AND_IMM: {
3338                         if (ins->dreg != ins->sreg1) {
3339                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3340                         }
3341                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3342                         s390_ngr (code, ins->dreg, s390_r0);
3343                 }
3344                         break;
3345                 case OP_LDIV: {
3346                         s390_lgr  (code, s390_r1, ins->sreg1);
3347                         s390_dsgr (code, s390_r0, ins->sreg2);
3348                         s390_lgr  (code, ins->dreg, s390_r1);
3349                 }
3350                         break;
3351                 case OP_LDIV_UN: {
3352                         s390_lgr   (code, s390_r1, ins->sreg1);
3353                         s390_lghi  (code, s390_r0, 0);
3354                         s390_dlgr  (code, s390_r0, ins->sreg2);
3355                         s390_lgr   (code, ins->dreg, s390_r1);
3356                 }
3357                         break;
3358                 case OP_LREM: {
3359                         s390_lgr  (code, s390_r1, ins->sreg1);
3360                         s390_dsgr (code, s390_r0, ins->sreg2);
3361                         s390_lgr  (code, ins->dreg, s390_r0);
3362                         break;
3363                 }
3364                 case OP_LREM_IMM: {
3365                         if (s390_is_imm16 (ins->inst_imm)) {
3366                                 s390_lghi (code, s390_r13, ins->inst_imm);
3367                         } else {
3368                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3369                         }
3370                         s390_lgr  (code, s390_r0, ins->sreg1);
3371                         s390_dsgr (code, s390_r0, s390_r13);
3372                         s390_lgfr (code, ins->dreg, s390_r0);
3373                 }
3374                         break;
3375                 case OP_LREM_UN: {
3376                         s390_lgr   (code, s390_r1, ins->sreg1);
3377                         s390_lghi  (code, s390_r0, 0);
3378                         s390_dlgr  (code, s390_r0, ins->sreg2);
3379                         s390_lgr   (code, ins->dreg, s390_r0);
3380                 }
3381                         break;
3382                 case OP_LOR: {
3383                         if (ins->sreg1 == ins->dreg) {
3384                                 s390_ogr  (code, ins->dreg, ins->sreg2);
3385                         } 
3386                         else { 
3387                                 if (ins->sreg2 == ins->dreg) { 
3388                                         s390_ogr (code, ins->dreg, ins->sreg1);
3389                                 }
3390                                 else { 
3391                                         s390_lgr (code, ins->dreg, ins->sreg1);
3392                                         s390_ogr (code, ins->dreg, ins->sreg2);
3393                                 }
3394                         }
3395                 }
3396                         break;
3397                 case OP_OR_IMM: {
3398                         if (ins->dreg != ins->sreg1) {
3399                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3400                         }
3401                         S390_SET_MASK(code, s390_r0, ins->inst_imm);
3402                         s390_ogr (code, ins->dreg, s390_r0);
3403                 }
3404                         break;
3405                 case OP_LXOR: {
3406                         if (ins->sreg1 == ins->dreg) {
3407                                 s390_xgr  (code, ins->dreg, ins->sreg2);
3408                         } 
3409                         else { 
3410                                 if (ins->sreg2 == ins->dreg) { 
3411                                         s390_xgr (code, ins->dreg, ins->sreg1);
3412                                 }
3413                                 else { 
3414                                         s390_lgr (code, ins->dreg, ins->sreg1);
3415                                         s390_xgr (code, ins->dreg, ins->sreg2);
3416                                 }
3417                         }
3418                 }
3419                         break;
3420                 case OP_XOR_IMM: {
3421                         if (ins->dreg != ins->sreg1) {
3422                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3423                         }
3424                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3425                         s390_xgr (code, ins->dreg, s390_r0);
3426                 }
3427                         break;
3428                 case OP_LSHL: {
3429                         CHECK_SRCDST_NCOM;
3430                         s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3431                 }
3432                         break;
3433                 case OP_SHL_IMM: 
3434                 case OP_LSHL_IMM: {
3435                         if (ins->sreg1 != ins->dreg) {
3436                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3437                         }
3438                         s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3439                 }
3440                         break;
3441                 case OP_LSHR: {
3442                         CHECK_SRCDST_NCOM;
3443                         s390_srag  (code, ins->dreg, ins->dreg, src2, 0);
3444                 }
3445                         break;
3446                 case OP_SHR_IMM:
3447                 case OP_LSHR_IMM: {
3448                         if (ins->sreg1 != ins->dreg) {
3449                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3450                         }
3451                         s390_srag  (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3452                 }
3453                         break;
3454                 case OP_SHR_UN_IMM: 
3455                 case OP_LSHR_UN_IMM: {
3456                         if (ins->sreg1 != ins->dreg) {
3457                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3458                         }
3459                         s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3460                 }
3461                         break;
3462                 case OP_LSHR_UN: {
3463                         CHECK_SRCDST_NCOM;
3464                         s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3465                 }
3466                         break;
3467                 case OP_LNOT: {
3468                         if (ins->sreg1 != ins->dreg) {
3469                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3470                         }
3471                         s390_lghi (code, s390_r0, -1);
3472                         s390_xgr  (code, ins->dreg, s390_r0);
3473                 }
3474                         break;
3475                 case OP_LNEG: {
3476                         s390_lcgr (code, ins->dreg, ins->sreg1);
3477                 }
3478                         break;
3479                 case OP_LMUL: {
3480                         CHECK_SRCDST_COM;
3481                         s390_msgr (code, ins->dreg, src2);
3482                 }
3483                         break;
3484                 case OP_MUL_IMM: 
3485                 case OP_LMUL_IMM: {
3486                         if (ins->dreg != ins->sreg1) {
3487                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3488                         }
3489                         if (s390_is_imm16 (ins->inst_imm)) {
3490                                 s390_lghi (code, s390_r13, ins->inst_imm);
3491                         } else if (s390_is_imm32 (ins->inst_imm)) {
3492                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3493                         } else {
3494                                 S390_SET (code, s390_r13, ins->inst_imm);
3495                         }
3496                         s390_msgr (code, ins->dreg, s390_r13);
3497                 }
3498                         break;
3499                 case OP_LMUL_OVF: {
3500                         short int *o[2];
3501                         s390_ltgr (code, s390_r1, ins->sreg1);
3502                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3503                         s390_ltgr (code, s390_r0, ins->sreg2);
3504                         s390_jnz  (code, 6);
3505                         s390_lghi (code, s390_r1, 0);
3506                         s390_j    (code, 0); CODEPTR(code, o[1]);
3507                         s390_xgr  (code, s390_r0, s390_r1);
3508                         s390_msgr (code, s390_r1, ins->sreg2);
3509                         s390_xgr  (code, s390_r0, s390_r1);
3510                         s390_srlg (code, s390_r0, s390_r0, 0, 63);
3511                         s390_ltgr (code, s390_r0, s390_r0);
3512                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3513                         PTRSLOT   (code, o[0]); 
3514                         PTRSLOT   (code, o[1]);
3515                         s390_lgr  (code, ins->dreg, s390_r1);
3516                 }
3517                         break;
3518                 case OP_LMUL_OVF_UN: {
3519                         s390_lghi  (code, s390_r0, 0);
3520                         s390_lgr   (code, s390_r1, ins->sreg1);
3521                         s390_mlgr  (code, s390_r0, ins->sreg2);
3522                         s390_ltgr  (code, s390_r0, s390_r0);
3523                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3524                         s390_lgr   (code, ins->dreg, s390_r1);
3525                 }
3526                         break;
3527                 case OP_IADDCC: {
3528                         g_assert_not_reached ();
3529                         CHECK_SRCDST_COM_I;
3530                         s390_algr (code, ins->dreg, src2);
3531                 }
3532                         break;
3533                 case OP_IADD: {
3534                         CHECK_SRCDST_COM_I;
3535                         s390_agr  (code, ins->dreg, src2);
3536                 }
3537                         break;
3538                 case OP_IADC: {
3539                         g_assert_not_reached ();
3540                         CHECK_SRCDST_COM_I;
3541                         s390_alcgr (code, ins->dreg, src2);
3542                 }
3543                         break;
3544                 case OP_IADD_IMM: {
3545                         if (ins->dreg != ins->sreg1) {
3546                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3547                         }
3548                         if (s390_is_imm16 (ins->inst_imm)) {
3549                                 s390_aghi (code, ins->dreg, ins->inst_imm);
3550                         } else {
3551                                 s390_afi  (code, ins->dreg, ins->inst_imm);
3552                         }
3553                 }
3554                         break;
3555                 case OP_IADC_IMM: {
3556                         if (ins->dreg != ins->sreg1) {
3557                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3558                         } 
3559                         if (s390_is_imm16 (ins->inst_imm)) {
3560                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3561                                 s390_alcgr (code, ins->dreg, s390_r0);
3562                         } else {
3563                                 S390_SET   (code, s390_r0, ins->inst_imm);
3564                                 s390_alcgr (code, ins->dreg, s390_r0);
3565                         }
3566                 }
3567                         break;
3568                 case OP_LADD_OVF:
3569                 case OP_S390_LADD_OVF: {
3570                         CHECK_SRCDST_COM;
3571                         s390_agr    (code, ins->dreg, src2);
3572                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3573                 }
3574                         break;
3575                 case OP_LADD_OVF_UN:
3576                 case OP_S390_LADD_OVF_UN: {
3577                         CHECK_SRCDST_COM;
3578                         s390_algr  (code, ins->dreg, src2);
3579                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3580                 }
3581                         break;
3582                 case OP_ISUBCC: {
3583                         CHECK_SRCDST_NCOM_I;
3584                         s390_slgr (code, ins->dreg, src2);
3585                 }
3586                         break;
3587                 case OP_ISUB: {
3588                         CHECK_SRCDST_NCOM_I;
3589                         s390_sgr  (code, ins->dreg, src2);
3590                 }
3591                         break;
3592                 case OP_ISBB: {
3593                         CHECK_SRCDST_NCOM_I;
3594                         s390_slbgr (code, ins->dreg, src2);
3595                 }
3596                         break;
3597                 case OP_ISUB_IMM: {
3598                         if (ins->dreg != ins->sreg1) {
3599                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3600                         }
3601                         if (s390_is_imm16 (-ins->inst_imm)) {
3602                                 s390_aghi (code, ins->dreg, -ins->inst_imm);
3603                         } else {
3604                                 s390_agfi (code, ins->dreg, -ins->inst_imm);
3605                         }
3606                 }
3607                         break;
3608                 case OP_ISBB_IMM: {
3609                         S390_SET (code, s390_r0, ins->inst_imm);
3610                         s390_slgfr (code, ins->dreg, s390_r0);
3611                 }
3612                         break;
3613                 case OP_ISUB_OVF:
3614                 case OP_S390_ISUB_OVF: {
3615                         CHECK_SRCDST_NCOM;
3616                         s390_sr   (code, ins->dreg, src2);
3617                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3618                         s390_lgfr (code, ins->dreg, ins->dreg);
3619                 }
3620                         break;
3621                 case OP_ISUB_OVF_UN:
3622                 case OP_S390_ISUB_OVF_UN: {
3623                         CHECK_SRCDST_NCOM;
3624                         s390_slr  (code, ins->dreg, src2);
3625                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3626                         s390_llgfr(code, ins->dreg, ins->dreg);
3627                 }
3628                         break;
3629                 case OP_LSUB_OVF:
3630                 case OP_S390_LSUB_OVF: {
3631                         CHECK_SRCDST_NCOM;
3632                         s390_sgr   (code, ins->dreg, src2);
3633                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3634                 }
3635                         break;
3636                 case OP_LSUB_OVF_UN:
3637                 case OP_S390_LSUB_OVF_UN: {
3638                         CHECK_SRCDST_NCOM;
3639                         s390_slgr  (code, ins->dreg, src2);
3640                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3641                 }
3642                         break;
3643                 case OP_IAND: {
3644                         CHECK_SRCDST_NCOM_I;
3645                         s390_ngr (code, ins->dreg, src2);
3646                 }
3647                         break;
3648                 case OP_IAND_IMM: {
3649                         if (ins->dreg != ins->sreg1) {
3650                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3651                         }
3652                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3653                         s390_ngr  (code, ins->dreg, s390_r0);
3654                 }
3655                         break;
3656                 case OP_IDIV: {
3657                         s390_lgfr (code, s390_r0, ins->sreg1);
3658                         s390_srda (code, s390_r0, 0, 32);
3659                         s390_dr   (code, s390_r0, ins->sreg2);
3660                         s390_lgfr (code, ins->dreg, s390_r1);
3661                 }
3662                         break;
3663                 case OP_IDIV_UN: {
3664                         s390_lgfr (code, s390_r0, ins->sreg1);
3665                         s390_srdl (code, s390_r0, 0, 32);
3666                         s390_dlr  (code, s390_r0, ins->sreg2);
3667                         s390_lgfr (code, ins->dreg, s390_r1);
3668                 }
3669                         break;
3670                 case OP_IDIV_IMM: {
3671                         if (s390_is_imm16 (ins->inst_imm)) {
3672                                 s390_lghi (code, s390_r13, ins->inst_imm);
3673                         } else {
3674                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3675                         }
3676                         s390_lgfr (code, s390_r0, ins->sreg1);
3677                         s390_srda (code, s390_r0, 0, 32);
3678                         s390_dr   (code, s390_r0, ins->sreg2);
3679                         s390_lgfr (code, ins->dreg, s390_r1);
3680                 }
3681                         break;
3682                 case OP_IREM: {
3683                         s390_lgfr (code, s390_r0, ins->sreg1);
3684                         s390_srda (code, s390_r0, 0, 32);
3685                         s390_dr   (code, s390_r0, ins->sreg2);
3686                         s390_lgfr (code, ins->dreg, s390_r0);
3687                         break;
3688                 case OP_IREM_UN:
3689                         s390_lgfr (code, s390_r0, ins->sreg1);
3690                         s390_srdl (code, s390_r0, 0, 32);
3691                         s390_dlr  (code, s390_r0, ins->sreg2);
3692                         s390_lgfr (code, ins->dreg, s390_r0);
3693                 }
3694                         break;
3695                 case OP_IREM_IMM: {
3696                         if (s390_is_imm16 (ins->inst_imm)) {
3697                                 s390_lghi (code, s390_r13, ins->inst_imm);
3698                         } else {
3699                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3700                         }
3701                         s390_lgfr (code, s390_r0, ins->sreg1);
3702                         s390_srda (code, s390_r0, 0, 32);
3703                         s390_dr   (code, s390_r0, ins->sreg2);
3704                         s390_lgfr (code, ins->dreg, s390_r0);
3705                 }
3706                         break;
3707                 case OP_IOR: {
3708                         CHECK_SRCDST_COM_I;
3709                         s390_ogr (code, ins->dreg, src2);
3710                 }
3711                         break;
3712                 case OP_IOR_IMM: {
3713                         if (ins->dreg != ins->sreg1) {
3714                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3715                         }
3716                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3717                         s390_ogr  (code, ins->dreg, s390_r0);
3718                 }
3719                         break;
3720                 case OP_IXOR: {
3721                         CHECK_SRCDST_COM_I;
3722                         s390_xgr (code, ins->dreg, src2);
3723                 }
3724                         break;
3725                 case OP_IXOR_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_xgr  (code, ins->dreg, s390_r0);
3731                 }
3732                         break;
3733                 case OP_ISHL: {
3734                         CHECK_SRCDST_NCOM;
3735                         s390_sll  (code, ins->dreg, src2, 0);
3736                 }
3737                         break;
3738                 case OP_ISHL_IMM: {
3739                         if (ins->sreg1 != ins->dreg) {
3740                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3741                         }
3742                         s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3743                 }
3744                         break;
3745                 case OP_ISHR: {
3746                         CHECK_SRCDST_NCOM;
3747                         s390_sra (code, ins->dreg, src2, 0);
3748                 }
3749                         break;
3750                 case OP_ISHR_IMM: {
3751                         if (ins->sreg1 != ins->dreg) {
3752                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3753                         }
3754                         s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3755                 }
3756                         break;
3757                 case OP_ISHR_UN_IMM: {
3758                         if (ins->sreg1 != ins->dreg) {
3759                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3760                         }
3761                         s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3762                 }
3763                         break;
3764                 case OP_ISHR_UN: {
3765                         CHECK_SRCDST_NCOM;
3766                         s390_srl  (code, ins->dreg, src2, 0);
3767                 }
3768                         break;
3769                 case OP_INOT: {
3770                         if (ins->sreg1 != ins->dreg) {
3771                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3772                         }
3773                         s390_lghi (code, s390_r0, -1);
3774                         s390_xgr  (code, ins->dreg, s390_r0);
3775                 }
3776                         break;
3777                 case OP_INEG: {
3778                         s390_lcgr (code, ins->dreg, ins->sreg1);
3779                 }
3780                         break;
3781                 case OP_IMUL: {
3782                         CHECK_SRCDST_COM_I;
3783                         s390_msr (code, ins->dreg, src2);
3784                 }
3785                         break;
3786                 case OP_IMUL_IMM: {
3787                         if (ins->dreg != ins->sreg1) {
3788                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3789                         }
3790                         if (s390_is_imm16 (ins->inst_imm)) {
3791                                 s390_lghi (code, s390_r0, ins->inst_imm);
3792                         } else {
3793                                 s390_lgfi (code, s390_r0, ins->inst_imm);
3794                         }
3795                         s390_msr  (code, ins->dreg, s390_r0);
3796                 }
3797                         break;
3798                 case OP_IMUL_OVF: {
3799                         short int *o[2];
3800                         s390_ltr  (code, s390_r1, ins->sreg1);
3801                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3802                         s390_ltr  (code, s390_r0, ins->sreg2);
3803                         s390_jnz  (code, 6);
3804                         s390_lhi  (code, s390_r1, 0);
3805                         s390_j    (code, 0); CODEPTR(code, o[1]);
3806                         s390_xr   (code, s390_r0, s390_r1);
3807                         s390_msr  (code, s390_r1, ins->sreg2);
3808                         s390_xr   (code, s390_r0, s390_r1);
3809                         s390_srl  (code, s390_r0, 0, 31);
3810                         s390_ltr  (code, s390_r0, s390_r0);
3811                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3812                         PTRSLOT   (code, o[0]); 
3813                         PTRSLOT   (code, o[1]);
3814                         s390_lgfr (code, ins->dreg, s390_r1);
3815                 }
3816                         break;
3817                 case OP_IMUL_OVF_UN: {
3818                         s390_lhi  (code, s390_r0, 0);
3819                         s390_lr   (code, s390_r1, ins->sreg1);
3820                         s390_mlr  (code, s390_r0, ins->sreg2);
3821                         s390_ltr  (code, s390_r0, s390_r0);
3822                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3823                         s390_lgfr (code, ins->dreg, s390_r1);
3824                 }
3825                         break;
3826                 case OP_ICONST: 
3827                 case OP_I8CONST: {
3828                         S390_SET (code, ins->dreg, ins->inst_c0);
3829                 }
3830                         break;
3831                 case OP_AOTCONST: {
3832                         mono_add_patch_info (cfg, code - cfg->native_code, 
3833                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3834                         S390_LOAD_TEMPLATE (code, ins->dreg);
3835                 }
3836                         break;
3837                 case OP_JUMP_TABLE: {
3838                         mono_add_patch_info (cfg, code - cfg->native_code, 
3839                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3840                         S390_LOAD_TEMPLATE (code, ins->dreg);
3841                 }
3842                         break;
3843                 case OP_MOVE:
3844                         if (ins->dreg != ins->sreg1) {
3845                                 s390_lgr (code, ins->dreg, ins->sreg1);
3846                         }
3847                         break;
3848                 case OP_LCONV_TO_I:
3849                 case OP_LCONV_TO_I8:
3850                 case OP_SEXT_I4:
3851                         s390_lgfr (code, ins->dreg, ins->sreg1);
3852                         break;
3853                 case OP_LCONV_TO_I4:
3854                         s390_lgfr (code, ins->dreg, ins->sreg1);
3855                         break;
3856                 case OP_LCONV_TO_U:
3857                 case OP_LCONV_TO_U8:
3858                 case OP_LCONV_TO_U4:
3859                 case OP_ZEXT_I4:
3860                         s390_llgfr (code, ins->dreg, ins->sreg1);
3861                         break;
3862                 case OP_LCONV_TO_OVF_U4:
3863                         S390_SET  (code, s390_r0, 4294967295);
3864                         s390_clgr (code, ins->sreg1, s390_r0);
3865                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3866                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3867                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3868                         s390_llgfr(code, ins->dreg, ins->sreg1);
3869                         break;
3870                 case OP_LCONV_TO_OVF_I4_UN:
3871                         S390_SET  (code, s390_r0, 2147483647);
3872                         s390_cgr  (code, ins->sreg1, s390_r0);
3873                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3874                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3875                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3876                         s390_lgfr (code, ins->dreg, ins->sreg1);
3877                         break;
3878                 case OP_FMOVE:
3879                         if (ins->dreg != ins->sreg1) {
3880                                 s390_ldr   (code, ins->dreg, ins->sreg1);
3881                         }
3882                         break;
3883                 case OP_MOVE_F_TO_I8: 
3884                         s390_lgdr (code, ins->dreg, ins->sreg1);
3885                         break;
3886                 case OP_MOVE_I8_TO_F: 
3887                         s390_ldgr (code, ins->dreg, ins->sreg1);
3888                         break;
3889                 case OP_MOVE_F_TO_I4:
3890                         s390_ledbr (code, s390_f0, ins->sreg1);
3891                         s390_lgdr (code, ins->dreg, s390_f0);
3892                         s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3893                         break;
3894                 case OP_MOVE_I4_TO_F: 
3895                         s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3896                         s390_ldgr (code, ins->dreg, s390_r0);
3897                         s390_ldebr (code, ins->dreg, ins->dreg);
3898                         break;
3899                 case OP_FCONV_TO_R4:
3900                         s390_ledbr (code, ins->dreg, ins->sreg1);
3901                         s390_ldebr (code, ins->dreg, ins->dreg);
3902                         break;
3903                 case OP_S390_SETF4RET:
3904                         s390_ledbr (code, ins->dreg, ins->sreg1);
3905                         break;
3906                 case OP_TLS_GET: {
3907                         if (s390_is_imm16 (ins->inst_offset)) {
3908                                 s390_lghi (code, s390_r13, ins->inst_offset);
3909                         } else if (s390_is_imm32 (ins->inst_offset)) {
3910                                 s390_lgfi (code, s390_r13, ins->inst_offset);
3911                         } else {
3912                                 S390_SET  (code, s390_r13, ins->inst_offset);
3913                         }
3914                         s390_ear (code, s390_r1, 0);
3915                         s390_sllg(code, s390_r1, s390_r1, 0, 32);
3916                         s390_ear (code, s390_r1, 1);
3917                         s390_lg  (code, ins->dreg, s390_r13, s390_r1, 0);
3918                         }
3919                         break;
3920                 case OP_TLS_SET: {
3921                         if (s390_is_imm16 (ins->inst_offset)) {
3922                                 s390_lghi (code, s390_r13, ins->inst_offset);
3923                         } else if (s390_is_imm32 (ins->inst_offset)) {
3924                                 s390_lgfi (code, s390_r13, ins->inst_offset);
3925                         } else {
3926                                 S390_SET  (code, s390_r13, ins->inst_offset);
3927                         }
3928                         s390_ear (code, s390_r1, 0);
3929                         s390_sllg(code, s390_r1, s390_r1, 0, 32);
3930                         s390_ear (code, s390_r1, 1);
3931                         s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3932                         }
3933                         break;
3934                 case OP_JMP: {
3935                         if (cfg->method->save_lmf)
3936                                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3937
3938                         if (cfg->flags & MONO_CFG_HAS_TAIL) {
3939                                 code =  emit_load_volatile_arguments (code, cfg);
3940                         }
3941
3942                         code = backUpStackPtr(cfg, code);
3943                         s390_lg  (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3944                         mono_add_patch_info (cfg, code - cfg->native_code,
3945                                              MONO_PATCH_INFO_METHOD_JUMP,
3946                                              ins->inst_p0);
3947                         s390_jcl (code, S390_CC_UN, 0);
3948                 }
3949                         break;
3950                 case OP_CHECK_THIS: {
3951                         /* ensure ins->sreg1 is not NULL */
3952                         s390_lg   (code, s390_r0, 0, ins->sreg1, 0);
3953                         s390_ltgr (code, s390_r0, s390_r0);
3954 //                      EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3955                 }
3956                         break;
3957                 case OP_ARGLIST: {
3958                         int offset = cfg->sig_cookie + cfg->stack_usage;
3959
3960                         if (s390_is_imm16 (offset)) {
3961                                 s390_lghi (code, s390_r0, offset);
3962                         } else if (s390_is_imm32 (offset)) {
3963                                 s390_lgfi (code, s390_r0, offset);
3964                         } else {
3965                                 S390_SET  (code, s390_r0, offset);
3966                         }
3967                         s390_agr  (code, s390_r0, cfg->frame_reg);
3968                         s390_stg  (code, s390_r0, 0, ins->sreg1, 0);
3969                 }
3970                         break;
3971                 case OP_FCALL: {
3972                         call = (MonoCallInst*)ins;
3973                         if (ins->flags & MONO_INST_HAS_METHOD)
3974                                 mono_add_patch_info (cfg, code-cfg->native_code,
3975                                                      MONO_PATCH_INFO_METHOD, 
3976                                                      call->method);
3977                         else
3978                                 mono_add_patch_info (cfg, code-cfg->native_code,
3979                                                      MONO_PATCH_INFO_ABS, 
3980                                                      call->fptr);
3981                         S390_CALL_TEMPLATE (code, s390_r14);
3982                         if (call->signature->ret->type == MONO_TYPE_R4)
3983                                 s390_ldebr (code, s390_f0, s390_f0);
3984                 }
3985                         break;
3986                 case OP_LCALL:
3987                 case OP_VCALL:
3988                 case OP_VCALL2:
3989                 case OP_VOIDCALL:
3990                 case OP_CALL: {
3991                         call = (MonoCallInst*)ins;
3992                         if (ins->flags & MONO_INST_HAS_METHOD)
3993                                 mono_add_patch_info (cfg, code-cfg->native_code,
3994                                                      MONO_PATCH_INFO_METHOD, 
3995                                                      call->method);
3996                         else
3997                                 mono_add_patch_info (cfg, code-cfg->native_code,
3998                                                      MONO_PATCH_INFO_ABS, 
3999                                                      call->fptr);
4000                         S390_CALL_TEMPLATE (code, s390_r14);
4001                 }
4002                         break;
4003                 case OP_FCALL_REG: {
4004                         call = (MonoCallInst*)ins;
4005                         s390_lgr  (code, s390_r1, ins->sreg1);
4006                         s390_basr (code, s390_r14, s390_r1);
4007                         if (call->signature->ret->type == MONO_TYPE_R4)
4008                                 s390_ldebr (code, s390_f0, s390_f0);
4009                 }
4010                         break;
4011                 case OP_LCALL_REG:
4012                 case OP_VCALL_REG:
4013                 case OP_VCALL2_REG:
4014                 case OP_VOIDCALL_REG:
4015                 case OP_CALL_REG: {
4016                         s390_lgr  (code, s390_r1, ins->sreg1);
4017                         s390_basr (code, s390_r14, s390_r1);
4018                 }
4019                         break;
4020                 case OP_FCALL_MEMBASE: {
4021                         call = (MonoCallInst*)ins;
4022                         s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4023                         s390_basr (code, s390_r14, s390_r1);
4024                         if (call->signature->ret->type == MONO_TYPE_R4)
4025                                 s390_ldebr (code, s390_f0, s390_f0);
4026                 }
4027                         break;
4028                 case OP_LCALL_MEMBASE:
4029                 case OP_VCALL_MEMBASE:
4030                 case OP_VCALL2_MEMBASE:
4031                 case OP_VOIDCALL_MEMBASE:
4032                 case OP_CALL_MEMBASE: {
4033                         s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4034                         s390_basr (code, s390_r14, s390_r1);
4035                 }
4036                         break;
4037                 case OP_LOCALLOC: {
4038                         int alloca_skip;
4039                         int area_offset;
4040
4041                         if (cfg->param_area == 0)
4042                                 alloca_skip = S390_MINIMAL_STACK_SIZE;
4043                         else
4044                                 alloca_skip = cfg->param_area;
4045
4046                         area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4047                         s390_lgr  (code, s390_r1, ins->sreg1);
4048                         if (ins->flags & MONO_INST_INIT)
4049                                 s390_lgr  (code, s390_r0, ins->sreg1);
4050                         s390_aghi (code, s390_r1, 14);
4051                         s390_srlg (code, s390_r1, s390_r1, 0, 3);
4052                         s390_sllg (code, s390_r1, s390_r1, 0, 3);
4053                         if (cfg->method->save_lmf) {
4054                                 /*----------------------------------*/
4055                                 /* we have to adjust lmf ebp value  */
4056                                 /*----------------------------------*/
4057                                 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4058
4059                                 s390_lgr (code, s390_r13, cfg->frame_reg);
4060                                 if (s390_is_imm16(lmfOffset)) {
4061                                         s390_aghi (code, s390_r13, lmfOffset);
4062                                 } else if (s390_is_imm32(lmfOffset)) {
4063                                         s390_agfi (code, s390_r13, lmfOffset);
4064                                 } else {
4065                                         S390_SET  (code, s390_r13, lmfOffset);
4066                                 }
4067                                 s390_lgr (code, s390_r14, STK_BASE);
4068                                 s390_sgr (code, s390_r14, s390_r1);
4069                                 s390_stg (code, s390_r14, 0, s390_r13,
4070                                           G_STRUCT_OFFSET(MonoLMF, ebp));
4071                         }
4072                         s390_lg   (code, s390_r13, 0, STK_BASE, 0);
4073                         s390_sgr  (code, STK_BASE, s390_r1);
4074                         s390_stg  (code, s390_r13, 0, STK_BASE, 0);
4075                         s390_la   (code, ins->dreg, 0, STK_BASE, area_offset);
4076                         s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4077                         s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4078                         if (ins->flags & MONO_INST_INIT) {
4079                                 s390_lgr  (code, s390_r1, s390_r0);
4080                                 s390_lgr  (code, s390_r0, ins->dreg);
4081                                 s390_lgr  (code, s390_r14, s390_r12);
4082                                 s390_lghi (code, s390_r13, 0);
4083                                 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4084                                 s390_jo   (code, -2);
4085                                 s390_lgr  (code, s390_r12, s390_r14);
4086                         }
4087                 }
4088                         break;
4089                 case OP_THROW: {
4090                         s390_lgr  (code, s390_r2, ins->sreg1);
4091                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
4092                                              (gpointer) "mono_arch_throw_exception");
4093                         S390_CALL_TEMPLATE(code, s390_r14);
4094                 }
4095                         break;
4096                 case OP_RETHROW: {
4097                         s390_lgr  (code, s390_r2, ins->sreg1);
4098                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
4099                                              (gpointer) "mono_arch_rethrow_exception");
4100                         S390_CALL_TEMPLATE(code, s390_r14);
4101                 }
4102                         break;
4103                 case OP_START_HANDLER: {
4104                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4105
4106                         S390_LONG (code, stg, stg, s390_r14, 0,
4107                                    spvar->inst_basereg, 
4108                                    spvar->inst_offset);
4109                 }
4110                         break;
4111                 case OP_ENDFILTER: {
4112                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4113
4114                         if (ins->sreg1 != s390_r2)
4115                                 s390_lgr(code, s390_r2, ins->sreg1);
4116                         S390_LONG (code, lg, lg, s390_r14, 0,
4117                                    spvar->inst_basereg, 
4118                                    spvar->inst_offset);
4119                         s390_br  (code, s390_r14);
4120                 }
4121                         break;
4122                 case OP_ENDFINALLY: {
4123                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4124
4125                         S390_LONG (code, lg, lg, s390_r14, 0,
4126                                    spvar->inst_basereg, 
4127                                    spvar->inst_offset);
4128                         s390_br  (code, s390_r14);
4129                 }
4130                         break;
4131                 case OP_CALL_HANDLER: {
4132                         mono_add_patch_info (cfg, code-cfg->native_code, 
4133                                              MONO_PATCH_INFO_BB, ins->inst_target_bb);
4134                         s390_brasl (code, s390_r14, 0);
4135                         mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4136                 }
4137                         break;
4138                 case OP_LABEL: {
4139                         ins->inst_c0 = code - cfg->native_code;
4140                 }
4141                         break;
4142                 case OP_RELAXED_NOP:
4143                 case OP_NOP:
4144                 case OP_DUMMY_USE:
4145                 case OP_DUMMY_STORE:
4146                 case OP_NOT_REACHED:
4147                 case OP_NOT_NULL: {
4148                 }
4149                         break;
4150                 case OP_IL_SEQ_POINT:
4151                         mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4152                         break;
4153                 case OP_SEQ_POINT: {
4154                         int i;
4155
4156                         if (cfg->compile_aot)
4157                                 NOT_IMPLEMENTED;
4158
4159                         /* 
4160                          * Read from the single stepping trigger page. This will cause a
4161                          * SIGSEGV when single stepping is enabled.
4162                          * We do this _before_ the breakpoint, so single stepping after
4163                          * a breakpoint is hit will step to the next IL offset.
4164                          */
4165                         if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4166                                 breakpointCode.pTrigger = ss_trigger_page;
4167                                 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4168                                 code += BREAKPOINT_SIZE;
4169                         }
4170
4171                         mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4172
4173                         /* 
4174                          * A placeholder for a possible breakpoint inserted by
4175                          * mono_arch_set_breakpoint ().
4176                          */
4177                         for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4178                                 s390_nop (code);
4179
4180                         /*
4181                          * Add an additional nop so skipping the bp doesn't cause the ip to point
4182                          * to another IL offset.
4183                          */
4184                         s390_nop (code);
4185
4186                         break;
4187                 }
4188                 case OP_GENERIC_CLASS_INIT: {
4189                         static int byte_offset = -1;
4190                         static guint8 bitmask;
4191                         short int *jump;
4192
4193                         g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4194
4195                         if (byte_offset < 0)
4196                                 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4197
4198                         s390_tm (code, ins->sreg1, byte_offset, bitmask);
4199                         s390_jo (code, 0); CODEPTR(code, jump);
4200
4201                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4202                                                 "mono_generic_class_init");
4203                         S390_CALL_TEMPLATE(code, s390_r14);
4204
4205                         PTRSLOT (code, jump);
4206
4207                         ins->flags |= MONO_INST_GC_CALLSITE;
4208                         ins->backend.pc_offset = code - cfg->native_code;
4209                         break;
4210                 }
4211                 case OP_BR: 
4212                         EMIT_UNCOND_BRANCH(ins);
4213                         break;
4214                 case OP_BR_REG: {
4215                         s390_br  (code, ins->sreg1);
4216                 }
4217                         break;
4218                 case OP_CEQ: 
4219                 case OP_ICEQ:
4220                 case OP_LCEQ: {
4221                         s390_lghi(code, ins->dreg, 1);
4222                         s390_jz  (code, 4);
4223                         s390_lghi(code, ins->dreg, 0);
4224                 }
4225                         break;
4226                 case OP_CLT: 
4227                 case OP_ICLT:
4228                 case OP_LCLT: {
4229                         s390_lghi(code, ins->dreg, 1);
4230                         s390_jl  (code, 4);
4231                         s390_lghi(code, ins->dreg, 0);
4232                 }
4233                         break;
4234                 case OP_CLT_UN:
4235                 case OP_ICLT_UN:
4236                 case OP_LCLT_UN: {
4237                         s390_lghi(code, ins->dreg, 1);
4238                         s390_jlo (code, 4);
4239                         s390_lghi(code, ins->dreg, 0);
4240                 }
4241                         break;
4242                 case OP_CGT: 
4243                 case OP_ICGT:
4244                 case OP_LCGT: {
4245                         s390_lghi(code, ins->dreg, 1);
4246                         s390_jh  (code, 4);
4247                         s390_lghi(code, ins->dreg, 0);
4248                 }
4249                         break;
4250                 case OP_CGT_UN:
4251                 case OP_ICGT_UN:
4252                 case OP_LCGT_UN: {
4253                         s390_lghi(code, ins->dreg, 1);
4254                         s390_jho (code, 4);
4255                         s390_lghi(code, ins->dreg, 0);
4256                 }
4257                         break;
4258                 case OP_COND_EXC_EQ:
4259                 case OP_COND_EXC_IEQ:
4260                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4261                         break;
4262                 case OP_COND_EXC_NE_UN:
4263                 case OP_COND_EXC_INE_UN:
4264                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4265                         break;
4266                 case OP_COND_EXC_LT:
4267                 case OP_COND_EXC_ILT:
4268                 case OP_COND_EXC_LT_UN:
4269                 case OP_COND_EXC_ILT_UN:
4270                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4271                         break;
4272                 case OP_COND_EXC_GT:
4273                 case OP_COND_EXC_IGT:
4274                 case OP_COND_EXC_GT_UN:
4275                 case OP_COND_EXC_IGT_UN:
4276                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4277                         break;
4278                 case OP_COND_EXC_GE:
4279                 case OP_COND_EXC_IGE:
4280                 case OP_COND_EXC_GE_UN:
4281                 case OP_COND_EXC_IGE_UN:
4282                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4283                         break;
4284                 case OP_COND_EXC_LE:
4285                 case OP_COND_EXC_ILE:
4286                 case OP_COND_EXC_LE_UN:
4287                 case OP_COND_EXC_ILE_UN:
4288                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4289                         break;
4290                 case OP_COND_EXC_OV:
4291                 case OP_COND_EXC_IOV:
4292                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4293                         break;
4294                 case OP_COND_EXC_NO:
4295                 case OP_COND_EXC_INO:
4296                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4297                         break;
4298                 case OP_COND_EXC_C:
4299                 case OP_COND_EXC_IC:
4300                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4301                         break;
4302                 case OP_COND_EXC_NC:
4303                 case OP_COND_EXC_INC:
4304                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4305                         break;
4306                 case OP_LBEQ:
4307                 case OP_IBEQ:
4308                         EMIT_COND_BRANCH (ins, S390_CC_EQ);
4309                         break;  
4310                 case OP_LBNE_UN:
4311                 case OP_IBNE_UN:
4312                         EMIT_COND_BRANCH (ins, S390_CC_NE);
4313                         break;  
4314                 case OP_LBLT:
4315                 case OP_LBLT_UN:
4316                 case OP_IBLT:
4317                 case OP_IBLT_UN:
4318                         EMIT_COND_BRANCH (ins, S390_CC_LT);
4319                         break;  
4320                 case OP_LBGT:
4321                 case OP_LBGT_UN:
4322                 case OP_IBGT:
4323                 case OP_IBGT_UN:
4324                         EMIT_COND_BRANCH (ins, S390_CC_GT);
4325                         break;  
4326                 case OP_LBGE:
4327                 case OP_LBGE_UN:
4328                 case OP_IBGE:
4329                 case OP_IBGE_UN:
4330                         EMIT_COND_BRANCH (ins, S390_CC_GE);
4331                         break;  
4332                 case OP_LBLE:
4333                 case OP_LBLE_UN:
4334                 case OP_IBLE:
4335                 case OP_IBLE_UN:
4336                         EMIT_COND_BRANCH (ins, S390_CC_LE);
4337                         break;
4338
4339                 /* floating point opcodes */
4340                 case OP_R8CONST: {
4341                         if (*((double *) ins->inst_p0) == 0) {
4342                                 s390_lzdr (code, ins->dreg);
4343                         } else {
4344                                 S390_SET  (code, s390_r13, ins->inst_p0);
4345                                 s390_ld   (code, ins->dreg, 0, s390_r13, 0);
4346                         }
4347                 }
4348                         break;
4349                 case OP_R4CONST: {
4350                         if (*((float *) ins->inst_p0) == 0) {
4351                                 s390_lzdr (code, ins->dreg);
4352                         } else {
4353                                 S390_SET  (code, s390_r13, ins->inst_p0);
4354                                 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4355                         }
4356                 }
4357                         break;
4358                 case OP_STORER8_MEMBASE_REG: {
4359                         S390_LONG (code, stdy, std, ins->sreg1, 0, 
4360                                    ins->inst_destbasereg, ins->inst_offset);
4361                 }
4362                         break;
4363                 case OP_LOADR8_MEMBASE: {
4364                         S390_LONG (code, ldy, ld, ins->dreg, 0, 
4365                                    ins->inst_basereg, ins->inst_offset);
4366                 }
4367                         break;
4368                 case OP_STORER4_MEMBASE_REG: {
4369                         s390_ledbr (code, s390_f15, ins->sreg1);
4370                         S390_LONG (code, stey, ste, s390_f15, 0, 
4371                                    ins->inst_destbasereg, ins->inst_offset);
4372                 }
4373                         break;
4374                 case OP_LOADR4_MEMBASE: {
4375                         S390_LONG (code, ley, le, s390_f15, 0, 
4376                                    ins->inst_basereg, ins->inst_offset);
4377                         s390_ldebr (code, ins->dreg, s390_f15);
4378                 }
4379                         break;
4380                 case OP_ICONV_TO_R_UN: {
4381                         if (mono_hwcap_s390x_has_fpe) {
4382                                 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4383                         } else {
4384                                 s390_llgfr (code, s390_r0, ins->sreg1);
4385                                 s390_cdgbr (code, ins->dreg, s390_r0);
4386                         }
4387                 }
4388                         break;
4389                 case OP_LCONV_TO_R_UN: {
4390                         if (mono_hwcap_s390x_has_fpe) {
4391                                 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4392                         } else {
4393                                 short int *jump;
4394                                 s390_cxgbr (code, s390_f12, ins->sreg1);
4395                                 s390_ltgr  (code, ins->sreg1, ins->sreg1);
4396                                 s390_jnl   (code, 0); CODEPTR(code, jump);
4397                                 S390_SET   (code, s390_r13, 0x403f000000000000llu);
4398                                 s390_lgdr  (code, s390_f13, s390_r13);
4399                                 s390_lzdr  (code, s390_f15);
4400                                 s390_axbr  (code, s390_f12, s390_f13);
4401                                 PTRSLOT(code, jump);
4402                                 s390_ldxbr (code, s390_f13, s390_f12);
4403                                 s390_ldr   (code, ins->dreg, s390_f13);
4404                         }
4405                 }
4406                         break;
4407                 case OP_LCONV_TO_R4:
4408                 case OP_ICONV_TO_R4: {
4409                         s390_cegbr (code, ins->dreg, ins->sreg1);
4410                         s390_ldebr (code, ins->dreg, ins->dreg);
4411                 }
4412                         break;
4413                 case OP_LCONV_TO_R8:
4414                 case OP_ICONV_TO_R8: {
4415                         s390_cdgbr (code, ins->dreg, ins->sreg1);
4416                 }
4417                         break;
4418                 case OP_FCONV_TO_I1:
4419                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4420                         s390_ltgr  (code, ins->dreg, ins->dreg);
4421                         s390_jnl   (code, 4);
4422                         s390_oill  (code, ins->dreg, 0x80);
4423                         s390_lghi  (code, s390_r0, 0xff);
4424                         s390_ngr   (code, ins->dreg, s390_r0);
4425                         break;
4426                 case OP_FCONV_TO_U1:
4427                         if (mono_hwcap_s390x_has_fpe) {
4428                                 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4429                                 s390_lghi  (code, s390_r0, 0xff);
4430                                 s390_ngr   (code, ins->dreg, s390_r0);
4431                         } else {
4432                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4433                         }
4434                         break;
4435                 case OP_FCONV_TO_I2:
4436                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4437                         s390_ltgr  (code, ins->dreg, ins->dreg);
4438                         s390_jnl   (code, 4);
4439                         s390_oill  (code, ins->dreg, 0x8000);
4440                         s390_llill (code, s390_r0, 0xffff);
4441                         s390_ngr   (code, ins->dreg, s390_r0);
4442                         break;
4443                 case OP_FCONV_TO_U2:
4444                         if (mono_hwcap_s390x_has_fpe) {
4445                                 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4446                                 s390_llill  (code, s390_r0, 0xffff);
4447                                 s390_ngr    (code, ins->dreg, s390_r0);
4448                         } else {
4449                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4450                         }
4451                         break;
4452                 case OP_FCONV_TO_I4:
4453                 case OP_FCONV_TO_I:
4454                         s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4455                         break;
4456                 case OP_FCONV_TO_U4:
4457                 case OP_FCONV_TO_U:
4458                         if (mono_hwcap_s390x_has_fpe) {
4459                                 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4460                         } else {
4461                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4462                         }
4463                         break;
4464                 case OP_FCONV_TO_I8:
4465                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4466                         break;
4467                 case OP_FCONV_TO_U8:
4468                         if (mono_hwcap_s390x_has_fpe) {
4469                                 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4470                         } else {
4471                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4472                         }
4473                         break;
4474                 case OP_LCONV_TO_OVF_I: {
4475                         /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4476                         short int *o[5];
4477                         s390_ltgr (code, ins->sreg2, ins->sreg2);
4478                         s390_jnl  (code, 0); CODEPTR(code, o[0]);
4479                         s390_ltgr (code, ins->sreg1, ins->sreg1);
4480                         s390_jnl  (code, 0); CODEPTR(code, o[1]);
4481                         s390_lhi  (code, s390_r13, -1);
4482                         s390_cgr  (code, ins->sreg1, s390_r13);
4483                         s390_jnz  (code, 0); CODEPTR(code, o[2]);
4484                         if (ins->dreg != ins->sreg2)
4485                                 s390_lgr  (code, ins->dreg, ins->sreg2);
4486                         s390_j    (code, 0); CODEPTR(code, o[3]);
4487                         PTRSLOT(code, o[0]);
4488                         s390_jz   (code, 0); CODEPTR(code, o[4]);
4489                         PTRSLOT(code, o[1]);
4490                         PTRSLOT(code, o[2]);
4491                         mono_add_patch_info (cfg, code - cfg->native_code, 
4492                                              MONO_PATCH_INFO_EXC, "OverflowException");
4493                         s390_brasl (code, s390_r14, 0);
4494                         PTRSLOT(code, o[3]);
4495                         PTRSLOT(code, o[4]);
4496                 }
4497                         break;
4498                 case OP_ABS: {
4499                         s390_lpdbr (code, ins->dreg, ins->sreg1);
4500                 }
4501                         break;
4502                 case OP_SQRT: {
4503                         s390_sqdbr (code, ins->dreg, ins->sreg1);
4504                 }
4505                         break;
4506                 case OP_FADD: {
4507                         CHECK_SRCDST_COM_F;
4508                         s390_adbr (code, ins->dreg, src2);
4509                 }
4510                         break;
4511                 case OP_FSUB: {
4512                         CHECK_SRCDST_NCOM_F;
4513                         s390_sdbr (code, ins->dreg, src2);
4514                 }
4515                         break;          
4516                 case OP_FMUL: {
4517                         CHECK_SRCDST_COM_F;
4518                         s390_mdbr (code, ins->dreg, src2);
4519                 }
4520                         break;          
4521                 case OP_FDIV: {
4522                         CHECK_SRCDST_NCOM_F;
4523                         s390_ddbr (code, ins->dreg, src2);
4524                 }
4525                         break;          
4526                 case OP_FNEG: {
4527                         s390_lcdbr (code, ins->dreg, ins->sreg1);
4528                 }
4529                         break;          
4530                 case OP_FREM: {
4531                         CHECK_SRCDST_NCOM_F;
4532                         s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4533                 }
4534                         break;
4535                 case OP_FCOMPARE: {
4536                         s390_cdbr (code, ins->sreg1, ins->sreg2);
4537                 }
4538                         break;
4539                 case OP_FCEQ: {
4540                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4541                         s390_lghi  (code, ins->dreg, 1);
4542                         s390_je    (code, 4);
4543                         s390_lghi  (code, ins->dreg, 0);
4544                 }
4545                         break;
4546                 case OP_FCLT: {
4547                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4548                         s390_lghi  (code, ins->dreg, 1);
4549                         s390_jl    (code, 4);
4550                         s390_lghi  (code, ins->dreg, 0);
4551                 }
4552                         break;
4553                 case OP_FCLT_UN: {
4554                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4555                         s390_lghi  (code, ins->dreg, 1);
4556                         s390_jlo   (code, 4);
4557                         s390_lghi  (code, ins->dreg, 0);
4558                 }
4559                         break;
4560                 case OP_FCGT: {
4561                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4562                         s390_lghi  (code, ins->dreg, 1);
4563                         s390_jh    (code, 4);
4564                         s390_lghi  (code, ins->dreg, 0);
4565                 }
4566                         break;
4567                 case OP_FCGT_UN: {
4568                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4569                         s390_lghi  (code, ins->dreg, 1);
4570                         s390_jho   (code, 4);
4571                         s390_lghi  (code, ins->dreg, 0);
4572                 }
4573                         break;
4574                 case OP_FBEQ: {
4575                         short *o;
4576                         s390_jo (code, 0); CODEPTR(code, o);
4577                         EMIT_COND_BRANCH (ins, S390_CC_EQ);
4578                         PTRSLOT (code, o);
4579                 }
4580                         break;
4581                 case OP_FBNE_UN:
4582                         EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4583                         break;
4584                 case OP_FBLT: {
4585                         short *o;
4586                         s390_jo (code, 0); CODEPTR(code, o);
4587                         EMIT_COND_BRANCH (ins, S390_CC_LT);
4588                         PTRSLOT (code, o);
4589                 }
4590                         break;
4591                 case OP_FBLT_UN:
4592                         EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4593                         break;
4594                 case OP_FBGT: {
4595                         short *o;
4596                         s390_jo (code, 0); CODEPTR(code, o);
4597                         EMIT_COND_BRANCH (ins, S390_CC_GT);
4598                         PTRSLOT (code, o);
4599                 }
4600                         break;
4601                 case OP_FBGT_UN:
4602                         EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4603                         break;
4604                 case OP_FBGE: {
4605                         short *o;
4606                         s390_jo (code, 0); CODEPTR(code, o);
4607                         EMIT_COND_BRANCH (ins, S390_CC_GE);
4608                         PTRSLOT (code, o);
4609                 }
4610                         break;
4611                 case OP_FBGE_UN:
4612                         EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4613                         break;
4614                 case OP_FBLE: {
4615                         short *o;
4616                         s390_jo (code, 0); CODEPTR(code, o);
4617                         EMIT_COND_BRANCH (ins, S390_CC_LE);
4618                         PTRSLOT (code, o);
4619                 }
4620                         break;
4621                 case OP_FBLE_UN:
4622                         EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4623                         break;
4624                 case OP_CKFINITE: {
4625                         short *o;
4626                         s390_lhi  (code, s390_r13, 0x7f);
4627                         s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4628                         s390_jz   (code, 0); CODEPTR(code, o);
4629                         mono_add_patch_info (cfg, code - cfg->native_code, 
4630                                              MONO_PATCH_INFO_EXC, "OverflowException");
4631                         s390_brasl (code, s390_r14,0);
4632                         PTRSLOT(code, o);
4633                 }
4634                         break;
4635                 case OP_S390_MOVE: {
4636                         if (ins->backend.size > 0) {
4637                                 if (ins->backend.size <= 256) {
4638                                         s390_mvc  (code, ins->backend.size, ins->dreg, 
4639                                                    ins->inst_offset, ins->sreg1, ins->inst_imm);
4640                                 } else {
4641                                         s390_lgr  (code, s390_r0, ins->dreg);
4642                                         if (ins->inst_offset > 0) {
4643                                                 if (s390_is_imm16 (ins->inst_offset)) {
4644                                                         s390_aghi (code, s390_r0, ins->inst_offset);
4645                                                 } else if (s390_is_imm32 (ins->inst_offset)) {
4646                                                         s390_agfi (code, s390_r0, ins->inst_offset);
4647                                                 } else {
4648                                                         S390_SET  (code, s390_r13, ins->inst_offset);
4649                                                         s390_agr  (code, s390_r0, s390_r13);
4650                                                 }
4651                                         }
4652                                         s390_lgr  (code, s390_r12, ins->sreg1);
4653                                         if (ins->inst_imm > 0) {
4654                                                 if (s390_is_imm16 (ins->inst_imm)) {
4655                                                         s390_aghi (code, s390_r12, ins->inst_imm);
4656                                                 } else if (s390_is_imm32 (ins->inst_imm)) {
4657                                                         s390_agfi (code, s390_r12, ins->inst_imm);
4658                                                 } else {
4659                                                         S390_SET  (code, s390_r13, ins->inst_imm);
4660                                                         s390_agr  (code, s390_r12, s390_r13);
4661                                                 }
4662                                         }
4663                                         if (s390_is_imm16 (ins->backend.size)) {
4664                                                 s390_lghi (code, s390_r1, ins->backend.size);
4665                                         } else if (s390_is_imm32 (ins->inst_offset)) {
4666                                                 s390_agfi (code, s390_r1, ins->backend.size);
4667                                         } else {
4668                                                 S390_SET  (code, s390_r13, ins->backend.size);
4669                                                 s390_agr  (code, s390_r1, s390_r13);
4670                                         }
4671                                         s390_lgr  (code, s390_r13, s390_r1);
4672                                         s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4673                                         s390_jo   (code, -2);
4674                                 }
4675                         }
4676                 }
4677                         break;
4678                 case OP_ATOMIC_ADD_I8: {
4679                         s390_lgr (code, s390_r1, ins->sreg2);
4680                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4681                         s390_agr (code, s390_r1, s390_r0);
4682                         s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4683                         s390_jnz (code, -10);
4684                         s390_lgr (code, ins->dreg, s390_r1);
4685                 }
4686                         break;  
4687                 case OP_ATOMIC_EXCHANGE_I8: {
4688                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4689                         s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4690                         s390_jnz (code, -6);
4691                         s390_lgr (code, ins->dreg, s390_r0);
4692                 }
4693                         break;  
4694                 case OP_ATOMIC_ADD_I4: {
4695                         s390_lgfr(code, s390_r1, ins->sreg2);
4696                         s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4697                         s390_agr (code, s390_r1, s390_r0);
4698                         s390_cs  (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4699                         s390_jnz (code, -9);
4700                         s390_lgfr(code, ins->dreg, s390_r1);
4701                 }
4702                         break;  
4703                 case OP_ATOMIC_EXCHANGE_I4: {
4704                         s390_l   (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4705                         s390_cs  (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4706                         s390_jnz (code, -4);
4707                         s390_lgfr(code, ins->dreg, s390_r0);
4708                 }
4709                         break;  
4710                 case OP_S390_BKCHAIN: {
4711                         s390_lgr  (code, ins->dreg, ins->sreg1);
4712                         if (s390_is_imm16 (cfg->stack_offset)) {
4713                                 s390_aghi (code, ins->dreg, cfg->stack_offset);
4714                         } else if (s390_is_imm32 (cfg->stack_offset)) {
4715                                 s390_agfi (code, ins->dreg, cfg->stack_offset);
4716                         } else {
4717                                 S390_SET  (code, s390_r13, cfg->stack_offset);
4718                                 s390_agr  (code, ins->dreg, s390_r13);
4719                         }
4720                 }
4721                         break;  
4722                 case OP_MEMORY_BARRIER:
4723                         s390_mem (code);
4724                         break;
4725                 case OP_GC_SAFE_POINT: {
4726                         guint8 *br;
4727
4728                         g_assert (mono_threads_is_coop_enabled ());
4729
4730                         s390_chi (code, ins->sreg1, 1); 
4731                         s390_je  (code, 0); CODEPTR(code, br);
4732                         mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4733                                              mono_threads_state_poll);
4734                         S390_CALL_TEMPLATE (code, s390_r14);
4735                         PTRSLOT (code, br);
4736                         break;
4737                 }
4738                 case OP_GC_LIVENESS_DEF:
4739                 case OP_GC_LIVENESS_USE:
4740                 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4741                         ins->backend.pc_offset = code - cfg->native_code;
4742                         break;
4743                 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4744                         ins->backend.pc_offset = code - cfg->native_code;
4745                         bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4746                         break;
4747 #ifdef MONO_ARCH_SIMD_INTRINSICS
4748                 case OP_ADDPS:
4749                         s390x_addps (code, ins->sreg1, ins->sreg2);
4750                         break;
4751                 case OP_DIVPS:
4752                         s390x_divps (code, ins->sreg1, ins->sreg2);
4753                         break;
4754                 case OP_MULPS:
4755                         s390x_mulps (code, ins->sreg1, ins->sreg2);
4756                         break;
4757                 case OP_SUBPS:
4758                         s390x_subps (code, ins->sreg1, ins->sreg2);
4759                         break;
4760                 case OP_MAXPS:
4761                         s390x_maxps (code, ins->sreg1, ins->sreg2);
4762                         break;
4763                 case OP_MINPS:
4764                         s390x_minps (code, ins->sreg1, ins->sreg2);
4765                         break;
4766                 case OP_COMPPS:
4767                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4768                         s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4769                         break;
4770                 case OP_ANDPS:
4771                         s390x_andps (code, ins->sreg1, ins->sreg2);
4772                         break;
4773                 case OP_ANDNPS:
4774                         s390x_andnps (code, ins->sreg1, ins->sreg2);
4775                         break;
4776                 case OP_ORPS:
4777                         s390x_orps (code, ins->sreg1, ins->sreg2);
4778                         break;
4779                 case OP_XORPS:
4780                         s390x_xorps (code, ins->sreg1, ins->sreg2);
4781                         break;
4782                 case OP_SQRTPS:
4783                         s390x_sqrtps (code, ins->dreg, ins->sreg1);
4784                         break;
4785                 case OP_RSQRTPS:
4786                         s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4787                         break;
4788                 case OP_RCPPS:
4789                         s390x_rcpps (code, ins->dreg, ins->sreg1);
4790                         break;
4791                 case OP_ADDSUBPS:
4792                         s390x_addsubps (code, ins->sreg1, ins->sreg2);
4793                         break;
4794                 case OP_HADDPS:
4795                         s390x_haddps (code, ins->sreg1, ins->sreg2);
4796                         break;
4797                 case OP_HSUBPS:
4798                         s390x_hsubps (code, ins->sreg1, ins->sreg2);
4799                         break;
4800                 case OP_DUPPS_HIGH:
4801                         s390x_movshdup (code, ins->dreg, ins->sreg1);
4802                         break;
4803                 case OP_DUPPS_LOW:
4804                         s390x_movsldup (code, ins->dreg, ins->sreg1);
4805                         break;
4806
4807                 case OP_PSHUFLEW_HIGH:
4808                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4809                         s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4810                         break;
4811                 case OP_PSHUFLEW_LOW:
4812                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4813                         s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4814                         break;
4815                 case OP_PSHUFLED:
4816                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4817                         s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4818                         break;
4819                 case OP_SHUFPS:
4820                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4821                         s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4822                         break;
4823                 case OP_SHUFPD:
4824                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4825                         s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4826                         break;
4827
4828                 case OP_ADDPD:
4829                         s390x_addpd (code, ins->sreg1, ins->sreg2);
4830                         break;
4831                 case OP_DIVPD:
4832                         s390x_divpd (code, ins->sreg1, ins->sreg2);
4833                         break;
4834                 case OP_MULPD:
4835                         s390x_mulpd (code, ins->sreg1, ins->sreg2);
4836                         break;
4837                 case OP_SUBPD:
4838                         s390x_subpd (code, ins->sreg1, ins->sreg2);
4839                         break;
4840                 case OP_MAXPD:
4841                         s390x_maxpd (code, ins->sreg1, ins->sreg2);
4842                         break;
4843                 case OP_MINPD:
4844                         s390x_minpd (code, ins->sreg1, ins->sreg2);
4845                         break;
4846                 case OP_COMPPD:
4847                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4848                         s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4849                         break;
4850                 case OP_ANDPD:
4851                         s390x_andpd (code, ins->sreg1, ins->sreg2);
4852                         break;
4853                 case OP_ANDNPD:
4854                         s390x_andnpd (code, ins->sreg1, ins->sreg2);
4855                         break;
4856                 case OP_ORPD:
4857                         s390x_orpd (code, ins->sreg1, ins->sreg2);
4858                         break;
4859                 case OP_XORPD:
4860                         s390x_xorpd (code, ins->sreg1, ins->sreg2);
4861                         break;
4862                 case OP_SQRTPD:
4863                         s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4864                         break;
4865                 case OP_ADDSUBPD:
4866                         s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4867                         break;
4868                 case OP_HADDPD:
4869                         s390x_haddpd (code, ins->sreg1, ins->sreg2);
4870                         break;
4871                 case OP_HSUBPD:
4872                         s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4873                         break;
4874                 case OP_DUPPD:
4875                         s390x_movddup (code, ins->dreg, ins->sreg1);
4876                         break;
4877
4878                 case OP_EXTRACT_MASK:
4879                         s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4880                         break;
4881
4882                 case OP_PAND:
4883                         s390x_pand (code, ins->sreg1, ins->sreg2);
4884                         break;
4885                 case OP_POR:
4886                         s390x_por (code, ins->sreg1, ins->sreg2);
4887                         break;
4888                 case OP_PXOR:
4889                         s390x_pxor (code, ins->sreg1, ins->sreg2);
4890                         break;
4891
4892                 case OP_PADDB:
4893                         s390x_paddb (code, ins->sreg1, ins->sreg2);
4894                         break;
4895                 case OP_PADDW:
4896                         s390x_paddw (code, ins->sreg1, ins->sreg2);
4897                         break;
4898                 case OP_PADDD:
4899                         s390x_paddd (code, ins->sreg1, ins->sreg2);
4900                         break;
4901                 case OP_PADDQ:
4902                         s390x_paddq (code, ins->sreg1, ins->sreg2);
4903                         break;
4904
4905                 case OP_PSUBB:
4906                         s390x_psubb (code, ins->sreg1, ins->sreg2);
4907                         break;
4908                 case OP_PSUBW:
4909                         s390x_psubw (code, ins->sreg1, ins->sreg2);
4910                         break;
4911                 case OP_PSUBD:
4912                         s390x_psubd (code, ins->sreg1, ins->sreg2);
4913                         break;
4914                 case OP_PSUBQ:
4915                         s390x_psubq (code, ins->sreg1, ins->sreg2);
4916                         break;
4917
4918                 case OP_PMAXB_UN:
4919                         s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4920                         break;
4921                 case OP_PMAXW_UN:
4922                         s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4923                         break;
4924                 case OP_PMAXD_UN:
4925                         s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4926                         break;
4927                 
4928                 case OP_PMAXB:
4929                         s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4930                         break;
4931                 case OP_PMAXW:
4932                         s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4933                         break;
4934                 case OP_PMAXD:
4935                         s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4936                         break;
4937
4938                 case OP_PAVGB_UN:
4939                         s390x_pavgb (code, ins->sreg1, ins->sreg2);
4940                         break;
4941                 case OP_PAVGW_UN:
4942                         s390x_pavgw (code, ins->sreg1, ins->sreg2);
4943                         break;
4944
4945                 case OP_PMINB_UN:
4946                         s390x_pminub (code, ins->sreg1, ins->sreg2);
4947                         break;
4948                 case OP_PMINW_UN:
4949                         s390x_pminuw (code, ins->sreg1, ins->sreg2);
4950                         break;
4951                 case OP_PMIND_UN:
4952                         s390x_pminud (code, ins->sreg1, ins->sreg2);
4953                         break;
4954
4955                 case OP_PMINB:
4956                         s390x_pminsb (code, ins->sreg1, ins->sreg2);
4957                         break;
4958                 case OP_PMINW:
4959                         s390x_pminsw (code, ins->sreg1, ins->sreg2);
4960                         break;
4961                 case OP_PMIND:
4962                         s390x_pminsd (code, ins->sreg1, ins->sreg2);
4963                         break;
4964
4965                 case OP_PCMPEQB:
4966                         s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4967                         break;
4968                 case OP_PCMPEQW:
4969                         s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4970                         break;
4971                 case OP_PCMPEQD:
4972                         s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4973                         break;
4974                 case OP_PCMPEQQ:
4975                         s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4976                         break;
4977
4978                 case OP_PCMPGTB:
4979                         s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4980                         break;
4981                 case OP_PCMPGTW:
4982                         s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4983                         break;
4984                 case OP_PCMPGTD:
4985                         s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4986                         break;
4987                 case OP_PCMPGTQ:
4988                         s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4989                         break;
4990
4991                 case OP_PSUM_ABS_DIFF:
4992                         s390x_psadbw (code, ins->sreg1, ins->sreg2);
4993                         break;
4994
4995                 case OP_UNPACK_LOWB:
4996                         s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4997                         break;
4998                 case OP_UNPACK_LOWW:
4999                         s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5000                         break;
5001                 case OP_UNPACK_LOWD:
5002                         s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5003                         break;
5004                 case OP_UNPACK_LOWQ:
5005                         s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5006                         break;
5007                 case OP_UNPACK_LOWPS:
5008                         s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5009                         break;
5010                 case OP_UNPACK_LOWPD:
5011                         s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5012                         break;
5013
5014                 case OP_UNPACK_HIGHB:
5015                         s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5016                         break;
5017                 case OP_UNPACK_HIGHW:
5018                         s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5019                         break;
5020                 case OP_UNPACK_HIGHD:
5021                         s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5022                         break;
5023                 case OP_UNPACK_HIGHQ:
5024                         s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5025                         break;
5026                 case OP_UNPACK_HIGHPS:
5027                         s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5028                         break;
5029                 case OP_UNPACK_HIGHPD:
5030                         s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5031                         break;
5032
5033                 case OP_PACKW:
5034                         s390x_packsswb (code, ins->sreg1, ins->sreg2);
5035                         break;
5036                 case OP_PACKD:
5037                         s390x_packssdw (code, ins->sreg1, ins->sreg2);
5038                         break;
5039                 case OP_PACKW_UN:
5040                         s390x_packuswb (code, ins->sreg1, ins->sreg2);
5041                         break;
5042                 case OP_PACKD_UN:
5043                         s390x_packusdw (code, ins->sreg1, ins->sreg2);
5044                         break;
5045
5046                 case OP_PADDB_SAT_UN:
5047                         s390x_paddusb (code, ins->sreg1, ins->sreg2);
5048                         break;
5049                 case OP_PSUBB_SAT_UN:
5050                         s390x_psubusb (code, ins->sreg1, ins->sreg2);
5051                         break;
5052                 case OP_PADDW_SAT_UN:
5053                         s390x_paddusw (code, ins->sreg1, ins->sreg2);
5054                         break;
5055                 case OP_PSUBW_SAT_UN:
5056                         s390x_psubusw (code, ins->sreg1, ins->sreg2);
5057                         break;
5058
5059                 case OP_PADDB_SAT:
5060                         s390x_paddsb (code, ins->sreg1, ins->sreg2);
5061                         break;
5062                 case OP_PSUBB_SAT:
5063                         s390x_psubsb (code, ins->sreg1, ins->sreg2);
5064                         break;
5065                 case OP_PADDW_SAT:
5066                         s390x_paddsw (code, ins->sreg1, ins->sreg2);
5067                         break;
5068                 case OP_PSUBW_SAT:
5069                         s390x_psubsw (code, ins->sreg1, ins->sreg2);
5070                         break;
5071                         
5072                 case OP_PMULW:
5073                         s390x_pmullw (code, ins->sreg1, ins->sreg2);
5074                         break;
5075                 case OP_PMULD:
5076                         s390x_pmulld (code, ins->sreg1, ins->sreg2);
5077                         break;
5078                 case OP_PMULQ:
5079                         s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5080                         break;
5081                 case OP_PMULW_HIGH_UN:
5082                         s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5083                         break;
5084                 case OP_PMULW_HIGH:
5085                         s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5086                         break;
5087
5088                 case OP_PSHRW:
5089                         s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5090                         break;
5091                 case OP_PSHRW_REG:
5092                         s390x_psrlw (code, ins->dreg, ins->sreg2);
5093                         break;
5094
5095                 case OP_PSARW:
5096                         s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5097                         break;
5098                 case OP_PSARW_REG:
5099                         s390x_psraw (code, ins->dreg, ins->sreg2);
5100                         break;
5101
5102                 case OP_PSHLW:
5103                         s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5104                         break;
5105                 case OP_PSHLW_REG:
5106                         s390x_psllw (code, ins->dreg, ins->sreg2);
5107                         break;
5108
5109                 case OP_PSHRD:
5110                         s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5111                         break;
5112                 case OP_PSHRD_REG:
5113                         s390x_psrld (code, ins->dreg, ins->sreg2);
5114                         break;
5115
5116                 case OP_PSARD:
5117                         s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5118                         break;
5119                 case OP_PSARD_REG:
5120                         s390x_psrad (code, ins->dreg, ins->sreg2);
5121                         break;
5122
5123                 case OP_PSHLD:
5124                         s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5125                         break;
5126                 case OP_PSHLD_REG:
5127                         s390x_pslld (code, ins->dreg, ins->sreg2);
5128                         break;
5129
5130                 case OP_PSHRQ:
5131                         s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5132                         break;
5133                 case OP_PSHRQ_REG:
5134                         s390x_psrlq (code, ins->dreg, ins->sreg2);
5135                         break;
5136                 
5137                 /*TODO: This is appart of the sse spec but not added
5138                 case OP_PSARQ:
5139                         s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5140                         break;
5141                 case OP_PSARQ_REG:
5142                         s390x_psraq (code, ins->dreg, ins->sreg2);
5143                         break;  
5144                 */
5145         
5146                 case OP_PSHLQ:
5147                         s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5148                         break;
5149                 case OP_PSHLQ_REG:
5150                         s390x_psllq (code, ins->dreg, ins->sreg2);
5151                         break;  
5152                 case OP_CVTDQ2PD:
5153                         s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5154                         break;
5155                 case OP_CVTDQ2PS:
5156                         s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5157                         break;
5158                 case OP_CVTPD2DQ:
5159                         s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5160                         break;
5161                 case OP_CVTPD2PS:
5162                         s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5163                         break;
5164                 case OP_CVTPS2DQ:
5165                         s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5166                         break;
5167                 case OP_CVTPS2PD:
5168                         s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5169                         break;
5170                 case OP_CVTTPD2DQ:
5171                         s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5172                         break;
5173                 case OP_CVTTPS2DQ:
5174                         s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5175                         break;
5176
5177                 case OP_ICONV_TO_X:
5178                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5179                         break;
5180                 case OP_EXTRACT_I4:
5181                         amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5182                         break;
5183                 case OP_EXTRACT_I8:
5184                         if (ins->inst_c0) {
5185                                 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5186                                 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5187                         } else {
5188                                 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5189                         }
5190                         break;
5191                 case OP_EXTRACT_I1:
5192                 case OP_EXTRACT_U1:
5193                         amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5194                         if (ins->inst_c0)
5195                                 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5196                         amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5197                         break;
5198                 case OP_EXTRACT_I2:
5199                 case OP_EXTRACT_U2:
5200                         /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5201                         if (ins->inst_c0)
5202                                 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5203                         s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5204                         amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5205                         break;
5206                 case OP_EXTRACT_R8:
5207                         if (ins->inst_c0)
5208                                 amd64_movhlps (code, ins->dreg, ins->sreg1);
5209                         else
5210                                 s390x_movsd (code, ins->dreg, ins->sreg1);
5211                         break;
5212                 case OP_INSERT_I2:
5213                         s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5214                         break;
5215                 case OP_EXTRACTX_U2:
5216                         s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5217                         break;
5218                 case OP_INSERTX_U1_SLOW:
5219                         /*sreg1 is the extracted ireg (scratch)
5220                         /sreg2 is the to be inserted ireg (scratch)
5221                         /dreg is the xreg to receive the value*/
5222
5223                         /*clear the bits from the extracted word*/
5224                         amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5225                         /*shift the value to insert if needed*/
5226                         if (ins->inst_c0 & 1)
5227                                 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5228                         /*join them together*/
5229                         amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5230                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5231                         break;
5232                 case OP_INSERTX_I4_SLOW:
5233                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5234                         amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5235                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5236                         break;
5237                 case OP_INSERTX_I8_SLOW:
5238                         amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5239                         if (ins->inst_c0)
5240                                 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5241                         else
5242                                 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5243                         break;
5244
5245                 case OP_INSERTX_R4_SLOW:
5246                         switch (ins->inst_c0) {
5247                         case 0:
5248                                 if (cfg->r4fp)
5249                                         s390x_movss (code, ins->dreg, ins->sreg2);
5250                                 else
5251                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5252                                 break;
5253                         case 1:
5254                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5255                                 if (cfg->r4fp)
5256                                         s390x_movss (code, ins->dreg, ins->sreg2);
5257                                 else
5258                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5259                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5260                                 break;
5261                         case 2:
5262                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5263                                 if (cfg->r4fp)
5264                                         s390x_movss (code, ins->dreg, ins->sreg2);
5265                                 else
5266                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5267                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5268                                 break;
5269                         case 3:
5270                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5271                                 if (cfg->r4fp)
5272                                         s390x_movss (code, ins->dreg, ins->sreg2);
5273                                 else
5274                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5275                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5276                                 break;
5277                         }
5278                         break;
5279                 case OP_INSERTX_R8_SLOW:
5280                         if (ins->inst_c0)
5281                                 amd64_movlhps (code, ins->dreg, ins->sreg2);
5282                         else
5283                                 s390x_movsd (code, ins->dreg, ins->sreg2);
5284                         break;
5285                 case OP_STOREX_MEMBASE_REG:
5286                 case OP_STOREX_MEMBASE:
5287                         s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5288                         break;
5289                 case OP_LOADX_MEMBASE:
5290                         s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5291                         break;
5292                 case OP_LOADX_ALIGNED_MEMBASE:
5293                         s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5294                         break;
5295                 case OP_STOREX_ALIGNED_MEMBASE_REG:
5296                         s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5297                         break;
5298                 case OP_STOREX_NTA_MEMBASE_REG:
5299                         s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5300                         break;
5301                 case OP_PREFETCH_MEMBASE:
5302                         s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5303                         break;
5304
5305                 case OP_XMOVE:
5306                         /*FIXME the peephole pass should have killed this*/
5307                         if (ins->dreg != ins->sreg1)
5308                                 s390x_movaps (code, ins->dreg, ins->sreg1);
5309                         break;          
5310                 case OP_XZERO:
5311                         s390x_pxor (code, ins->dreg, ins->dreg);
5312                         break;
5313                 case OP_ICONV_TO_R4_RAW:
5314                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5315                         break;
5316
5317                 case OP_FCONV_TO_R8_X:
5318                         s390x_movsd (code, ins->dreg, ins->sreg1);
5319                         break;
5320
5321                 case OP_XCONV_R8_TO_I4:
5322                         s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5323                         switch (ins->backend.source_opcode) {
5324                         case OP_FCONV_TO_I1:
5325                                 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5326                                 break;
5327                         case OP_FCONV_TO_U1:
5328                                 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5329                                 break;
5330                         case OP_FCONV_TO_I2:
5331                                 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5332                                 break;
5333                         case OP_FCONV_TO_U2:
5334                                 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5335                                 break;
5336                         }                       
5337                         break;
5338
5339                 case OP_EXPAND_I2:
5340                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5341                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5342                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5343                         break;
5344                 case OP_EXPAND_I4:
5345                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5346                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5347                         break;
5348                 case OP_EXPAND_I8:
5349                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5350                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5351                         break;
5352                 case OP_EXPAND_R4:
5353                         if (cfg->r4fp) {
5354                                 s390x_movsd (code, ins->dreg, ins->sreg1);
5355                         } else {
5356                                 s390x_movsd (code, ins->dreg, ins->sreg1);
5357                                 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5358                         }
5359                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5360                         break;
5361                 case OP_EXPAND_R8:
5362                         s390x_movsd (code, ins->dreg, ins->sreg1);
5363                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5364                         break;
5365 #endif
5366                 default:
5367                         g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5368                         g_assert_not_reached ();
5369                 }
5370
5371                 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5372                         g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5373                                    mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5374                         g_assert_not_reached ();
5375                 }
5376                
5377                 last_offset = offset;
5378         }
5379
5380         cfg->code_len = code - cfg->native_code;
5381 }
5382
5383 /*========================= End of Function ========================*/
5384
5385 /*------------------------------------------------------------------*/
5386 /*                                                                  */
5387 /* Name         - mono_arch_register_lowlevel_calls                 */
5388 /*                                                                  */
5389 /* Function     - Register routines to help with --trace operation. */
5390 /*                                                                  */
5391 /*------------------------------------------------------------------*/
5392
5393 void
5394 mono_arch_register_lowlevel_calls (void)
5395 {
5396 }
5397
5398 /*========================= End of Function ========================*/
5399
5400 /*------------------------------------------------------------------*/
5401 /*                                                                  */
5402 /* Name         - mono_arch_patch_code                              */
5403 /*                                                                  */
5404 /* Function     - Process the patch data created during the         */
5405 /*                instruction build process. This resolves jumps,   */
5406 /*                calls, variables etc.                             */
5407 /*                                                                  */
5408 /*------------------------------------------------------------------*/
5409
5410 void
5411 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, 
5412                       guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5413                       MonoError *error)
5414 {
5415         MonoJumpInfo *patch_info;
5416
5417         error_init (error);
5418
5419         for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5420                 unsigned char *ip = patch_info->ip.i + code;
5421                 gconstpointer target = NULL;
5422
5423                 target = mono_resolve_patch_target (method, domain, code, 
5424                                                                                         patch_info, run_cctors, error);
5425                 return_if_nok (error);
5426
5427                 switch (patch_info->type) {
5428                         case MONO_PATCH_INFO_IP:
5429                         case MONO_PATCH_INFO_LDSTR:
5430                         case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
5431                         case MONO_PATCH_INFO_LDTOKEN: 
5432                         case MONO_PATCH_INFO_EXC:
5433                                 s390_patch_addr (ip, (guint64) target);
5434                                 continue;
5435                         case MONO_PATCH_INFO_METHOD:
5436                         case MONO_PATCH_INFO_INTERNAL_METHOD:
5437                         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5438                         case MONO_PATCH_INFO_RGCTX_FETCH:
5439                         case MONO_PATCH_INFO_ABS: {
5440                                 S390_EMIT_CALL (ip, target);
5441                                 continue;
5442                         }
5443                         case MONO_PATCH_INFO_SWITCH: 
5444                                 /*----------------------------------*/
5445                                 /* ip points at the basr r13,0/j +4 */
5446                                 /* instruction the vtable value     */
5447                                 /* follows this (i.e. ip+6)         */
5448                                 /*----------------------------------*/
5449                                 S390_EMIT_LOAD (ip, target);
5450                                 continue;
5451                         case MONO_PATCH_INFO_METHODCONST:
5452                         case MONO_PATCH_INFO_CLASS:
5453                         case MONO_PATCH_INFO_IMAGE:
5454                         case MONO_PATCH_INFO_FIELD:
5455                         case MONO_PATCH_INFO_IID:
5456                         case MONO_PATCH_INFO_EXC_NAME:
5457                                 target = S390_RELATIVE(target, ip);
5458                                 s390_patch_rel (ip, (guint64) target);
5459                                 continue;
5460                         case MONO_PATCH_INFO_R4:
5461                         case MONO_PATCH_INFO_R8:
5462                         case MONO_PATCH_INFO_METHOD_REL:
5463                                 g_assert_not_reached ();
5464                                 continue;
5465                         default:
5466                                 target = S390_RELATIVE(target, ip);
5467                                 ip += 2;
5468                                 s390_patch_rel (ip, (guint64) target);
5469                 }
5470         }
5471 }
5472
5473 /*========================= End of Function ========================*/
5474
5475 /*------------------------------------------------------------------*/
5476 /*                                                                  */
5477 /* Name         - emit_load_volatile_arguments                      */
5478 /*                                                                  */
5479 /* Function     - Emit the instructions to reload parameter regist- */
5480 /*                registers for use with "tail" operations.         */
5481 /*                                                                  */
5482 /*                The register loading operations performed here    */
5483 /*                are the mirror of the store operations performed  */
5484 /*                in mono_arch_emit_prolog and need to be kept in   */
5485 /*                synchronization with it.                          */
5486 /*                                                                  */
5487 /*------------------------------------------------------------------*/
5488
5489 guint8 *
5490 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5491 {
5492         MonoInst *inst;
5493         MonoMethod *method = cfg->method;
5494         MonoMethodSignature *sig = mono_method_signature(method);
5495         int pos = 0, i;
5496         CallInfo *cinfo;
5497
5498         cinfo = get_call_info (NULL, NULL, sig);
5499
5500         if (cinfo->struct_ret) {
5501                 ArgInfo *ainfo = &cinfo->ret;
5502                 inst         = cfg->vret_addr;
5503                 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5504         }
5505
5506         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5507                 ArgInfo *ainfo = cinfo->args + i;
5508                 inst = cfg->args [pos];
5509
5510                 if (inst->opcode == OP_REGVAR) {
5511                         if (ainfo->regtype == RegTypeGeneral)
5512                                 s390_lgr (code, ainfo->reg, inst->dreg);
5513                         else if (ainfo->regtype == RegTypeFP) {
5514                                 if (inst->dreg != ainfo->reg) {
5515                                         if (ainfo->size == 4) {
5516                                                 s390_ldebr (code, ainfo->reg, inst->dreg);
5517                                         } else {
5518                                                 s390_ldr   (code, ainfo->reg, inst->dreg);
5519                                         }
5520                                 }
5521                         }
5522                         else if (ainfo->regtype == RegTypeBase) {
5523                         } else
5524                                 g_assert_not_reached ();
5525                 } else {
5526                         if (ainfo->regtype == RegTypeGeneral) {
5527                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5528                                         g_assert_not_reached();
5529                                 switch (ainfo->size) {
5530                                 case 1:
5531                                         s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532                                         break;
5533                                 case 2:
5534                                         s390_lgh  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5535                                         break;
5536                                 case 4: 
5537                                         s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538                                         break;
5539                                 case 8:
5540                                         s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5541                                         break;
5542                                 }
5543                         } else if (ainfo->regtype == RegTypeBase) {
5544                         } else if (ainfo->regtype == RegTypeFP) {
5545                                 if (ainfo->size == 8)
5546                                         s390_ld  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5547                                 else if (ainfo->size == 4)
5548                                         s390_le  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5549                                 else
5550                                         g_assert_not_reached ();
5551                         } else if (ainfo->regtype == RegTypeStructByVal) {
5552                                 if (ainfo->reg != STK_BASE) {
5553                                         switch (ainfo->size) {
5554                                         case 1:
5555                                                 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5556                                                 break;
5557                                         case 2:
5558                                                 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5559                                                 break;
5560                                         case 4:
5561                                                 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5562                                                 break;
5563                                         case 8:
5564                                                 s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5565                                                 break;
5566                                         }
5567                                 }
5568                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5569                                 if (ainfo->reg != STK_BASE) {
5570                                         s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5571                                 }
5572                         } else
5573                                 g_assert_not_reached ();
5574                 }
5575                 pos++;
5576         }
5577
5578         return code;
5579 }
5580
5581 /*========================= End of Function ========================*/
5582
5583 /*------------------------------------------------------------------*/
5584 /*                                                                  */
5585 /* Name         - mono_arch_emit_prolog                             */
5586 /*                                                                  */
5587 /* Function     - Create the instruction sequence for a function    */
5588 /*                prolog.                                           */
5589 /*                                                                  */
5590 /*------------------------------------------------------------------*/
5591
5592 guint8 *
5593 mono_arch_emit_prolog (MonoCompile *cfg)
5594 {
5595         MonoMethod *method = cfg->method;
5596         MonoBasicBlock *bb;
5597         MonoMethodSignature *sig;
5598         MonoInst *inst;
5599         long alloc_size, pos, max_offset, i, cfa_offset = 0;
5600         guint8 *code;
5601         guint32 size;
5602         CallInfo *cinfo;
5603         int tracing = 0,
5604             argsClobbered = 0,
5605             lmfOffset,
5606             fpOffset;
5607
5608         cfg->code_size   = 512;
5609
5610         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5611                 tracing         = 1;
5612                 cfg->code_size += 256;
5613         }
5614
5615         if (method->save_lmf)
5616                 cfg->code_size += 200;
5617
5618         cfg->native_code = code = g_malloc (cfg->code_size);
5619
5620         mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5621         emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5622         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5623         mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5624         mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5625
5626         if (cfg->arch.bkchain_reg != -1)
5627                 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5628
5629         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5630                 cfg->used_int_regs |= 1 << 11;
5631         }
5632
5633         alloc_size = cfg->stack_offset;
5634
5635         cfg->stack_usage = cfa_offset = alloc_size;
5636         mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5637         s390_lgr  (code, s390_r11, STK_BASE);
5638         if (s390_is_imm16 (alloc_size)) {
5639                 s390_aghi (code, STK_BASE, -alloc_size);
5640         } else if (s390_is_imm32 (alloc_size)) { 
5641                 s390_agfi (code, STK_BASE, -alloc_size);
5642         } else {
5643                 int stackSize = alloc_size;
5644                 while (stackSize > INT_MAX) {
5645                         s390_agfi (code, STK_BASE, -INT_MAX);
5646                         stackSize -= INT_MAX;
5647                 }
5648                 s390_agfi (code, STK_BASE, -stackSize);
5649         }
5650         s390_stg  (code, s390_r11, 0, STK_BASE, 0);
5651
5652         if (cfg->frame_reg != STK_BASE)
5653                 s390_lgr (code, s390_r11, STK_BASE);
5654
5655         mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5656
5657         /* store runtime generic context */
5658         if (cfg->rgctx_var) {
5659                 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5660
5661                 s390_stg  (code, MONO_ARCH_RGCTX_REG, 0, 
5662                            cfg->rgctx_var->inst_basereg, 
5663                            cfg->rgctx_var->inst_offset);
5664         }
5665
5666         /* compute max_offset in order to use short forward jumps
5667          * we always do it on s390 because the immediate displacement
5668          * for jumps is too small 
5669          */
5670         max_offset = 0;
5671         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5672                 MonoInst *ins;
5673                 bb->max_offset = max_offset;
5674
5675                 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5676                         max_offset += 6; 
5677
5678                 MONO_BB_FOR_EACH_INS (bb, ins)
5679                         max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5680         }
5681
5682         /* load arguments allocated to register from the stack */
5683         sig = mono_method_signature (method);
5684         pos = 0;
5685
5686         cinfo = get_call_info (cfg, cfg->mempool, sig);
5687
5688         if (cinfo->struct_ret) {
5689                 ArgInfo *ainfo     = &cinfo->ret;
5690                 inst               = cfg->vret_addr;
5691                 inst->backend.size = ainfo->vtsize;
5692                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5693         }
5694
5695         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5696                 ArgInfo *ainfo = cinfo->args + i;
5697                 inst = cfg->args [pos];
5698                 
5699                 if (inst->opcode == OP_VTARG_ADDR)
5700                         inst = inst->inst_left;
5701
5702                 if (inst->opcode == OP_REGVAR) {
5703                         if (ainfo->regtype == RegTypeGeneral)
5704                                 s390_lgr (code, inst->dreg, ainfo->reg);
5705                         else if (ainfo->regtype == RegTypeFP) {
5706                                 if (inst->dreg != ainfo->reg) {
5707                                         if (ainfo->size == 4) {
5708                                                 s390_ledbr (code, inst->dreg, ainfo->reg);
5709                                         } else {
5710                                                 s390_ldr   (code, inst->dreg, ainfo->reg);
5711                                         }
5712                                 }
5713                         }
5714                         else if (ainfo->regtype == RegTypeBase) {
5715                                 s390_lgr  (code, s390_r13, STK_BASE);
5716                                 s390_aghi (code, s390_r13, alloc_size);
5717                                 s390_lg   (code, inst->dreg, 0, s390_r13, ainfo->offset);
5718                         } else
5719                                 g_assert_not_reached ();
5720
5721                         if (cfg->verbose_level > 2)
5722                                 g_print ("Argument %d assigned to register %s\n", 
5723                                          pos, mono_arch_regname (inst->dreg));
5724                 } else {
5725                         if (ainfo->regtype == RegTypeGeneral) {
5726                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5727                                         g_assert_not_reached();
5728                                 switch (ainfo->size) {
5729                                 case 1:
5730                                         s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5731                                         break;
5732                                 case 2:
5733                                         s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5734                                         break;
5735                                 case 4: 
5736                                         s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5737                                         break;
5738                                 case 8:
5739                                         s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5740                                         break;
5741                                 }
5742                         } else if (ainfo->regtype == RegTypeBase) {
5743                         } else if (ainfo->regtype == RegTypeFP) {
5744                                 if (ainfo->size == 8)
5745                                         s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5746                                 else if (ainfo->size == 4)
5747                                         s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5748                                 else
5749                                         g_assert_not_reached ();
5750                         } else if (ainfo->regtype == RegTypeStructByVal) {
5751                                 int doffset = inst->inst_offset;
5752                                 int reg;
5753                                 if (ainfo->reg != STK_BASE)
5754                                         reg = ainfo->reg;
5755                                 else {
5756                                         reg = s390_r0;
5757                                         s390_lgr  (code, s390_r13, STK_BASE);
5758                                         s390_aghi (code, s390_r13, alloc_size);
5759                                 }
5760
5761                                 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE  
5762                                         ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5763                                         : ainfo->size);
5764
5765                                 switch (size) {
5766                                         case 1:
5767                                                 if (ainfo->reg == STK_BASE)
5768                                                         s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5769                                                 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5770                                                 break;
5771                                         case 2:
5772                                                 if (ainfo->reg == STK_BASE)
5773                                                         s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5774                                                 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5775                                                 break;
5776                                         case 4:
5777                                                 if (ainfo->reg == STK_BASE)
5778                                                         s390_l  (code, reg, 0, s390_r13, ainfo->offset+4);
5779                                                 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5780                                                 break;
5781                                         case 8:
5782                                                 if (ainfo->reg == STK_BASE)
5783                                                         s390_lg  (code, reg, 0, s390_r13, ainfo->offset);
5784                                                 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5785                                                 break;
5786                                 }
5787                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5788                                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5789                         } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5790                         } else
5791                                 g_assert_not_reached ();
5792                 }
5793                 pos++;
5794         }
5795
5796         if (method->save_lmf) {
5797                 /*---------------------------------------------------------------*/
5798                 /* build the MonoLMF structure on the stack - see mini-s390x.h   */
5799                 /*---------------------------------------------------------------*/
5800                 lmfOffset = alloc_size - sizeof(MonoLMF);       
5801                                                                                         
5802                 s390_lgr   (code, s390_r13, cfg->frame_reg);            
5803                 s390_aghi  (code, s390_r13, lmfOffset);                                 
5804                                                                                         
5805                 /*---------------------------------------------------------------*/
5806                 /* Preserve the parameter registers while we fix up the lmf      */
5807                 /*---------------------------------------------------------------*/
5808                 s390_stmg  (code, s390_r2, s390_r6, s390_r13,
5809                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5810
5811                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5812                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5813                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5814                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5815                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5816
5817                 /*---------------------------------------------------------------*/
5818                 /* On return from this call r2 have the address of the &lmf      */
5819                 /*---------------------------------------------------------------*/
5820                 mono_add_patch_info (cfg, code - cfg->native_code, 
5821                                 MONO_PATCH_INFO_INTERNAL_METHOD, 
5822                                 (gpointer)"mono_tls_get_lmf_addr");
5823                 S390_CALL_TEMPLATE(code, s390_r1);
5824
5825                 /*---------------------------------------------------------------*/     
5826                 /* Set lmf.lmf_addr = jit_tls->lmf                               */     
5827                 /*---------------------------------------------------------------*/     
5828                 s390_stg   (code, s390_r2, 0, s390_r13,                                 
5829                             G_STRUCT_OFFSET(MonoLMF, lmf_addr));                        
5830                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5831                                                                                         
5832                 /*---------------------------------------------------------------*/     
5833                 /* Get current lmf                                               */     
5834                 /*---------------------------------------------------------------*/     
5835                 s390_lg    (code, s390_r0, 0, s390_r2, 0);                              
5836                                                                                         
5837                 /*---------------------------------------------------------------*/     
5838                 /* Set our lmf as the current lmf                                */     
5839                 /*---------------------------------------------------------------*/     
5840                 s390_stg   (code, s390_r13, 0, s390_r2, 0);                             
5841                                                                                         
5842                 /*---------------------------------------------------------------*/     
5843                 /* Have our lmf.previous_lmf point to the last lmf               */     
5844                 /*---------------------------------------------------------------*/     
5845                 s390_stg   (code, s390_r0, 0, s390_r13,                                 
5846                             G_STRUCT_OFFSET(MonoLMF, previous_lmf));                    
5847                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5848                                                                                         
5849                 /*---------------------------------------------------------------*/     
5850                 /* save method info                                              */     
5851                 /*---------------------------------------------------------------*/     
5852                 S390_SET   (code, s390_r1, method);
5853                 s390_stg   (code, s390_r1, 0, s390_r13,                                 
5854                             G_STRUCT_OFFSET(MonoLMF, method));                          
5855                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5856                                                                                 
5857                 /*---------------------------------------------------------------*/     
5858                 /* save the current IP                                           */     
5859                 /*---------------------------------------------------------------*/     
5860                 s390_stg   (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5861                 s390_basr  (code, s390_r1, 0);
5862                 s390_stg   (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); 
5863                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5864                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5865                                                                                         
5866                 /*---------------------------------------------------------------*/     
5867                 /* Save general and floating point registers                     */     
5868                 /*---------------------------------------------------------------*/     
5869                 s390_stmg  (code, s390_r2, s390_r12, s390_r13,                          
5870                             G_STRUCT_OFFSET(MonoLMF, gregs[2]));                        
5871                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5872                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5873                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5874                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5875                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5876                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5877                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5878                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5879                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5880                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5881                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5882
5883                 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5884                 for (i = 0; i < 16; i++) {                                              
5885                         s390_std  (code, i, 0, s390_r13,                                
5886                                    G_STRUCT_OFFSET(MonoLMF, fregs[i]));                 
5887                         mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5888                         fpOffset += sizeof(double);
5889                 }                                                                       
5890
5891                 /*---------------------------------------------------------------*/
5892                 /* Restore the parameter registers now that we've set up the lmf */
5893                 /*---------------------------------------------------------------*/
5894                 s390_lmg   (code, s390_r2, s390_r6, s390_r13,                           
5895                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));                        
5896         }
5897
5898         if (cfg->method->save_lmf)
5899                 argsClobbered = TRUE;
5900
5901         if (tracing) {
5902                 argsClobbered = TRUE;
5903                 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5904         }
5905
5906         /*
5907          * Optimize the common case of the first bblock making a call with the same
5908          * arguments as the method. This works because the arguments are still in their
5909          * original argument registers.
5910          */
5911         if (!argsClobbered) {
5912                 MonoBasicBlock *first_bb = cfg->bb_entry;
5913                 MonoInst *next;
5914                 int filter = FILTER_IL_SEQ_POINT;
5915
5916                 next = mono_bb_first_inst (first_bb, filter);
5917                 if (!next && first_bb->next_bb) {
5918                         first_bb = first_bb->next_bb;
5919                         next = mono_bb_first_inst (first_bb, filter);
5920                 }
5921
5922                 if (first_bb->in_count > 1)
5923                         next = NULL;
5924
5925                 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5926                         ArgInfo *ainfo = cinfo->args + i;
5927                         gboolean match = FALSE;
5928
5929                         inst = cfg->args [i];
5930                         if (inst->opcode != OP_REGVAR) {
5931                                 switch (ainfo->regtype) {
5932                                 case RegTypeGeneral: {
5933                                         if (((next->opcode == OP_LOAD_MEMBASE) || 
5934                                              (next->opcode == OP_LOADI4_MEMBASE)) && 
5935                                              next->inst_basereg == inst->inst_basereg && 
5936                                              next->inst_offset == inst->inst_offset) {
5937                                                 if (next->dreg == ainfo->reg) {
5938                                                         NULLIFY_INS (next);
5939                                                         match = TRUE;
5940                                                 } else {
5941                                                         next->opcode = OP_MOVE;
5942                                                         next->sreg1 = ainfo->reg;
5943                                                         /* Only continue if the instruction doesn't change argument regs */
5944                                                         if (next->dreg == ainfo->reg)
5945                                                                 match = TRUE;
5946                                                 }
5947                                         }
5948                                         break;
5949                                 }
5950                                 default:
5951                                         break;
5952                                 }
5953                         } else {
5954                                 /* Argument allocated to (non-volatile) register */
5955                                 switch (ainfo->regtype) {
5956                                 case RegTypeGeneral:
5957                                         if (next->opcode == OP_MOVE && 
5958                                             next->sreg1 == inst->dreg && 
5959                                             next->dreg == ainfo->reg) {
5960                                                 NULLIFY_INS (next);
5961                                                 match = TRUE;
5962                                         }
5963                                         break;
5964                                 default:
5965                                         break;
5966                                 }
5967                         }
5968
5969                         if (match) {
5970                                 next = mono_inst_next (next, filter);
5971                                 if (!next)
5972                                         break;
5973                         }
5974                 }
5975         }
5976
5977         cfg->code_len = code - cfg->native_code;
5978         g_assert (cfg->code_len < cfg->code_size);
5979
5980         return code;
5981 }
5982
5983 /*========================= End of Function ========================*/
5984
5985 /*------------------------------------------------------------------*/
5986 /*                                                                  */
5987 /* Name         - mono_arch_emit_epilog                             */
5988 /*                                                                  */
5989 /* Function     - Emit the instructions for a function epilog.      */
5990 /*                                                                  */
5991 /*------------------------------------------------------------------*/
5992
5993 void
5994 mono_arch_emit_epilog (MonoCompile *cfg)
5995 {
5996         MonoMethod *method = cfg->method;
5997         int tracing = 0;
5998         guint8 *code;
5999         int max_epilog_size = 96;
6000         
6001         if (cfg->method->save_lmf)
6002                 max_epilog_size += 128;
6003         
6004         if (mono_jit_trace_calls != NULL)
6005                 max_epilog_size += 128;
6006         
6007         while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6008                 cfg->code_size  *= 2;
6009                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6010                 cfg->stat_code_reallocs++;
6011         }
6012
6013         code = cfg->native_code + cfg->code_len;
6014
6015         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6016                 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6017                 tracing = 1;
6018         }
6019         
6020         if (method->save_lmf) 
6021                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6022
6023         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6024                 s390_lg  (code, STK_BASE, 0, STK_BASE, 0);
6025         } else
6026                 code = backUpStackPtr(cfg, code);
6027
6028         s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6029         s390_br  (code, s390_r14);
6030
6031         cfg->code_len = code - cfg->native_code;
6032
6033         g_assert (cfg->code_len < cfg->code_size);
6034
6035 }
6036
6037 /*========================= End of Function ========================*/
6038
6039 /*------------------------------------------------------------------*/
6040 /*                                                                  */
6041 /* Name         - mono_arch_emit_exceptions                         */
6042 /*                                                                  */
6043 /* Function     - Emit the blocks to handle exception conditions.   */
6044 /*                                                                  */
6045 /*------------------------------------------------------------------*/
6046
6047 void
6048 mono_arch_emit_exceptions (MonoCompile *cfg) 
6049 {
6050         MonoJumpInfo    *patch_info;
6051         guint8          *code;
6052         int             nThrows = 0,
6053                         exc_count = 0,
6054                         iExc;
6055         guint32         code_size;
6056         MonoClass       *exc_classes [MAX_EXC];
6057         guint8          *exc_throw_start [MAX_EXC];
6058
6059         for (patch_info = cfg->patch_info; 
6060              patch_info; 
6061              patch_info = patch_info->next) {
6062                 if (patch_info->type == MONO_PATCH_INFO_EXC)
6063                         exc_count++;
6064         }
6065
6066         code_size = exc_count * 48;
6067
6068         while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6069                 cfg->code_size  *= 2;
6070                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6071                 cfg->stat_code_reallocs++; 
6072         }
6073
6074         code = cfg->native_code + cfg->code_len;
6075
6076         /*---------------------------------------------------------------------*/
6077         /* Add code to raise exceptions                                        */
6078         /*---------------------------------------------------------------------*/
6079         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6080                 switch (patch_info->type) {
6081                 case MONO_PATCH_INFO_EXC: {
6082                         guint8 *ip = patch_info->ip.i + cfg->native_code;
6083                         MonoClass *exc_class;
6084                         guint64 throw_ip;
6085
6086                         /*-----------------------------------------------------*/
6087                         /* Patch the branch in epilog to come here             */
6088                         /*-----------------------------------------------------*/
6089                         s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6090
6091                         exc_class = mono_class_load_from_name (mono_defaults.corlib,
6092                                                           "System", 
6093                                                           patch_info->data.name);
6094                         throw_ip = patch_info->ip.i;
6095
6096                         for (iExc = 0; iExc < nThrows; ++iExc)
6097                                 if (exc_classes [iExc] == exc_class)
6098                                         break;
6099                 
6100                         if (iExc < nThrows) {
6101                                 s390_jcl (code, S390_CC_UN, 
6102                                           (guint64) exc_throw_start [iExc]);
6103                                 patch_info->type = MONO_PATCH_INFO_NONE;
6104                         } else {
6105         
6106                                 if (nThrows < MAX_EXC) {
6107                                         exc_classes [nThrows]     = exc_class;
6108                                         exc_throw_start [nThrows] = code;
6109                                 }
6110         
6111                                 /*---------------------------------------------*/
6112                                 /* Patch the parameter passed to the handler   */ 
6113                                 /*---------------------------------------------*/
6114                                 S390_SET  (code, s390_r2, exc_class->type_token);
6115                                 /*---------------------------------------------*/
6116                                 /* Load return address & parameter register    */
6117                                 /*---------------------------------------------*/
6118                                 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6119                                                            cfg->native_code + 8), code));
6120                                 /*---------------------------------------------*/
6121                                 /* Reuse the current patch to set the jump     */
6122                                 /*---------------------------------------------*/
6123                                 patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
6124                                 patch_info->data.name = "mono_arch_throw_corlib_exception";
6125                                 patch_info->ip.i      = code - cfg->native_code;
6126                                 S390_BR_TEMPLATE (code, s390_r1);
6127                         }
6128                         break;
6129                 }
6130                 default:
6131                         /* do nothing */
6132                         break;
6133                 }
6134         }
6135
6136         cfg->code_len = code - cfg->native_code;
6137
6138         g_assert (cfg->code_len < cfg->code_size);
6139
6140 }
6141
6142 /*========================= End of Function ========================*/
6143
6144 /*------------------------------------------------------------------*/
6145 /*                                                                  */
6146 /* Name         - mono_arch_finish_init                                 */
6147 /*                                                                  */
6148 /* Function     - Setup the JIT's Thread Level Specific Data.       */
6149 /*                                                                  */
6150 /*------------------------------------------------------------------*/
6151
6152 void
6153 mono_arch_finish_init (void)
6154 {
6155 }
6156
6157 /*========================= End of Function ========================*/
6158
6159 /*------------------------------------------------------------------*/
6160 /*                                                                  */
6161 /* Name         - mono_arch_free_jit_tls_data                       */
6162 /*                                                                  */
6163 /* Function     - Free tls data.                                    */
6164 /*                                                                  */
6165 /*------------------------------------------------------------------*/
6166
6167 void
6168 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6169 {
6170 }
6171
6172 /*========================= End of Function ========================*/
6173
6174 /*------------------------------------------------------------------*/
6175 /*                                                                  */
6176 /* Name         - mono_arch_emit_inst_for_method                    */
6177 /*                                                                  */
6178 /*------------------------------------------------------------------*/
6179
6180 MonoInst*
6181 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6182 {
6183         return NULL;
6184 }
6185
6186 /*========================= End of Function ========================*/
6187
6188 /*------------------------------------------------------------------*/
6189 /*                                                                  */
6190 /* Name         - mono_arch_decompose_opts                          */
6191 /*                                                                  */
6192 /* Function     - Decompose opcode into a System z opcode.          */
6193 /*                                                                  */
6194 /*------------------------------------------------------------------*/
6195
6196 void
6197 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6198 {
6199         /* 
6200          * Have to rename these to avoid being decomposed normally, since the normal 
6201          * decomposition does not work on S390.
6202          */
6203         switch (ins->opcode) {
6204         case OP_ISUB_OVF:
6205                 ins->opcode = OP_S390_ISUB_OVF;
6206                 break;
6207         case OP_ISUB_OVF_UN:
6208                 ins->opcode = OP_S390_ISUB_OVF_UN;
6209                 break;
6210         case OP_IADD_OVF:
6211                 ins->opcode = OP_S390_IADD_OVF;
6212                 break;
6213         case OP_IADD_OVF_UN:
6214                 ins->opcode = OP_S390_IADD_OVF_UN;
6215                 break;
6216         case OP_LADD_OVF:
6217                 ins->opcode = OP_S390_LADD_OVF;
6218                 break;
6219         case OP_LADD_OVF_UN:
6220                 ins->opcode = OP_S390_LADD_OVF_UN;
6221                 break;
6222         case OP_LSUB_OVF:
6223                 ins->opcode = OP_S390_LSUB_OVF;
6224                 break;
6225         case OP_LSUB_OVF_UN:
6226                 ins->opcode = OP_S390_LSUB_OVF_UN;
6227                 break;
6228         default:
6229                 break;
6230         }
6231 }
6232
6233 /*========================= End of Function ========================*/
6234
6235 /*------------------------------------------------------------------*/
6236 /*                                                                  */
6237 /* Name         - mono_arch_print_tree                              */
6238 /*                                                                  */
6239 /* Function     - Print platform-specific opcode details.           */
6240 /*                                                                  */
6241 /* Returns      - 1 - opcode details have been printed              */
6242 /*                0 - opcode details have not been printed          */
6243 /*                                                                  */
6244 /*------------------------------------------------------------------*/
6245
6246 gboolean
6247 mono_arch_print_tree (MonoInst *tree, int arity)
6248 {
6249         gboolean done;
6250
6251         switch (tree->opcode) {
6252                 case OP_S390_LOADARG:
6253                 case OP_S390_ARGREG:
6254                 case OP_S390_ARGPTR:
6255                         printf ("[0x%lx(%s)]", tree->inst_offset, 
6256                                 mono_arch_regname (tree->inst_basereg));
6257                         done = 1;
6258                         break;
6259                 case OP_S390_STKARG:
6260                         printf ("[0x%lx(previous_frame)]", 
6261                                 tree->inst_offset); 
6262                         done = 1;
6263                         break;
6264                 case OP_S390_MOVE:
6265                         printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6266                                 tree->inst_offset, tree->backend.size,
6267                                 mono_arch_regname(tree->dreg), 
6268                                 tree->inst_imm, 
6269                                 mono_arch_regname(tree->sreg1));
6270                         done = 1;
6271                         break;
6272                 case OP_S390_SETF4RET:
6273                         printf ("[f%s,f%s]", 
6274                                 mono_arch_regname (tree->dreg),
6275                                 mono_arch_regname (tree->sreg1));
6276                         done = 1;
6277                         break;
6278                 case OP_TLS_GET:
6279                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6280                         tree->inst_imm,
6281                         mono_arch_regname (tree->sreg1));
6282                         done = 1;
6283                         break;
6284                 case OP_TLS_SET:
6285                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6286                         tree->inst_imm,
6287                         mono_arch_regname (tree->sreg1));
6288                         done = 1;
6289                         break;
6290                 case OP_S390_BKCHAIN:
6291                         printf ("[previous_frame(%s)]", 
6292                                 mono_arch_regname (tree->sreg1));
6293                         done = 1;
6294                 default:
6295                         done = 0;
6296         }
6297         return (done);
6298 }
6299
6300 /*========================= End of Function ========================*/
6301
6302 /*------------------------------------------------------------------*/
6303 /*                                                                  */
6304 /* Name         - mono_arch_regalloc_cost                           */
6305 /*                                                                  */
6306 /* Function     - Determine the cost, in the number of memory       */
6307 /*                references, of the action of allocating the var-  */
6308 /*                iable VMV into a register during global register  */
6309 /*                allocation.                                       */
6310 /*                                                                  */
6311 /* Returns      - Cost                                              */
6312 /*                                                                  */
6313 /*------------------------------------------------------------------*/
6314
6315 guint32
6316 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6317 {
6318         /* FIXME: */
6319         return 2;
6320 }
6321
6322 /*========================= End of Function ========================*/
6323
6324 /*------------------------------------------------------------------*/
6325 /*                                                                  */
6326 /* Name         - mono_arch_flush_register_windows                  */
6327 /*                                                                  */
6328 /* Function     -                                                   */
6329 /*                                                                  */
6330 /* Returns      -                                                   */
6331 /*                                                                  */
6332 /*------------------------------------------------------------------*/
6333
6334 void 
6335 mono_arch_flush_register_windows (void)
6336 {
6337 }
6338
6339 /*========================= End of Function ========================*/
6340
6341 /*------------------------------------------------------------------*/
6342 /*                                                                  */
6343 /* Name         - mono_arch_is_inst_imm                             */
6344 /*                                                                  */
6345 /* Function     - Determine if operand qualifies as an immediate    */
6346 /*                value. For s390 this is a value -32768-32768      */
6347 /*                                                                  */
6348 /* Returns      - True|False - is [not] immediate value.            */
6349 /*                                                                  */
6350 /*------------------------------------------------------------------*/
6351
6352 gboolean 
6353 mono_arch_is_inst_imm (gint64 imm)
6354 {
6355         return s390_is_imm32 (imm);
6356 }
6357
6358 /*========================= End of Function ========================*/
6359
6360 /*------------------------------------------------------------------*/
6361 /*                                                                  */
6362 /* Name         - mono_arch_get_patch_offset                        */
6363 /*                                                                  */
6364 /* Function     - Dummy entry point until s390x supports aot.       */
6365 /*                                                                  */
6366 /* Returns      - Offset for patch.                                 */
6367 /*                                                                  */
6368 /*------------------------------------------------------------------*/
6369
6370 guint32
6371 mono_arch_get_patch_offset (guint8 *code)
6372 {
6373         return 0;
6374 }
6375
6376 /*========================= End of Function ========================*/
6377
6378 /*------------------------------------------------------------------*/
6379 /*                                                                  */
6380 /* Name         - mono_arch_context_get_int_reg.                    */
6381 /*                                                                  */
6382 /* Function     -                                                   */
6383 /*                                                                  */
6384 /* Returns      - Return a register from the context.               */
6385 /*                                                                  */
6386 /*------------------------------------------------------------------*/
6387
6388 mgreg_t
6389 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6390 {
6391         return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6392 }
6393
6394 /*========================= End of Function ========================*/
6395
6396 /*------------------------------------------------------------------*/
6397 /*                                                                  */
6398 /* Name         - mono_arch_context_set_int_reg.                    */
6399 /*                                                                  */
6400 /* Function     - Set a value in a specified register.              */
6401 /*                                                                  */
6402 /*------------------------------------------------------------------*/
6403
6404 void
6405 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6406 {
6407         ctx->uc_mcontext.gregs[reg] = val;
6408 }
6409
6410 /*========================= End of Function ========================*/
6411
6412 /*------------------------------------------------------------------*/
6413 /*                                                                  */
6414 /* Name         - mono_arch_get_this_arg_from_call.                 */
6415 /*                                                                  */
6416 /* Function     -                                                   */
6417 /*                                                                  */
6418 /*------------------------------------------------------------------*/
6419
6420 gpointer
6421 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6422 {
6423         return (gpointer) regs [s390_r2];
6424 }
6425
6426 /*========================= End of Function ========================*/
6427  
6428 /*------------------------------------------------------------------*/
6429 /*                                                                  */
6430 /* Name         - mono_arch_install_handler_block_guard             */
6431 /*                                                                  */
6432 /* Function     -                                                   */
6433 /*                                                                  */
6434 /*------------------------------------------------------------------*/
6435
6436 gpointer
6437 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, 
6438                                        MonoContext *ctx, gpointer new_value)
6439 {
6440         int offset;
6441         gpointer *sp, old_value;
6442         char *bp;
6443
6444         offset = clause->exvar_offset;
6445
6446         /*Load the spvar*/
6447         bp = MONO_CONTEXT_GET_BP (ctx);
6448         sp = *(gpointer*)(bp + offset);
6449
6450         old_value = *sp;
6451         if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6452                 return old_value;
6453
6454         *sp = new_value;
6455
6456         return old_value;
6457 }
6458
6459 /*========================= End of Function ========================*/
6460  
6461 /*------------------------------------------------------------------*/
6462 /*                                                                  */
6463 /* Name         - get_delegate_invoke_impl.                         */
6464 /*                                                                  */
6465 /* Function     -                                                   */
6466 /*                                                                  */
6467 /*------------------------------------------------------------------*/
6468
6469 static gpointer
6470 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6471 {
6472         guint8 *code, *start;
6473
6474         if (has_target) {
6475                 int size = 32;
6476
6477                 start = code = mono_global_codeman_reserve (size);
6478
6479                 /* Replace the this argument with the target */
6480                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6481                 s390_lg   (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6482                 s390_br   (code, s390_r1);
6483                 g_assert ((code - start) <= size);
6484
6485                 mono_arch_flush_icache (start, size);
6486         } else {
6487                 int size, i;
6488
6489                 size = 32 + param_count * 8;
6490                 start = code = mono_global_codeman_reserve (size);
6491
6492                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6493                 /* slide down the arguments */
6494                 for (i = 0; i < param_count; ++i) {
6495                         s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6496                 }
6497                 s390_br   (code, s390_r1);
6498
6499                 g_assert ((code - start) <= size);
6500
6501                 mono_arch_flush_icache (start, size);
6502         }
6503
6504         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6505
6506         if (has_target) {
6507                 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6508         } else {
6509                 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6510                 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6511                 g_free (name);
6512         }
6513
6514         return start;
6515 }
6516
6517 /*========================= End of Function ========================*/
6518
6519 /*------------------------------------------------------------------*/
6520 /*                                                                  */
6521 /* Name         - mono_arch_get_delegate_invoke_impls.              */
6522 /*                                                                  */
6523 /* Function     -                                                   */
6524 /*                                                                  */
6525 /*------------------------------------------------------------------*/
6526
6527 GSList*
6528 mono_arch_get_delegate_invoke_impls (void)
6529 {
6530         GSList *res = NULL;
6531         MonoTrampInfo *info;
6532         int i;
6533
6534         get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6535         res = g_slist_prepend (res, info);
6536
6537         for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6538                 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6539                 res = g_slist_prepend (res, info);
6540         }
6541
6542         return res;
6543 }
6544
6545 /*========================= End of Function ========================*/
6546
6547 /*------------------------------------------------------------------*/
6548 /*                                                                  */
6549 /* Name         - mono_arch_get_delegate_invoke_impl.               */
6550 /*                                                                  */
6551 /* Function     -                                                   */
6552 /*                                                                  */
6553 /*------------------------------------------------------------------*/
6554
6555 gpointer
6556 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6557 {
6558         guint8 *code, *start;
6559
6560         /* FIXME: Support more cases */
6561         if (MONO_TYPE_ISSTRUCT (sig->ret))
6562                 return NULL;
6563
6564         if (has_target) {
6565                 static guint8* cached = NULL;
6566
6567                 if (cached)
6568                         return cached;
6569
6570                 if (mono_aot_only) {
6571                         start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6572                 } else {
6573                         MonoTrampInfo *info;
6574                         start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6575                         mono_tramp_info_register (info, NULL);
6576                 }
6577
6578                 mono_memory_barrier ();
6579
6580                 cached = start;
6581         } else {
6582                 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6583                 int i;
6584
6585                 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6586                         return NULL;
6587                 for (i = 0; i < sig->param_count; ++i)
6588                         if (!mono_is_regsize_var (sig->params [i]))
6589                                 return NULL;
6590
6591
6592                 code = cache [sig->param_count];
6593                 if (code)
6594                         return code;
6595
6596                 if (mono_aot_only) {
6597                         char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6598                         start = mono_aot_get_trampoline (name);
6599                         g_free (name);
6600                 } else {
6601                         MonoTrampInfo *info;
6602                         start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6603                         mono_tramp_info_register (info, NULL);
6604                 }
6605
6606                 mono_memory_barrier ();
6607
6608                 cache [sig->param_count] = start;
6609         }
6610         return start;
6611 }
6612
6613 /*========================= End of Function ========================*/
6614
6615 /*------------------------------------------------------------------*/
6616 /*                                                                  */
6617 /* Name         - mono_arch_get_delegate_virtual_invoke_impl.       */
6618 /*                                                                  */
6619 /* Function     -                                                   */
6620 /*                                                                  */
6621 /*------------------------------------------------------------------*/
6622
6623 gpointer
6624 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, 
6625                                             int offset, gboolean load_imt_reg)
6626 {
6627         guint8 *code, *start;
6628         int size = 40;
6629
6630         start = code = mono_global_codeman_reserve (size);
6631
6632         /*
6633         * Replace the "this" argument with the target
6634         */
6635         s390_lgr  (code, s390_r1, s390_r2);
6636         s390_lg   (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));        
6637
6638         /*
6639         * Load the IMT register, if needed
6640         */
6641         if (load_imt_reg) {
6642                 s390_lg  (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6643         }
6644
6645         /*
6646         * Load the vTable
6647         */
6648         s390_lg  (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6649         if (offset != 0) {
6650                 s390_agfi(code, s390_r1, offset);
6651         }
6652         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6653         s390_br  (code, s390_r1);
6654
6655         return(start);
6656 }
6657
6658 /*========================= End of Function ========================*/
6659
6660 /*------------------------------------------------------------------*/
6661 /*                                                                  */
6662 /* Name         - mono_arch_build_imt_trampoline.                       */
6663 /*                                                                  */
6664 /* Function     -                                                   */
6665 /*                                                                  */
6666 /*------------------------------------------------------------------*/
6667
6668 gpointer
6669 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, 
6670                                                                 MonoIMTCheckItem **imt_entries, int count,
6671                                                                 gpointer fail_tramp)
6672 {
6673         int i;
6674         int size = 0;
6675         guchar *code, *start;
6676         char trampName[64];
6677
6678         for (i = 0; i < count; ++i) {
6679                 MonoIMTCheckItem *item = imt_entries [i];
6680                 if (item->is_equals) {
6681                         if (item->check_target_idx) {
6682                                 if (!item->compare_done)
6683                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6684                                 if (item->has_target_code)
6685                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6686                                 else
6687                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE + 
6688                                                             LOAD_SIZE;
6689                         } else {
6690                                 if (fail_tramp) {
6691                                         item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE + 
6692                                                             2 * LOADCON_SIZE;
6693                                         if (!item->has_target_code)
6694                                                 item->chunk_size += LOAD_SIZE;
6695                                 } else {
6696                                         item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6697 #if ENABLE_WRONG_METHOD_CHECK
6698                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6699 #endif
6700                                 }
6701                         }
6702                 } else {
6703                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6704                         imt_entries [item->check_target_idx]->compare_done = TRUE;
6705                 }
6706                 size += item->chunk_size;
6707         }
6708
6709         if (fail_tramp)
6710                 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6711         else
6712                 code = mono_domain_code_reserve (domain, size);
6713
6714         start = code;
6715
6716         for (i = 0; i < count; ++i) {
6717                 MonoIMTCheckItem *item = imt_entries [i];
6718                 item->code_target = (guint8 *) code;
6719                 if (item->is_equals) {
6720                         if (item->check_target_idx) {
6721                                 if (!item->compare_done) {
6722                                         S390_SET  (code, s390_r0, item->key);
6723                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6724                                 }
6725                                 item->jmp_code = (guint8*) code;
6726                                 s390_jcl (code, S390_CC_NE, 0);
6727                                 
6728                                 if (item->has_target_code) {
6729                                         S390_SET (code, s390_r1, item->value.target_code);
6730                                 } else {
6731                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6732                                         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6733                                 }
6734                                 s390_br   (code, s390_r1);
6735                         } else {
6736                                 if (fail_tramp) {
6737                                         gint64  target;
6738
6739                                         S390_SET  (code, s390_r0, item->key);
6740                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6741                                         item->jmp_code = (guint8*) code;
6742                                         s390_jcl  (code, S390_CC_NE, 0);
6743                                         if (item->has_target_code) {
6744                                                 S390_SET (code, s390_r1, item->value.target_code);
6745                                         } else {
6746                                                 g_assert (vtable);
6747                                                 S390_SET  (code, s390_r1, 
6748                                                            (&(vtable->vtable [item->value.vtable_slot])));
6749                                                 s390_lg   (code, s390_r1, 0, s390_r1, 0);
6750                                         }
6751                                         s390_br   (code, s390_r1);
6752                                         target = (gint64) S390_RELATIVE(code, item->jmp_code);
6753                                         s390_patch_rel(item->jmp_code+2, target);
6754                                         S390_SET  (code, s390_r1, fail_tramp);
6755                                         s390_br   (code, s390_r1);
6756                                         item->jmp_code = NULL;
6757                                 } else {
6758                                 /* enable the commented code to assert on wrong method */
6759 #if ENABLE_WRONG_METHOD_CHECK
6760                                         g_assert_not_reached ();
6761 #endif
6762                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6763                                         s390_lg   (code, s390_r1, 0, s390_r1, 0);
6764                                         s390_br   (code, s390_r1);
6765                                 }
6766                         }
6767                 } else {
6768                         S390_SET  (code, s390_r0, item->key);
6769                         s390_cgr  (code, MONO_ARCH_IMT_REG, s390_r0);
6770                         item->jmp_code = (guint8 *) code;
6771                         s390_jcl  (code, S390_CC_GE, 0);
6772                 }
6773         }
6774         /* 
6775          * patch the branches to get to the target items 
6776          */
6777         for (i = 0; i < count; ++i) {
6778                 MonoIMTCheckItem *item = imt_entries [i];
6779                 if (item->jmp_code) {
6780                         if (item->check_target_idx) {
6781                                 gint64 offset;
6782                                 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6783                                                        item->jmp_code);
6784                                 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6785                         }
6786                 }
6787         }
6788
6789         mono_arch_flush_icache ((guint8*)start, (code - start));
6790         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6791
6792         if (!fail_tramp) 
6793                 mono_stats.imt_trampolines_size += (code - start);
6794
6795         g_assert (code - start <= size);
6796
6797         snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6798         mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6799
6800         return (start);
6801 }
6802
6803 /*========================= End of Function ========================*/
6804
6805 /*------------------------------------------------------------------*/
6806 /*                                                                  */
6807 /* Name         - mono_arch_find_imt_method.                        */
6808 /*                                                                  */
6809 /* Function     - Get the method address from MONO_ARCH_IMT_REG     */
6810 /*                found in the save area.                           */
6811 /*                                                                  */
6812 /*------------------------------------------------------------------*/
6813
6814 MonoMethod*
6815 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6816 {
6817         return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6818 }
6819
6820 /*========================= End of Function ========================*/
6821
6822 /*------------------------------------------------------------------*/
6823 /*                                                                  */
6824 /* Name         - mono_arch_find_static_call_vtable                 */
6825 /*                                                                  */
6826 /* Function     - Find the static call vtable.                      */
6827 /*                                                                  */
6828 /*------------------------------------------------------------------*/
6829
6830 MonoVTable*
6831 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6832 {
6833         mgreg_t *r = (mgreg_t*)regs;
6834
6835         return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6836 }
6837
6838 /*========================= End of Function ========================*/
6839
6840 /*------------------------------------------------------------------*/
6841 /*                                                                  */
6842 /* Name         - mono_arch_get_cie_program                         */
6843 /*                                                                  */
6844 /* Function     - Find the static call vtable.                      */
6845 /*                                                                  */
6846 /*------------------------------------------------------------------*/
6847
6848 GSList*
6849 mono_arch_get_cie_program (void)
6850 {
6851         GSList *l = NULL;
6852
6853         mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6854
6855         return(l);
6856 }
6857
6858 /*========================= End of Function ========================*/
6859
6860 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6861
6862 /*------------------------------------------------------------------*/
6863 /*                                                                  */
6864 /* Name         - mono_arch_set_breakpoint.                         */
6865 /*                                                                  */
6866 /* Function     - Set a breakpoint at the native code corresponding */
6867 /*                to JI at NATIVE_OFFSET.  The location should      */
6868 /*                contain code emitted by OP_SEQ_POINT.             */
6869 /*                                                                  */
6870 /*------------------------------------------------------------------*/
6871
6872 void
6873 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6874 {
6875         guint8 *code = ip;
6876
6877         breakpointCode.pTrigger = bp_trigger_page;
6878         memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6879         code += BREAKPOINT_SIZE;
6880 }
6881
6882 /*========================= End of Function ========================*/
6883
6884 /*------------------------------------------------------------------*/
6885 /*                                                                  */
6886 /* Name         - mono_arch_clear_breakpoint.                       */
6887 /*                                                                  */
6888 /* Function     - Clear the breakpoint at IP.                       */
6889 /*                                                                  */
6890 /*------------------------------------------------------------------*/
6891
6892 void
6893 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6894 {
6895         guint8 *code = ip;
6896         int i;
6897
6898         for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6899                 s390_nop(code);
6900 }
6901
6902 /*========================= End of Function ========================*/
6903
6904 /*------------------------------------------------------------------*/
6905 /*                                                                  */
6906 /* Name         - mono_arch_is_breakpoint_event.                    */
6907 /*                                                                  */
6908 /* Function     -                                                   */
6909 /*                                                                  */
6910 /*------------------------------------------------------------------*/
6911
6912 gboolean
6913 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6914 {
6915         siginfo_t* sinfo = (siginfo_t*) info;
6916
6917         /* 
6918          * Sometimes the address is off by 4 
6919          */
6920         if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6921                 return TRUE;
6922         else
6923                 return FALSE;
6924 }
6925
6926 /*========================= End of Function ========================*/
6927
6928 /*------------------------------------------------------------------*/
6929 /*                                                                  */
6930 /* Name         - mono_arch_skip_breakpoint.                        */
6931 /*                                                                  */
6932 /* Function     - Modify the CTX so the IP is placed after the      */
6933 /*                breakpoint instruction, so when we resume, the    */
6934 /*                instruction is not executed again.                */
6935 /*                                                                  */
6936 /*------------------------------------------------------------------*/
6937
6938 void
6939 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6940 {
6941         MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6942 }
6943
6944 /*========================= End of Function ========================*/
6945         
6946 /*------------------------------------------------------------------*/
6947 /*                                                                  */
6948 /* Name         - mono_arch_start_single_stepping.                  */
6949 /*                                                                  */
6950 /* Function     - Start single stepping.                            */
6951 /*                                                                  */
6952 /*------------------------------------------------------------------*/
6953
6954 void
6955 mono_arch_start_single_stepping (void)
6956 {
6957         mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6958 }
6959
6960 /*========================= End of Function ========================*/
6961         
6962 /*------------------------------------------------------------------*/
6963 /*                                                                  */
6964 /* Name         - mono_arch_stop_single_stepping.                   */
6965 /*                                                                  */
6966 /* Function     - Stop single stepping.                             */
6967 /*                                                                  */
6968 /*------------------------------------------------------------------*/
6969
6970 void
6971 mono_arch_stop_single_stepping (void)
6972 {
6973         mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6974 }
6975
6976 /*========================= End of Function ========================*/
6977
6978 /*------------------------------------------------------------------*/
6979 /*                                                                  */
6980 /* Name         - mono_arch_is_single_step_event.                   */
6981 /*                                                                  */
6982 /* Function     - Return whether the machine state in sigctx cor-   */
6983 /*                responds to a single step event.                  */
6984 /*                                                                  */
6985 /*------------------------------------------------------------------*/
6986
6987 gboolean
6988 mono_arch_is_single_step_event (void *info, void *sigctx)
6989 {
6990         siginfo_t* sinfo = (siginfo_t*) info;
6991
6992         /* 
6993          * Sometimes the address is off by 4 
6994          */
6995         if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6996                 return TRUE;
6997         else
6998                 return FALSE;
6999 }
7000
7001 /*========================= End of Function ========================*/
7002
7003 /*------------------------------------------------------------------*/
7004 /*                                                                  */
7005 /* Name         - mono_arch_skip_single_step.                       */
7006 /*                                                                  */
7007 /* Function     - Modify the ctx so the IP is placed after the      */
7008 /*                single step trigger instruction, so that the      */
7009 /*                instruction is not executed again.                */
7010 /*                                                                  */
7011 /*------------------------------------------------------------------*/
7012
7013 void
7014 mono_arch_skip_single_step (MonoContext *ctx)
7015 {
7016         MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7017 }
7018
7019 /*========================= End of Function ========================*/
7020
7021 /*------------------------------------------------------------------*/
7022 /*                                                                  */
7023 /* Name         - mono_arch_create_seq_point_info.                  */
7024 /*                                                                  */
7025 /* Function     - Return a pointer to a data struction which is     */
7026 /*                used by the sequence point implementation in      */
7027 /*                AOTed code.                                       */
7028 /*                                                                  */
7029 /*------------------------------------------------------------------*/
7030
7031 gpointer
7032 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7033 {
7034         NOT_IMPLEMENTED;
7035         return NULL;
7036 }
7037
7038 /*========================= End of Function ========================*/
7039
7040 /*------------------------------------------------------------------*/
7041 /*                                                                  */
7042 /* Name         - mono_arch_init_lmf_ext.                           */
7043 /*                                                                  */
7044 /* Function -                                                       */
7045 /*                                                                  */
7046 /*------------------------------------------------------------------*/
7047
7048 void
7049 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7050 {
7051         ext->lmf.previous_lmf = prev_lmf;
7052         /* Mark that this is a MonoLMFExt */
7053         ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7054         ext->lmf.ebp = (gssize)ext;
7055 }
7056
7057 /*========================= End of Function ========================*/
7058
7059 #endif
7060
7061 /*------------------------------------------------------------------*/
7062 /*                                                                  */
7063 /* Name     - mono_arch_cpu_enumerate_simd_versions.                */
7064 /*                                                                  */
7065 /* Function - If this CPU supports vector operations then it        */
7066 /*            supports the equivalent of SSE1-4.                    */
7067 /*                                                                  */
7068 /*------------------------------------------------------------------*/
7069
7070 guint32
7071 mono_arch_cpu_enumerate_simd_versions (void)
7072 {
7073         guint32 sseOpts = 0;
7074
7075         if (mono_hwcap_s390x_has_vec)
7076                 sseOpts = (SIMD_VERSION_SSE1  | SIMD_VERSION_SSE2 |
7077                            SIMD_VERSION_SSE3  | SIMD_VERSION_SSSE3 |
7078                            SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7079                            SIMD_VERSION_SSE4a);
7080
7081         return (sseOpts);
7082 }
7083
7084 /*========================= End of Function ========================*/
7085
7086 /*------------------------------------------------------------------*/
7087 /*                                                                  */
7088 /* Name     - mono_arch_opcode_supported.                           */
7089 /*                                                                  */
7090 /* Function - Check if a given return code is supported.            */
7091 /*                                                                  */
7092 /*------------------------------------------------------------------*/
7093
7094 gboolean
7095 mono_arch_opcode_supported (int opcode)
7096 {
7097         switch (opcode) {
7098         case OP_ATOMIC_ADD_I4:
7099         case OP_ATOMIC_ADD_I8:
7100         case OP_ATOMIC_EXCHANGE_I4:
7101         case OP_ATOMIC_EXCHANGE_I8:
7102                 return TRUE;
7103         default:
7104                 return FALSE;
7105         }
7106 }
7107
7108 /*========================= End of Function ========================*/