bab41317cc6012bd583e8b0f9063ed8ad80bbb21
[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         MONO_BB_FOR_EACH_INS (bb, ins) {
2989                 offset = code - cfg->native_code;
2990
2991                 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2992
2993                 if (offset > (cfg->code_size - max_len - 16)) {
2994                         cfg->code_size *= 2;
2995                         cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2996                         code = cfg->native_code + offset;
2997                 }
2998
2999                 mono_debug_record_line_number (cfg, ins, offset);
3000
3001                 switch (ins->opcode) {
3002                 case OP_STOREI1_MEMBASE_IMM: {
3003                         s390_lghi (code, s390_r0, ins->inst_imm);
3004                         S390_LONG (code, stcy, stc, s390_r0, 0, 
3005                                    ins->inst_destbasereg, ins->inst_offset);
3006                 }
3007                         break;
3008                 case OP_STOREI2_MEMBASE_IMM: {
3009                         s390_lghi (code, s390_r0, ins->inst_imm);
3010                         S390_LONG (code, sthy, sth, s390_r0, 0, 
3011                                    ins->inst_destbasereg, ins->inst_offset);
3012                 }
3013                         break;
3014                 case OP_STOREI4_MEMBASE_IMM: {
3015                         s390_lgfi (code, s390_r0, ins->inst_imm);
3016                         S390_LONG (code, sty, st, s390_r0, 0, 
3017                                    ins->inst_destbasereg, ins->inst_offset);
3018                 }
3019                         break;
3020                 case OP_STORE_MEMBASE_IMM:
3021                 case OP_STOREI8_MEMBASE_IMM: {
3022                         S390_SET (code, s390_r0, ins->inst_imm);
3023                         S390_LONG (code, stg, stg, s390_r0, 0, 
3024                                    ins->inst_destbasereg, ins->inst_offset);
3025                 }
3026                         break;
3027                 case OP_STOREI1_MEMBASE_REG: {
3028                         S390_LONG (code, stcy, stc, ins->sreg1, 0, 
3029                                    ins->inst_destbasereg, ins->inst_offset);
3030                 }
3031                         break;
3032                 case OP_STOREI2_MEMBASE_REG: {
3033                         S390_LONG (code, sthy, sth, ins->sreg1, 0, 
3034                                    ins->inst_destbasereg, ins->inst_offset);
3035                 }
3036                         break;
3037                 case OP_STOREI4_MEMBASE_REG: {
3038                         S390_LONG (code, sty, st, ins->sreg1, 0, 
3039                                    ins->inst_destbasereg, ins->inst_offset);
3040                 }
3041                         break;
3042                 case OP_STORE_MEMBASE_REG:
3043                 case OP_STOREI8_MEMBASE_REG: {
3044                         S390_LONG (code, stg, stg, ins->sreg1, 0, 
3045                                    ins->inst_destbasereg, ins->inst_offset);
3046                 }
3047                         break;
3048                 case OP_LOADU4_MEM:
3049                         g_assert_not_reached ();
3050                         break;
3051                 case OP_LOAD_MEMBASE:
3052                 case OP_LOADI8_MEMBASE: {
3053                         S390_LONG (code, lg, lg, ins->dreg, 0, 
3054                                    ins->inst_basereg, ins->inst_offset);
3055                 }
3056                         break;
3057                 case OP_LOADI4_MEMBASE: {
3058                         S390_LONG (code, lgf, lgf, ins->dreg, 0, 
3059                                    ins->inst_basereg, ins->inst_offset);
3060                 }
3061                         break;
3062                 case OP_LOADU4_MEMBASE: {
3063                         S390_LONG (code, llgf, llgf, ins->dreg, 0, 
3064                                    ins->inst_basereg, ins->inst_offset);
3065                 }
3066                         break;
3067                 case OP_LOADU1_MEMBASE: {
3068                         S390_LONG (code, llgc, llgc, ins->dreg, 0, 
3069                                    ins->inst_basereg, ins->inst_offset);
3070                 }
3071                         break;
3072                 case OP_LOADI1_MEMBASE: {
3073                         S390_LONG (code, lgb, lgb, ins->dreg, 0, 
3074                                    ins->inst_basereg, ins->inst_offset);
3075                 }
3076                         break;
3077                 case OP_LOADU2_MEMBASE: {
3078                         S390_LONG (code, llgh, llgh, ins->dreg, 0, 
3079                                    ins->inst_basereg, ins->inst_offset);
3080                 }
3081                         break;
3082                 case OP_LOADI2_MEMBASE: {
3083                         S390_LONG (code, lgh, lgh, ins->dreg, 0, 
3084                                    ins->inst_basereg, ins->inst_offset);
3085                 }
3086                         break;
3087                 case OP_LCONV_TO_I1: {
3088                         s390_lgbr (code, ins->dreg, ins->sreg1);
3089                 }
3090                         break;
3091                 case OP_LCONV_TO_I2: {
3092                         s390_lghr (code, ins->dreg, ins->sreg1);
3093                 }
3094                         break;
3095                 case OP_LCONV_TO_U1: {
3096                         s390_llgcr (code, ins->dreg, ins->sreg1);
3097                 }
3098                         break;
3099                 case OP_LCONV_TO_U2: {
3100                         s390_llghr (code, ins->dreg, ins->sreg1);
3101                 }
3102                         break;
3103                 case OP_ICONV_TO_I1: {
3104                         s390_lgbr  (code, ins->dreg, ins->sreg1);
3105                 }
3106                         break;
3107                 case OP_ICONV_TO_I2: {
3108                         s390_lghr  (code, ins->dreg, ins->sreg1);
3109                 }
3110                         break;
3111                 case OP_ICONV_TO_U1: {
3112                         s390_llgcr (code, ins->dreg, ins->sreg1);
3113                 }
3114                         break;
3115                 case OP_ICONV_TO_U2: {
3116                         s390_llghr (code, ins->dreg, ins->sreg1);
3117                 }
3118                         break;
3119                 case OP_COMPARE: 
3120                 case OP_LCOMPARE: {
3121                         if (is_unsigned (ins->next))
3122                                 s390_clgr (code, ins->sreg1, ins->sreg2);
3123                         else
3124                                 s390_cgr  (code, ins->sreg1, ins->sreg2);
3125                 }
3126                         break;
3127                 case OP_ICOMPARE: {
3128                         if (is_unsigned (ins->next))
3129                                 s390_clr  (code, ins->sreg1, ins->sreg2);
3130                         else
3131                                 s390_cr   (code, ins->sreg1, ins->sreg2);
3132                 }
3133                         break;
3134                 case OP_COMPARE_IMM:
3135                 case OP_LCOMPARE_IMM: {
3136                         S390_SET (code, s390_r0, ins->inst_imm);
3137                         if (is_unsigned (ins->next))
3138                                 s390_clgr (code, ins->sreg1, s390_r0);
3139                         else
3140                                 s390_cgr  (code, ins->sreg1, s390_r0);
3141                 }
3142                         break;
3143                 case OP_ICOMPARE_IMM: {
3144                         S390_SET (code, s390_r0, ins->inst_imm);
3145                         if (is_unsigned (ins->next))
3146                                 s390_clr  (code, ins->sreg1, s390_r0);
3147                         else
3148                                 s390_cr   (code, ins->sreg1, s390_r0);
3149                 }
3150                         break;
3151                 case OP_BREAK: {
3152                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS, 
3153                                              mono_break);
3154                         S390_CALL_TEMPLATE (code, s390_r14);
3155                 }
3156                         break;
3157                 case OP_ADDCC: {
3158                         CHECK_SRCDST_COM;
3159                         s390_agr  (code, ins->dreg, src2);
3160                 }
3161                         break;
3162                 case OP_LADD: {
3163                         CHECK_SRCDST_COM;
3164                         s390_agr   (code, ins->dreg, src2);
3165                 }
3166                         break;
3167                 case OP_ADC: {
3168                         CHECK_SRCDST_COM;
3169                         s390_alcgr (code, ins->dreg, src2);
3170                 }
3171                         break;
3172                 case OP_ADD_IMM: {
3173                         if (ins->dreg != ins->sreg1) {
3174                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3175                         }
3176                         if (s390_is_imm16 (ins->inst_imm)) {
3177                                 s390_aghi (code, ins->dreg, ins->inst_imm);
3178                         } else if (s390_is_imm32 (ins->inst_imm)) {
3179                                 s390_agfi (code, ins->dreg, ins->inst_imm);
3180                         } else {
3181                                 S390_SET  (code, s390_r0, ins->inst_imm);
3182                                 s390_agr  (code, ins->dreg, s390_r0);
3183                         }
3184                 }
3185                         break;
3186                 case OP_LADD_IMM: {
3187                         if (ins->dreg != ins->sreg1) {
3188                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3189                         }
3190                         g_assert (s390_is_imm16 (ins->inst_imm));
3191                         s390_aghi (code, ins->dreg, ins->inst_imm);
3192                 }
3193                         break;
3194                 case OP_ADC_IMM: {
3195                         if (ins->dreg != ins->sreg1) {
3196                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3197                         }
3198                         if (s390_is_imm16 (ins->inst_imm)) {
3199                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3200                                 s390_alcgr (code, ins->dreg, s390_r0);
3201                         } else {
3202                                 S390_SET   (code, s390_r0, ins->inst_imm);
3203                                 s390_alcgr (code, ins->dreg, s390_r0);
3204                         }
3205                 }
3206                         break;
3207                 case OP_IADD_OVF:
3208                 case OP_S390_IADD_OVF: {
3209                         CHECK_SRCDST_COM;
3210                         s390_ar    (code, ins->dreg, src2);
3211                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3212                         s390_lgfr  (code, ins->dreg, ins->dreg);
3213                 }
3214                         break;
3215                 case OP_IADD_OVF_UN:
3216                 case OP_S390_IADD_OVF_UN: {
3217                         CHECK_SRCDST_COM;
3218                         s390_algr  (code, ins->dreg, src2);
3219                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3220                         s390_llgfr (code, ins->dreg, ins->dreg);
3221                 }
3222                         break;
3223                 case OP_ADD_OVF_CARRY: {
3224                         CHECK_SRCDST_COM;
3225                         s390_lghi  (code, s390_r0, 0);
3226                         s390_lgr   (code, s390_r1, s390_r0);
3227                         s390_alcgr (code, s390_r0, s390_r1);
3228                         s390_agr   (code, ins->dreg, src2);
3229                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3230                         s390_agr   (code, ins->dreg, s390_r0);
3231                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3232                 }
3233                         break;
3234                 case OP_ADD_OVF_UN_CARRY: {
3235                         CHECK_SRCDST_COM;
3236                         s390_alcgr (code, ins->dreg, src2);
3237                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3238                 }
3239                         break;
3240                 case OP_SUBCC: {
3241                         CHECK_SRCDST_NCOM;
3242                         s390_sgr (code, ins->dreg, src2);
3243                 }
3244                         break;
3245                 case OP_LSUB: {
3246                         CHECK_SRCDST_NCOM;
3247                         s390_sgr  (code, ins->dreg, src2);
3248                 }
3249                         break;
3250                 case OP_SBB: {
3251                         CHECK_SRCDST_NCOM;
3252                         s390_slbgr(code, ins->dreg, src2);
3253                 }
3254                         break;
3255                 case OP_SUB_IMM: {
3256                         if (ins->dreg != ins->sreg1) {
3257                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3258                         }
3259                         if (s390_is_imm16 (-ins->inst_imm)) {
3260                                 s390_aghi  (code, ins->dreg, -ins->inst_imm);
3261                         } else if (s390_is_imm32 (-ins->inst_imm)) {
3262                                 s390_slgfi  (code, ins->dreg, ins->inst_imm);
3263                         } else {
3264                                 S390_SET  (code, s390_r0, ins->inst_imm);
3265                                 s390_slgr (code, ins->dreg, s390_r0);
3266                         }
3267                 }
3268                         break;
3269                 case OP_LSUB_IMM: {
3270                         if (ins->dreg != ins->sreg1) {
3271                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3272                         }
3273                         if (s390_is_imm16 (-ins->inst_imm)) {
3274                                 s390_aghi  (code, ins->dreg, -ins->inst_imm);
3275                         } else if (s390_is_imm32 (-ins->inst_imm)) {
3276                                 s390_slgfi (code, ins->dreg, ins->inst_imm);
3277                         } else {
3278                                 S390_SET  (code, s390_r0, ins->inst_imm);
3279                                 s390_slgr (code, ins->dreg, s390_r0);
3280                         }
3281                 }
3282                         break;
3283                 case OP_SBB_IMM: {
3284                         if (ins->dreg != ins->sreg1) {
3285                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3286                         }
3287                         if (s390_is_imm16 (-ins->inst_imm)) {
3288                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3289                                 s390_slbgr (code, ins->dreg, s390_r0);
3290                         } else {
3291                                 S390_SET  (code, s390_r0, ins->inst_imm);
3292                                 s390_slbgr(code, ins->dreg, s390_r0);
3293                         }
3294                 }
3295                         break;
3296                 case OP_SUB_OVF_CARRY: {
3297                         CHECK_SRCDST_NCOM;
3298                         s390_lghi  (code, s390_r0, 0);
3299                         s390_lgr   (code, s390_r1, s390_r0);
3300                         s390_slbgr (code, s390_r0, s390_r1);
3301                         s390_sgr   (code, ins->dreg, src2);
3302                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3303                         s390_agr   (code, ins->dreg, s390_r0);
3304                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3305                 }
3306                         break;
3307                 case OP_SUB_OVF_UN_CARRY: {
3308                         CHECK_SRCDST_NCOM;
3309                         s390_slbgr (code, ins->dreg, src2);
3310                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3311                 }
3312                         break;
3313                 case OP_LAND: {
3314                         if (ins->sreg1 == ins->dreg) {
3315                                 s390_ngr  (code, ins->dreg, ins->sreg2);
3316                         } 
3317                         else { 
3318                                 if (ins->sreg2 == ins->dreg) { 
3319                                         s390_ngr (code, ins->dreg, ins->sreg1);
3320                                 }
3321                                 else { 
3322                                         s390_lgr (code, ins->dreg, ins->sreg1);
3323                                         s390_ngr (code, ins->dreg, ins->sreg2);
3324                                 }
3325                         }
3326                 }
3327                         break;
3328                 case OP_AND_IMM: {
3329                         if (ins->dreg != ins->sreg1) {
3330                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3331                         }
3332                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3333                         s390_ngr (code, ins->dreg, s390_r0);
3334                 }
3335                         break;
3336                 case OP_LDIV: {
3337                         s390_lgr  (code, s390_r1, ins->sreg1);
3338                         s390_dsgr (code, s390_r0, ins->sreg2);
3339                         s390_lgr  (code, ins->dreg, s390_r1);
3340                 }
3341                         break;
3342                 case OP_LDIV_UN: {
3343                         s390_lgr   (code, s390_r1, ins->sreg1);
3344                         s390_lghi  (code, s390_r0, 0);
3345                         s390_dlgr  (code, s390_r0, ins->sreg2);
3346                         s390_lgr   (code, ins->dreg, s390_r1);
3347                 }
3348                         break;
3349                 case OP_LREM: {
3350                         s390_lgr  (code, s390_r1, ins->sreg1);
3351                         s390_dsgr (code, s390_r0, ins->sreg2);
3352                         s390_lgr  (code, ins->dreg, s390_r0);
3353                         break;
3354                 }
3355                 case OP_LREM_IMM: {
3356                         if (s390_is_imm16 (ins->inst_imm)) {
3357                                 s390_lghi (code, s390_r13, ins->inst_imm);
3358                         } else {
3359                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3360                         }
3361                         s390_lgr  (code, s390_r0, ins->sreg1);
3362                         s390_dsgr (code, s390_r0, s390_r13);
3363                         s390_lgfr (code, ins->dreg, s390_r0);
3364                 }
3365                         break;
3366                 case OP_LREM_UN: {
3367                         s390_lgr   (code, s390_r1, ins->sreg1);
3368                         s390_lghi  (code, s390_r0, 0);
3369                         s390_dlgr  (code, s390_r0, ins->sreg2);
3370                         s390_lgr   (code, ins->dreg, s390_r0);
3371                 }
3372                         break;
3373                 case OP_LOR: {
3374                         if (ins->sreg1 == ins->dreg) {
3375                                 s390_ogr  (code, ins->dreg, ins->sreg2);
3376                         } 
3377                         else { 
3378                                 if (ins->sreg2 == ins->dreg) { 
3379                                         s390_ogr (code, ins->dreg, ins->sreg1);
3380                                 }
3381                                 else { 
3382                                         s390_lgr (code, ins->dreg, ins->sreg1);
3383                                         s390_ogr (code, ins->dreg, ins->sreg2);
3384                                 }
3385                         }
3386                 }
3387                         break;
3388                 case OP_OR_IMM: {
3389                         if (ins->dreg != ins->sreg1) {
3390                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3391                         }
3392                         S390_SET_MASK(code, s390_r0, ins->inst_imm);
3393                         s390_ogr (code, ins->dreg, s390_r0);
3394                 }
3395                         break;
3396                 case OP_LXOR: {
3397                         if (ins->sreg1 == ins->dreg) {
3398                                 s390_xgr  (code, ins->dreg, ins->sreg2);
3399                         } 
3400                         else { 
3401                                 if (ins->sreg2 == ins->dreg) { 
3402                                         s390_xgr (code, ins->dreg, ins->sreg1);
3403                                 }
3404                                 else { 
3405                                         s390_lgr (code, ins->dreg, ins->sreg1);
3406                                         s390_xgr (code, ins->dreg, ins->sreg2);
3407                                 }
3408                         }
3409                 }
3410                         break;
3411                 case OP_XOR_IMM: {
3412                         if (ins->dreg != ins->sreg1) {
3413                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3414                         }
3415                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3416                         s390_xgr (code, ins->dreg, s390_r0);
3417                 }
3418                         break;
3419                 case OP_LSHL: {
3420                         CHECK_SRCDST_NCOM;
3421                         s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3422                 }
3423                         break;
3424                 case OP_SHL_IMM: 
3425                 case OP_LSHL_IMM: {
3426                         if (ins->sreg1 != ins->dreg) {
3427                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3428                         }
3429                         s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3430                 }
3431                         break;
3432                 case OP_LSHR: {
3433                         CHECK_SRCDST_NCOM;
3434                         s390_srag  (code, ins->dreg, ins->dreg, src2, 0);
3435                 }
3436                         break;
3437                 case OP_SHR_IMM:
3438                 case OP_LSHR_IMM: {
3439                         if (ins->sreg1 != ins->dreg) {
3440                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3441                         }
3442                         s390_srag  (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3443                 }
3444                         break;
3445                 case OP_SHR_UN_IMM: 
3446                 case OP_LSHR_UN_IMM: {
3447                         if (ins->sreg1 != ins->dreg) {
3448                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3449                         }
3450                         s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3451                 }
3452                         break;
3453                 case OP_LSHR_UN: {
3454                         CHECK_SRCDST_NCOM;
3455                         s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3456                 }
3457                         break;
3458                 case OP_LNOT: {
3459                         if (ins->sreg1 != ins->dreg) {
3460                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3461                         }
3462                         s390_lghi (code, s390_r0, -1);
3463                         s390_xgr  (code, ins->dreg, s390_r0);
3464                 }
3465                         break;
3466                 case OP_LNEG: {
3467                         s390_lcgr (code, ins->dreg, ins->sreg1);
3468                 }
3469                         break;
3470                 case OP_LMUL: {
3471                         CHECK_SRCDST_COM;
3472                         s390_msgr (code, ins->dreg, src2);
3473                 }
3474                         break;
3475                 case OP_MUL_IMM: 
3476                 case OP_LMUL_IMM: {
3477                         if (ins->dreg != ins->sreg1) {
3478                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3479                         }
3480                         if (s390_is_imm16 (ins->inst_imm)) {
3481                                 s390_lghi (code, s390_r13, ins->inst_imm);
3482                         } else if (s390_is_imm32 (ins->inst_imm)) {
3483                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3484                         } else {
3485                                 S390_SET (code, s390_r13, ins->inst_imm);
3486                         }
3487                         s390_msgr (code, ins->dreg, s390_r13);
3488                 }
3489                         break;
3490                 case OP_LMUL_OVF: {
3491                         short int *o[2];
3492                         s390_ltgr (code, s390_r1, ins->sreg1);
3493                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3494                         s390_ltgr (code, s390_r0, ins->sreg2);
3495                         s390_jnz  (code, 6);
3496                         s390_lghi (code, s390_r1, 0);
3497                         s390_j    (code, 0); CODEPTR(code, o[1]);
3498                         s390_xgr  (code, s390_r0, s390_r1);
3499                         s390_msgr (code, s390_r1, ins->sreg2);
3500                         s390_xgr  (code, s390_r0, s390_r1);
3501                         s390_srlg (code, s390_r0, s390_r0, 0, 63);
3502                         s390_ltgr (code, s390_r0, s390_r0);
3503                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3504                         PTRSLOT   (code, o[0]); 
3505                         PTRSLOT   (code, o[1]);
3506                         s390_lgr  (code, ins->dreg, s390_r1);
3507                 }
3508                         break;
3509                 case OP_LMUL_OVF_UN: {
3510                         s390_lghi  (code, s390_r0, 0);
3511                         s390_lgr   (code, s390_r1, ins->sreg1);
3512                         s390_mlgr  (code, s390_r0, ins->sreg2);
3513                         s390_ltgr  (code, s390_r0, s390_r0);
3514                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3515                         s390_lgr   (code, ins->dreg, s390_r1);
3516                 }
3517                         break;
3518                 case OP_IADDCC: {
3519                         g_assert_not_reached ();
3520                         CHECK_SRCDST_COM_I;
3521                         s390_algr (code, ins->dreg, src2);
3522                 }
3523                         break;
3524                 case OP_IADD: {
3525                         CHECK_SRCDST_COM_I;
3526                         s390_agr  (code, ins->dreg, src2);
3527                 }
3528                         break;
3529                 case OP_IADC: {
3530                         g_assert_not_reached ();
3531                         CHECK_SRCDST_COM_I;
3532                         s390_alcgr (code, ins->dreg, src2);
3533                 }
3534                         break;
3535                 case OP_IADD_IMM: {
3536                         if (ins->dreg != ins->sreg1) {
3537                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3538                         }
3539                         if (s390_is_imm16 (ins->inst_imm)) {
3540                                 s390_aghi (code, ins->dreg, ins->inst_imm);
3541                         } else {
3542                                 s390_afi  (code, ins->dreg, ins->inst_imm);
3543                         }
3544                 }
3545                         break;
3546                 case OP_IADC_IMM: {
3547                         if (ins->dreg != ins->sreg1) {
3548                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3549                         } 
3550                         if (s390_is_imm16 (ins->inst_imm)) {
3551                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3552                                 s390_alcgr (code, ins->dreg, s390_r0);
3553                         } else {
3554                                 S390_SET   (code, s390_r0, ins->inst_imm);
3555                                 s390_alcgr (code, ins->dreg, s390_r0);
3556                         }
3557                 }
3558                         break;
3559                 case OP_LADD_OVF:
3560                 case OP_S390_LADD_OVF: {
3561                         CHECK_SRCDST_COM;
3562                         s390_agr    (code, ins->dreg, src2);
3563                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3564                 }
3565                         break;
3566                 case OP_LADD_OVF_UN:
3567                 case OP_S390_LADD_OVF_UN: {
3568                         CHECK_SRCDST_COM;
3569                         s390_algr  (code, ins->dreg, src2);
3570                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3571                 }
3572                         break;
3573                 case OP_ISUBCC: {
3574                         CHECK_SRCDST_NCOM_I;
3575                         s390_slgr (code, ins->dreg, src2);
3576                 }
3577                         break;
3578                 case OP_ISUB: {
3579                         CHECK_SRCDST_NCOM_I;
3580                         s390_sgr  (code, ins->dreg, src2);
3581                 }
3582                         break;
3583                 case OP_ISBB: {
3584                         CHECK_SRCDST_NCOM_I;
3585                         s390_slbgr (code, ins->dreg, src2);
3586                 }
3587                         break;
3588                 case OP_ISUB_IMM: {
3589                         if (ins->dreg != ins->sreg1) {
3590                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3591                         }
3592                         if (s390_is_imm16 (-ins->inst_imm)) {
3593                                 s390_aghi (code, ins->dreg, -ins->inst_imm);
3594                         } else {
3595                                 s390_agfi (code, ins->dreg, -ins->inst_imm);
3596                         }
3597                 }
3598                         break;
3599                 case OP_ISBB_IMM: {
3600                         S390_SET (code, s390_r0, ins->inst_imm);
3601                         s390_slgfr (code, ins->dreg, s390_r0);
3602                 }
3603                         break;
3604                 case OP_ISUB_OVF:
3605                 case OP_S390_ISUB_OVF: {
3606                         CHECK_SRCDST_NCOM;
3607                         s390_sr   (code, ins->dreg, src2);
3608                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3609                         s390_lgfr (code, ins->dreg, ins->dreg);
3610                 }
3611                         break;
3612                 case OP_ISUB_OVF_UN:
3613                 case OP_S390_ISUB_OVF_UN: {
3614                         CHECK_SRCDST_NCOM;
3615                         s390_slr  (code, ins->dreg, src2);
3616                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3617                         s390_llgfr(code, ins->dreg, ins->dreg);
3618                 }
3619                         break;
3620                 case OP_LSUB_OVF:
3621                 case OP_S390_LSUB_OVF: {
3622                         CHECK_SRCDST_NCOM;
3623                         s390_sgr   (code, ins->dreg, src2);
3624                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3625                 }
3626                         break;
3627                 case OP_LSUB_OVF_UN:
3628                 case OP_S390_LSUB_OVF_UN: {
3629                         CHECK_SRCDST_NCOM;
3630                         s390_slgr  (code, ins->dreg, src2);
3631                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3632                 }
3633                         break;
3634                 case OP_IAND: {
3635                         CHECK_SRCDST_NCOM_I;
3636                         s390_ngr (code, ins->dreg, src2);
3637                 }
3638                         break;
3639                 case OP_IAND_IMM: {
3640                         if (ins->dreg != ins->sreg1) {
3641                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3642                         }
3643                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3644                         s390_ngr  (code, ins->dreg, s390_r0);
3645                 }
3646                         break;
3647                 case OP_IDIV: {
3648                         s390_lgfr (code, s390_r0, ins->sreg1);
3649                         s390_srda (code, s390_r0, 0, 32);
3650                         s390_dr   (code, s390_r0, ins->sreg2);
3651                         s390_lgfr (code, ins->dreg, s390_r1);
3652                 }
3653                         break;
3654                 case OP_IDIV_UN: {
3655                         s390_lgfr (code, s390_r0, ins->sreg1);
3656                         s390_srdl (code, s390_r0, 0, 32);
3657                         s390_dlr  (code, s390_r0, ins->sreg2);
3658                         s390_lgfr (code, ins->dreg, s390_r1);
3659                 }
3660                         break;
3661                 case OP_IDIV_IMM: {
3662                         if (s390_is_imm16 (ins->inst_imm)) {
3663                                 s390_lghi (code, s390_r13, ins->inst_imm);
3664                         } else {
3665                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3666                         }
3667                         s390_lgfr (code, s390_r0, ins->sreg1);
3668                         s390_srda (code, s390_r0, 0, 32);
3669                         s390_dr   (code, s390_r0, ins->sreg2);
3670                         s390_lgfr (code, ins->dreg, s390_r1);
3671                 }
3672                         break;
3673                 case OP_IREM: {
3674                         s390_lgfr (code, s390_r0, ins->sreg1);
3675                         s390_srda (code, s390_r0, 0, 32);
3676                         s390_dr   (code, s390_r0, ins->sreg2);
3677                         s390_lgfr (code, ins->dreg, s390_r0);
3678                         break;
3679                 case OP_IREM_UN:
3680                         s390_lgfr (code, s390_r0, ins->sreg1);
3681                         s390_srdl (code, s390_r0, 0, 32);
3682                         s390_dlr  (code, s390_r0, ins->sreg2);
3683                         s390_lgfr (code, ins->dreg, s390_r0);
3684                 }
3685                         break;
3686                 case OP_IREM_IMM: {
3687                         if (s390_is_imm16 (ins->inst_imm)) {
3688                                 s390_lghi (code, s390_r13, ins->inst_imm);
3689                         } else {
3690                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3691                         }
3692                         s390_lgfr (code, s390_r0, ins->sreg1);
3693                         s390_srda (code, s390_r0, 0, 32);
3694                         s390_dr   (code, s390_r0, ins->sreg2);
3695                         s390_lgfr (code, ins->dreg, s390_r0);
3696                 }
3697                         break;
3698                 case OP_IOR: {
3699                         CHECK_SRCDST_COM_I;
3700                         s390_ogr (code, ins->dreg, src2);
3701                 }
3702                         break;
3703                 case OP_IOR_IMM: {
3704                         if (ins->dreg != ins->sreg1) {
3705                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3706                         }
3707                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3708                         s390_ogr  (code, ins->dreg, s390_r0);
3709                 }
3710                         break;
3711                 case OP_IXOR: {
3712                         CHECK_SRCDST_COM_I;
3713                         s390_xgr (code, ins->dreg, src2);
3714                 }
3715                         break;
3716                 case OP_IXOR_IMM: {
3717                         if (ins->dreg != ins->sreg1) {
3718                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3719                         }
3720                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3721                         s390_xgr  (code, ins->dreg, s390_r0);
3722                 }
3723                         break;
3724                 case OP_ISHL: {
3725                         CHECK_SRCDST_NCOM;
3726                         s390_sll  (code, ins->dreg, src2, 0);
3727                 }
3728                         break;
3729                 case OP_ISHL_IMM: {
3730                         if (ins->sreg1 != ins->dreg) {
3731                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3732                         }
3733                         s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3734                 }
3735                         break;
3736                 case OP_ISHR: {
3737                         CHECK_SRCDST_NCOM;
3738                         s390_sra (code, ins->dreg, src2, 0);
3739                 }
3740                         break;
3741                 case OP_ISHR_IMM: {
3742                         if (ins->sreg1 != ins->dreg) {
3743                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3744                         }
3745                         s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3746                 }
3747                         break;
3748                 case OP_ISHR_UN_IMM: {
3749                         if (ins->sreg1 != ins->dreg) {
3750                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3751                         }
3752                         s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3753                 }
3754                         break;
3755                 case OP_ISHR_UN: {
3756                         CHECK_SRCDST_NCOM;
3757                         s390_srl  (code, ins->dreg, src2, 0);
3758                 }
3759                         break;
3760                 case OP_INOT: {
3761                         if (ins->sreg1 != ins->dreg) {
3762                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3763                         }
3764                         s390_lghi (code, s390_r0, -1);
3765                         s390_xgr  (code, ins->dreg, s390_r0);
3766                 }
3767                         break;
3768                 case OP_INEG: {
3769                         s390_lcgr (code, ins->dreg, ins->sreg1);
3770                 }
3771                         break;
3772                 case OP_IMUL: {
3773                         CHECK_SRCDST_COM_I;
3774                         s390_msr (code, ins->dreg, src2);
3775                 }
3776                         break;
3777                 case OP_IMUL_IMM: {
3778                         if (ins->dreg != ins->sreg1) {
3779                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3780                         }
3781                         if (s390_is_imm16 (ins->inst_imm)) {
3782                                 s390_lghi (code, s390_r0, ins->inst_imm);
3783                         } else {
3784                                 s390_lgfi (code, s390_r0, ins->inst_imm);
3785                         }
3786                         s390_msr  (code, ins->dreg, s390_r0);
3787                 }
3788                         break;
3789                 case OP_IMUL_OVF: {
3790                         short int *o[2];
3791                         s390_ltr  (code, s390_r1, ins->sreg1);
3792                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3793                         s390_ltr  (code, s390_r0, ins->sreg2);
3794                         s390_jnz  (code, 6);
3795                         s390_lhi  (code, s390_r1, 0);
3796                         s390_j    (code, 0); CODEPTR(code, o[1]);
3797                         s390_xr   (code, s390_r0, s390_r1);
3798                         s390_msr  (code, s390_r1, ins->sreg2);
3799                         s390_xr   (code, s390_r0, s390_r1);
3800                         s390_srl  (code, s390_r0, 0, 31);
3801                         s390_ltr  (code, s390_r0, s390_r0);
3802                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3803                         PTRSLOT   (code, o[0]); 
3804                         PTRSLOT   (code, o[1]);
3805                         s390_lgfr (code, ins->dreg, s390_r1);
3806                 }
3807                         break;
3808                 case OP_IMUL_OVF_UN: {
3809                         s390_lhi  (code, s390_r0, 0);
3810                         s390_lr   (code, s390_r1, ins->sreg1);
3811                         s390_mlr  (code, s390_r0, ins->sreg2);
3812                         s390_ltr  (code, s390_r0, s390_r0);
3813                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3814                         s390_lgfr (code, ins->dreg, s390_r1);
3815                 }
3816                         break;
3817                 case OP_ICONST: 
3818                 case OP_I8CONST: {
3819                         S390_SET (code, ins->dreg, ins->inst_c0);
3820                 }
3821                         break;
3822                 case OP_AOTCONST: {
3823                         mono_add_patch_info (cfg, code - cfg->native_code, 
3824                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3825                         S390_LOAD_TEMPLATE (code, ins->dreg);
3826                 }
3827                         break;
3828                 case OP_JUMP_TABLE: {
3829                         mono_add_patch_info (cfg, code - cfg->native_code, 
3830                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3831                         S390_LOAD_TEMPLATE (code, ins->dreg);
3832                 }
3833                         break;
3834                 case OP_MOVE:
3835                         if (ins->dreg != ins->sreg1) {
3836                                 s390_lgr (code, ins->dreg, ins->sreg1);
3837                         }
3838                         break;
3839                 case OP_LCONV_TO_I:
3840                 case OP_LCONV_TO_I8:
3841                 case OP_SEXT_I4:
3842                         s390_lgfr (code, ins->dreg, ins->sreg1);
3843                         break;
3844                 case OP_LCONV_TO_I4:
3845                         s390_lgfr (code, ins->dreg, ins->sreg1);
3846                         break;
3847                 case OP_LCONV_TO_U:
3848                 case OP_LCONV_TO_U8:
3849                 case OP_LCONV_TO_U4:
3850                 case OP_ZEXT_I4:
3851                         s390_llgfr (code, ins->dreg, ins->sreg1);
3852                         break;
3853                 case OP_LCONV_TO_OVF_U4:
3854                         S390_SET  (code, s390_r0, 4294967295);
3855                         s390_clgr (code, ins->sreg1, s390_r0);
3856                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3857                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3858                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3859                         s390_llgfr(code, ins->dreg, ins->sreg1);
3860                         break;
3861                 case OP_LCONV_TO_OVF_I4_UN:
3862                         S390_SET  (code, s390_r0, 2147483647);
3863                         s390_cgr  (code, ins->sreg1, s390_r0);
3864                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3865                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3866                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3867                         s390_lgfr (code, ins->dreg, ins->sreg1);
3868                         break;
3869                 case OP_FMOVE:
3870                         if (ins->dreg != ins->sreg1) {
3871                                 s390_ldr   (code, ins->dreg, ins->sreg1);
3872                         }
3873                         break;
3874                 case OP_MOVE_F_TO_I8: 
3875                         s390_lgdr (code, ins->dreg, ins->sreg1);
3876                         break;
3877                 case OP_MOVE_I8_TO_F: 
3878                         s390_ldgr (code, ins->dreg, ins->sreg1);
3879                         break;
3880                 case OP_MOVE_F_TO_I4:
3881                         s390_ledbr (code, s390_f0, ins->sreg1);
3882                         s390_lgdr (code, ins->dreg, s390_f0);
3883                         s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3884                         break;
3885                 case OP_MOVE_I4_TO_F: 
3886                         s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3887                         s390_ldgr (code, ins->dreg, s390_r0);
3888                         s390_ldebr (code, ins->dreg, ins->dreg);
3889                         break;
3890                 case OP_FCONV_TO_R4:
3891                         s390_ledbr (code, ins->dreg, ins->sreg1);
3892                         s390_ldebr (code, ins->dreg, ins->dreg);
3893                         break;
3894                 case OP_S390_SETF4RET:
3895                         s390_ledbr (code, ins->dreg, ins->sreg1);
3896                         break;
3897                 case OP_TLS_GET: {
3898                         if (s390_is_imm16 (ins->inst_offset)) {
3899                                 s390_lghi (code, s390_r13, ins->inst_offset);
3900                         } else if (s390_is_imm32 (ins->inst_offset)) {
3901                                 s390_lgfi (code, s390_r13, ins->inst_offset);
3902                         } else {
3903                                 S390_SET  (code, s390_r13, ins->inst_offset);
3904                         }
3905                         s390_ear (code, s390_r1, 0);
3906                         s390_sllg(code, s390_r1, s390_r1, 0, 32);
3907                         s390_ear (code, s390_r1, 1);
3908                         s390_lg  (code, ins->dreg, s390_r13, s390_r1, 0);
3909                         }
3910                         break;
3911                 case OP_TLS_SET: {
3912                         if (s390_is_imm16 (ins->inst_offset)) {
3913                                 s390_lghi (code, s390_r13, ins->inst_offset);
3914                         } else if (s390_is_imm32 (ins->inst_offset)) {
3915                                 s390_lgfi (code, s390_r13, ins->inst_offset);
3916                         } else {
3917                                 S390_SET  (code, s390_r13, ins->inst_offset);
3918                         }
3919                         s390_ear (code, s390_r1, 0);
3920                         s390_sllg(code, s390_r1, s390_r1, 0, 32);
3921                         s390_ear (code, s390_r1, 1);
3922                         s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3923                         }
3924                         break;
3925                 case OP_JMP: {
3926                         if (cfg->method->save_lmf)
3927                                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3928
3929                         if (cfg->flags & MONO_CFG_HAS_TAIL) {
3930                                 code =  emit_load_volatile_arguments (code, cfg);
3931                         }
3932
3933                         code = backUpStackPtr(cfg, code);
3934                         s390_lg  (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3935                         mono_add_patch_info (cfg, code - cfg->native_code,
3936                                              MONO_PATCH_INFO_METHOD_JUMP,
3937                                              ins->inst_p0);
3938                         s390_jcl (code, S390_CC_UN, 0);
3939                 }
3940                         break;
3941                 case OP_CHECK_THIS: {
3942                         /* ensure ins->sreg1 is not NULL */
3943                         s390_lg   (code, s390_r0, 0, ins->sreg1, 0);
3944                         s390_ltgr (code, s390_r0, s390_r0);
3945 //                      EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3946                 }
3947                         break;
3948                 case OP_ARGLIST: {
3949                         int offset = cfg->sig_cookie + cfg->stack_usage;
3950
3951                         if (s390_is_imm16 (offset)) {
3952                                 s390_lghi (code, s390_r0, offset);
3953                         } else if (s390_is_imm32 (offset)) {
3954                                 s390_lgfi (code, s390_r0, offset);
3955                         } else {
3956                                 S390_SET  (code, s390_r0, offset);
3957                         }
3958                         s390_agr  (code, s390_r0, cfg->frame_reg);
3959                         s390_stg  (code, s390_r0, 0, ins->sreg1, 0);
3960                 }
3961                         break;
3962                 case OP_FCALL: {
3963                         call = (MonoCallInst*)ins;
3964                         if (ins->flags & MONO_INST_HAS_METHOD)
3965                                 mono_add_patch_info (cfg, code-cfg->native_code,
3966                                                      MONO_PATCH_INFO_METHOD, 
3967                                                      call->method);
3968                         else
3969                                 mono_add_patch_info (cfg, code-cfg->native_code,
3970                                                      MONO_PATCH_INFO_ABS, 
3971                                                      call->fptr);
3972                         S390_CALL_TEMPLATE (code, s390_r14);
3973                         if (call->signature->ret->type == MONO_TYPE_R4)
3974                                 s390_ldebr (code, s390_f0, s390_f0);
3975                 }
3976                         break;
3977                 case OP_LCALL:
3978                 case OP_VCALL:
3979                 case OP_VCALL2:
3980                 case OP_VOIDCALL:
3981                 case OP_CALL: {
3982                         call = (MonoCallInst*)ins;
3983                         if (ins->flags & MONO_INST_HAS_METHOD)
3984                                 mono_add_patch_info (cfg, code-cfg->native_code,
3985                                                      MONO_PATCH_INFO_METHOD, 
3986                                                      call->method);
3987                         else
3988                                 mono_add_patch_info (cfg, code-cfg->native_code,
3989                                                      MONO_PATCH_INFO_ABS, 
3990                                                      call->fptr);
3991                         S390_CALL_TEMPLATE (code, s390_r14);
3992                 }
3993                         break;
3994                 case OP_FCALL_REG: {
3995                         call = (MonoCallInst*)ins;
3996                         s390_lgr  (code, s390_r1, ins->sreg1);
3997                         s390_basr (code, s390_r14, s390_r1);
3998                         if (call->signature->ret->type == MONO_TYPE_R4)
3999                                 s390_ldebr (code, s390_f0, s390_f0);
4000                 }
4001                         break;
4002                 case OP_LCALL_REG:
4003                 case OP_VCALL_REG:
4004                 case OP_VCALL2_REG:
4005                 case OP_VOIDCALL_REG:
4006                 case OP_CALL_REG: {
4007                         s390_lgr  (code, s390_r1, ins->sreg1);
4008                         s390_basr (code, s390_r14, s390_r1);
4009                 }
4010                         break;
4011                 case OP_FCALL_MEMBASE: {
4012                         call = (MonoCallInst*)ins;
4013                         s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4014                         s390_basr (code, s390_r14, s390_r1);
4015                         if (call->signature->ret->type == MONO_TYPE_R4)
4016                                 s390_ldebr (code, s390_f0, s390_f0);
4017                 }
4018                         break;
4019                 case OP_LCALL_MEMBASE:
4020                 case OP_VCALL_MEMBASE:
4021                 case OP_VCALL2_MEMBASE:
4022                 case OP_VOIDCALL_MEMBASE:
4023                 case OP_CALL_MEMBASE: {
4024                         s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4025                         s390_basr (code, s390_r14, s390_r1);
4026                 }
4027                         break;
4028                 case OP_LOCALLOC: {
4029                         int alloca_skip;
4030                         int area_offset;
4031
4032                         if (cfg->param_area == 0)
4033                                 alloca_skip = S390_MINIMAL_STACK_SIZE;
4034                         else
4035                                 alloca_skip = cfg->param_area;
4036
4037                         area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4038                         s390_lgr  (code, s390_r1, ins->sreg1);
4039                         if (ins->flags & MONO_INST_INIT)
4040                                 s390_lgr  (code, s390_r0, ins->sreg1);
4041                         s390_aghi (code, s390_r1, 14);
4042                         s390_srlg (code, s390_r1, s390_r1, 0, 3);
4043                         s390_sllg (code, s390_r1, s390_r1, 0, 3);
4044                         if (cfg->method->save_lmf) {
4045                                 /*----------------------------------*/
4046                                 /* we have to adjust lmf ebp value  */
4047                                 /*----------------------------------*/
4048                                 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4049
4050                                 s390_lgr (code, s390_r13, cfg->frame_reg);
4051                                 if (s390_is_imm16(lmfOffset)) {
4052                                         s390_aghi (code, s390_r13, lmfOffset);
4053                                 } else if (s390_is_imm32(lmfOffset)) {
4054                                         s390_agfi (code, s390_r13, lmfOffset);
4055                                 } else {
4056                                         S390_SET  (code, s390_r13, lmfOffset);
4057                                 }
4058                                 s390_lgr (code, s390_r14, STK_BASE);
4059                                 s390_sgr (code, s390_r14, s390_r1);
4060                                 s390_stg (code, s390_r14, 0, s390_r13,
4061                                           G_STRUCT_OFFSET(MonoLMF, ebp));
4062                         }
4063                         s390_lg   (code, s390_r13, 0, STK_BASE, 0);
4064                         s390_sgr  (code, STK_BASE, s390_r1);
4065                         s390_stg  (code, s390_r13, 0, STK_BASE, 0);
4066                         s390_la   (code, ins->dreg, 0, STK_BASE, area_offset);
4067                         s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4068                         s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4069                         if (ins->flags & MONO_INST_INIT) {
4070                                 s390_lgr  (code, s390_r1, s390_r0);
4071                                 s390_lgr  (code, s390_r0, ins->dreg);
4072                                 s390_lgr  (code, s390_r14, s390_r12);
4073                                 s390_lghi (code, s390_r13, 0);
4074                                 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4075                                 s390_jo   (code, -2);
4076                                 s390_lgr  (code, s390_r12, s390_r14);
4077                         }
4078                 }
4079                         break;
4080                 case OP_THROW: {
4081                         s390_lgr  (code, s390_r2, ins->sreg1);
4082                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
4083                                              (gpointer) "mono_arch_throw_exception");
4084                         S390_CALL_TEMPLATE(code, s390_r14);
4085                 }
4086                         break;
4087                 case OP_RETHROW: {
4088                         s390_lgr  (code, s390_r2, ins->sreg1);
4089                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
4090                                              (gpointer) "mono_arch_rethrow_exception");
4091                         S390_CALL_TEMPLATE(code, s390_r14);
4092                 }
4093                         break;
4094                 case OP_START_HANDLER: {
4095                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4096
4097                         S390_LONG (code, stg, stg, s390_r14, 0,
4098                                    spvar->inst_basereg, 
4099                                    spvar->inst_offset);
4100                 }
4101                         break;
4102                 case OP_ENDFILTER: {
4103                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4104
4105                         if (ins->sreg1 != s390_r2)
4106                                 s390_lgr(code, s390_r2, ins->sreg1);
4107                         S390_LONG (code, lg, lg, s390_r14, 0,
4108                                    spvar->inst_basereg, 
4109                                    spvar->inst_offset);
4110                         s390_br  (code, s390_r14);
4111                 }
4112                         break;
4113                 case OP_ENDFINALLY: {
4114                         MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4115
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_CALL_HANDLER: {
4123                         mono_add_patch_info (cfg, code-cfg->native_code, 
4124                                              MONO_PATCH_INFO_BB, ins->inst_target_bb);
4125                         s390_brasl (code, s390_r14, 0);
4126                         mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4127                 }
4128                         break;
4129                 case OP_LABEL: {
4130                         ins->inst_c0 = code - cfg->native_code;
4131                 }
4132                         break;
4133                 case OP_RELAXED_NOP:
4134                 case OP_NOP:
4135                 case OP_DUMMY_USE:
4136                 case OP_DUMMY_STORE:
4137                 case OP_NOT_REACHED:
4138                 case OP_NOT_NULL: {
4139                 }
4140                         break;
4141                 case OP_IL_SEQ_POINT:
4142                         mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4143                         break;
4144                 case OP_SEQ_POINT: {
4145                         int i;
4146
4147                         if (cfg->compile_aot)
4148                                 NOT_IMPLEMENTED;
4149
4150                         /* 
4151                          * Read from the single stepping trigger page. This will cause a
4152                          * SIGSEGV when single stepping is enabled.
4153                          * We do this _before_ the breakpoint, so single stepping after
4154                          * a breakpoint is hit will step to the next IL offset.
4155                          */
4156                         if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4157                                 breakpointCode.pTrigger = ss_trigger_page;
4158                                 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4159                                 code += BREAKPOINT_SIZE;
4160                         }
4161
4162                         mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4163
4164                         /* 
4165                          * A placeholder for a possible breakpoint inserted by
4166                          * mono_arch_set_breakpoint ().
4167                          */
4168                         for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4169                                 s390_nop (code);
4170
4171                         /*
4172                          * Add an additional nop so skipping the bp doesn't cause the ip to point
4173                          * to another IL offset.
4174                          */
4175                         s390_nop (code);
4176
4177                         break;
4178                 }
4179                 case OP_GENERIC_CLASS_INIT: {
4180                         static int byte_offset = -1;
4181                         static guint8 bitmask;
4182                         short int *jump;
4183
4184                         g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4185
4186                         if (byte_offset < 0)
4187                                 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4188
4189                         s390_tm (code, ins->sreg1, byte_offset, bitmask);
4190                         s390_jo (code, 0); CODEPTR(code, jump);
4191
4192                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4193                                                 "mono_generic_class_init");
4194                         S390_CALL_TEMPLATE(code, s390_r14);
4195
4196                         PTRSLOT (code, jump);
4197
4198                         ins->flags |= MONO_INST_GC_CALLSITE;
4199                         ins->backend.pc_offset = code - cfg->native_code;
4200                         break;
4201                 }
4202                 case OP_BR: 
4203                         EMIT_UNCOND_BRANCH(ins);
4204                         break;
4205                 case OP_BR_REG: {
4206                         s390_br  (code, ins->sreg1);
4207                 }
4208                         break;
4209                 case OP_CEQ: 
4210                 case OP_ICEQ:
4211                 case OP_LCEQ: {
4212                         s390_lghi(code, ins->dreg, 1);
4213                         s390_jz  (code, 4);
4214                         s390_lghi(code, ins->dreg, 0);
4215                 }
4216                         break;
4217                 case OP_CLT: 
4218                 case OP_ICLT:
4219                 case OP_LCLT: {
4220                         s390_lghi(code, ins->dreg, 1);
4221                         s390_jl  (code, 4);
4222                         s390_lghi(code, ins->dreg, 0);
4223                 }
4224                         break;
4225                 case OP_CLT_UN:
4226                 case OP_ICLT_UN:
4227                 case OP_LCLT_UN: {
4228                         s390_lghi(code, ins->dreg, 1);
4229                         s390_jlo (code, 4);
4230                         s390_lghi(code, ins->dreg, 0);
4231                 }
4232                         break;
4233                 case OP_CGT: 
4234                 case OP_ICGT:
4235                 case OP_LCGT: {
4236                         s390_lghi(code, ins->dreg, 1);
4237                         s390_jh  (code, 4);
4238                         s390_lghi(code, ins->dreg, 0);
4239                 }
4240                         break;
4241                 case OP_CGT_UN:
4242                 case OP_ICGT_UN:
4243                 case OP_LCGT_UN: {
4244                         s390_lghi(code, ins->dreg, 1);
4245                         s390_jho (code, 4);
4246                         s390_lghi(code, ins->dreg, 0);
4247                 }
4248                         break;
4249                 case OP_COND_EXC_EQ:
4250                 case OP_COND_EXC_IEQ:
4251                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4252                         break;
4253                 case OP_COND_EXC_NE_UN:
4254                 case OP_COND_EXC_INE_UN:
4255                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4256                         break;
4257                 case OP_COND_EXC_LT:
4258                 case OP_COND_EXC_ILT:
4259                 case OP_COND_EXC_LT_UN:
4260                 case OP_COND_EXC_ILT_UN:
4261                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4262                         break;
4263                 case OP_COND_EXC_GT:
4264                 case OP_COND_EXC_IGT:
4265                 case OP_COND_EXC_GT_UN:
4266                 case OP_COND_EXC_IGT_UN:
4267                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4268                         break;
4269                 case OP_COND_EXC_GE:
4270                 case OP_COND_EXC_IGE:
4271                 case OP_COND_EXC_GE_UN:
4272                 case OP_COND_EXC_IGE_UN:
4273                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4274                         break;
4275                 case OP_COND_EXC_LE:
4276                 case OP_COND_EXC_ILE:
4277                 case OP_COND_EXC_LE_UN:
4278                 case OP_COND_EXC_ILE_UN:
4279                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4280                         break;
4281                 case OP_COND_EXC_OV:
4282                 case OP_COND_EXC_IOV:
4283                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4284                         break;
4285                 case OP_COND_EXC_NO:
4286                 case OP_COND_EXC_INO:
4287                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4288                         break;
4289                 case OP_COND_EXC_C:
4290                 case OP_COND_EXC_IC:
4291                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4292                         break;
4293                 case OP_COND_EXC_NC:
4294                 case OP_COND_EXC_INC:
4295                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4296                         break;
4297                 case OP_LBEQ:
4298                 case OP_IBEQ:
4299                         EMIT_COND_BRANCH (ins, S390_CC_EQ);
4300                         break;  
4301                 case OP_LBNE_UN:
4302                 case OP_IBNE_UN:
4303                         EMIT_COND_BRANCH (ins, S390_CC_NE);
4304                         break;  
4305                 case OP_LBLT:
4306                 case OP_LBLT_UN:
4307                 case OP_IBLT:
4308                 case OP_IBLT_UN:
4309                         EMIT_COND_BRANCH (ins, S390_CC_LT);
4310                         break;  
4311                 case OP_LBGT:
4312                 case OP_LBGT_UN:
4313                 case OP_IBGT:
4314                 case OP_IBGT_UN:
4315                         EMIT_COND_BRANCH (ins, S390_CC_GT);
4316                         break;  
4317                 case OP_LBGE:
4318                 case OP_LBGE_UN:
4319                 case OP_IBGE:
4320                 case OP_IBGE_UN:
4321                         EMIT_COND_BRANCH (ins, S390_CC_GE);
4322                         break;  
4323                 case OP_LBLE:
4324                 case OP_LBLE_UN:
4325                 case OP_IBLE:
4326                 case OP_IBLE_UN:
4327                         EMIT_COND_BRANCH (ins, S390_CC_LE);
4328                         break;
4329
4330                 /* floating point opcodes */
4331                 case OP_R8CONST: {
4332                         if (*((double *) ins->inst_p0) == 0) {
4333                                 s390_lzdr (code, ins->dreg);
4334                         } else {
4335                                 S390_SET  (code, s390_r13, ins->inst_p0);
4336                                 s390_ld   (code, ins->dreg, 0, s390_r13, 0);
4337                         }
4338                 }
4339                         break;
4340                 case OP_R4CONST: {
4341                         if (*((float *) ins->inst_p0) == 0) {
4342                                 s390_lzdr (code, ins->dreg);
4343                         } else {
4344                                 S390_SET  (code, s390_r13, ins->inst_p0);
4345                                 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4346                         }
4347                 }
4348                         break;
4349                 case OP_STORER8_MEMBASE_REG: {
4350                         S390_LONG (code, stdy, std, ins->sreg1, 0, 
4351                                    ins->inst_destbasereg, ins->inst_offset);
4352                 }
4353                         break;
4354                 case OP_LOADR8_MEMBASE: {
4355                         S390_LONG (code, ldy, ld, ins->dreg, 0, 
4356                                    ins->inst_basereg, ins->inst_offset);
4357                 }
4358                         break;
4359                 case OP_STORER4_MEMBASE_REG: {
4360                         s390_ledbr (code, s390_f15, ins->sreg1);
4361                         S390_LONG (code, stey, ste, s390_f15, 0, 
4362                                    ins->inst_destbasereg, ins->inst_offset);
4363                 }
4364                         break;
4365                 case OP_LOADR4_MEMBASE: {
4366                         S390_LONG (code, ley, le, s390_f15, 0, 
4367                                    ins->inst_basereg, ins->inst_offset);
4368                         s390_ldebr (code, ins->dreg, s390_f15);
4369                 }
4370                         break;
4371                 case OP_ICONV_TO_R_UN: {
4372                         if (mono_hwcap_s390x_has_fpe) {
4373                                 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4374                         } else {
4375                                 s390_llgfr (code, s390_r0, ins->sreg1);
4376                                 s390_cdgbr (code, ins->dreg, s390_r0);
4377                         }
4378                 }
4379                         break;
4380                 case OP_LCONV_TO_R_UN: {
4381                         if (mono_hwcap_s390x_has_fpe) {
4382                                 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4383                         } else {
4384                                 short int *jump;
4385                                 s390_cxgbr (code, s390_f12, ins->sreg1);
4386                                 s390_ltgr  (code, ins->sreg1, ins->sreg1);
4387                                 s390_jnl   (code, 0); CODEPTR(code, jump);
4388                                 S390_SET   (code, s390_r13, 0x403f000000000000llu);
4389                                 s390_lgdr  (code, s390_f13, s390_r13);
4390                                 s390_lzdr  (code, s390_f15);
4391                                 s390_axbr  (code, s390_f12, s390_f13);
4392                                 PTRSLOT(code, jump);
4393                                 s390_ldxbr (code, s390_f13, s390_f12);
4394                                 s390_ldr   (code, ins->dreg, s390_f13);
4395                         }
4396                 }
4397                         break;
4398                 case OP_LCONV_TO_R4:
4399                 case OP_ICONV_TO_R4: {
4400                         s390_cegbr (code, ins->dreg, ins->sreg1);
4401                         s390_ldebr (code, ins->dreg, ins->dreg);
4402                 }
4403                         break;
4404                 case OP_LCONV_TO_R8:
4405                 case OP_ICONV_TO_R8: {
4406                         s390_cdgbr (code, ins->dreg, ins->sreg1);
4407                 }
4408                         break;
4409                 case OP_FCONV_TO_I1:
4410                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4411                         s390_ltgr  (code, ins->dreg, ins->dreg);
4412                         s390_jnl   (code, 4);
4413                         s390_oill  (code, ins->dreg, 0x80);
4414                         s390_lghi  (code, s390_r0, 0xff);
4415                         s390_ngr   (code, ins->dreg, s390_r0);
4416                         break;
4417                 case OP_FCONV_TO_U1:
4418                         if (mono_hwcap_s390x_has_fpe) {
4419                                 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4420                                 s390_lghi  (code, s390_r0, 0xff);
4421                                 s390_ngr   (code, ins->dreg, s390_r0);
4422                         } else {
4423                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4424                         }
4425                         break;
4426                 case OP_FCONV_TO_I2:
4427                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4428                         s390_ltgr  (code, ins->dreg, ins->dreg);
4429                         s390_jnl   (code, 4);
4430                         s390_oill  (code, ins->dreg, 0x8000);
4431                         s390_llill (code, s390_r0, 0xffff);
4432                         s390_ngr   (code, ins->dreg, s390_r0);
4433                         break;
4434                 case OP_FCONV_TO_U2:
4435                         if (mono_hwcap_s390x_has_fpe) {
4436                                 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4437                                 s390_llill  (code, s390_r0, 0xffff);
4438                                 s390_ngr    (code, ins->dreg, s390_r0);
4439                         } else {
4440                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4441                         }
4442                         break;
4443                 case OP_FCONV_TO_I4:
4444                 case OP_FCONV_TO_I:
4445                         s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4446                         break;
4447                 case OP_FCONV_TO_U4:
4448                 case OP_FCONV_TO_U:
4449                         if (mono_hwcap_s390x_has_fpe) {
4450                                 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4451                         } else {
4452                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4453                         }
4454                         break;
4455                 case OP_FCONV_TO_I8:
4456                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4457                         break;
4458                 case OP_FCONV_TO_U8:
4459                         if (mono_hwcap_s390x_has_fpe) {
4460                                 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4461                         } else {
4462                                 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4463                         }
4464                         break;
4465                 case OP_LCONV_TO_OVF_I: {
4466                         /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4467                         short int *o[5];
4468                         s390_ltgr (code, ins->sreg2, ins->sreg2);
4469                         s390_jnl  (code, 0); CODEPTR(code, o[0]);
4470                         s390_ltgr (code, ins->sreg1, ins->sreg1);
4471                         s390_jnl  (code, 0); CODEPTR(code, o[1]);
4472                         s390_lhi  (code, s390_r13, -1);
4473                         s390_cgr  (code, ins->sreg1, s390_r13);
4474                         s390_jnz  (code, 0); CODEPTR(code, o[2]);
4475                         if (ins->dreg != ins->sreg2)
4476                                 s390_lgr  (code, ins->dreg, ins->sreg2);
4477                         s390_j    (code, 0); CODEPTR(code, o[3]);
4478                         PTRSLOT(code, o[0]);
4479                         s390_jz   (code, 0); CODEPTR(code, o[4]);
4480                         PTRSLOT(code, o[1]);
4481                         PTRSLOT(code, o[2]);
4482                         mono_add_patch_info (cfg, code - cfg->native_code, 
4483                                              MONO_PATCH_INFO_EXC, "OverflowException");
4484                         s390_brasl (code, s390_r14, 0);
4485                         PTRSLOT(code, o[3]);
4486                         PTRSLOT(code, o[4]);
4487                 }
4488                         break;
4489                 case OP_ABS: {
4490                         s390_lpdbr (code, ins->dreg, ins->sreg1);
4491                 }
4492                         break;
4493                 case OP_SQRT: {
4494                         s390_sqdbr (code, ins->dreg, ins->sreg1);
4495                 }
4496                         break;
4497                 case OP_FADD: {
4498                         CHECK_SRCDST_COM_F;
4499                         s390_adbr (code, ins->dreg, src2);
4500                 }
4501                         break;
4502                 case OP_FSUB: {
4503                         CHECK_SRCDST_NCOM_F;
4504                         s390_sdbr (code, ins->dreg, src2);
4505                 }
4506                         break;          
4507                 case OP_FMUL: {
4508                         CHECK_SRCDST_COM_F;
4509                         s390_mdbr (code, ins->dreg, src2);
4510                 }
4511                         break;          
4512                 case OP_FDIV: {
4513                         CHECK_SRCDST_NCOM_F;
4514                         s390_ddbr (code, ins->dreg, src2);
4515                 }
4516                         break;          
4517                 case OP_FNEG: {
4518                         s390_lcdbr (code, ins->dreg, ins->sreg1);
4519                 }
4520                         break;          
4521                 case OP_FREM: {
4522                         CHECK_SRCDST_NCOM_F;
4523                         s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4524                 }
4525                         break;
4526                 case OP_FCOMPARE: {
4527                         s390_cdbr (code, ins->sreg1, ins->sreg2);
4528                 }
4529                         break;
4530                 case OP_FCEQ: {
4531                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4532                         s390_lghi  (code, ins->dreg, 1);
4533                         s390_je    (code, 4);
4534                         s390_lghi  (code, ins->dreg, 0);
4535                 }
4536                         break;
4537                 case OP_FCLT: {
4538                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4539                         s390_lghi  (code, ins->dreg, 1);
4540                         s390_jl    (code, 4);
4541                         s390_lghi  (code, ins->dreg, 0);
4542                 }
4543                         break;
4544                 case OP_FCLT_UN: {
4545                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4546                         s390_lghi  (code, ins->dreg, 1);
4547                         s390_jlo   (code, 4);
4548                         s390_lghi  (code, ins->dreg, 0);
4549                 }
4550                         break;
4551                 case OP_FCGT: {
4552                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4553                         s390_lghi  (code, ins->dreg, 1);
4554                         s390_jh    (code, 4);
4555                         s390_lghi  (code, ins->dreg, 0);
4556                 }
4557                         break;
4558                 case OP_FCGT_UN: {
4559                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
4560                         s390_lghi  (code, ins->dreg, 1);
4561                         s390_jho   (code, 4);
4562                         s390_lghi  (code, ins->dreg, 0);
4563                 }
4564                         break;
4565                 case OP_FBEQ: {
4566                         short *o;
4567                         s390_jo (code, 0); CODEPTR(code, o);
4568                         EMIT_COND_BRANCH (ins, S390_CC_EQ);
4569                         PTRSLOT (code, o);
4570                 }
4571                         break;
4572                 case OP_FBNE_UN:
4573                         EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4574                         break;
4575                 case OP_FBLT: {
4576                         short *o;
4577                         s390_jo (code, 0); CODEPTR(code, o);
4578                         EMIT_COND_BRANCH (ins, S390_CC_LT);
4579                         PTRSLOT (code, o);
4580                 }
4581                         break;
4582                 case OP_FBLT_UN:
4583                         EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4584                         break;
4585                 case OP_FBGT: {
4586                         short *o;
4587                         s390_jo (code, 0); CODEPTR(code, o);
4588                         EMIT_COND_BRANCH (ins, S390_CC_GT);
4589                         PTRSLOT (code, o);
4590                 }
4591                         break;
4592                 case OP_FBGT_UN:
4593                         EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4594                         break;
4595                 case OP_FBGE: {
4596                         short *o;
4597                         s390_jo (code, 0); CODEPTR(code, o);
4598                         EMIT_COND_BRANCH (ins, S390_CC_GE);
4599                         PTRSLOT (code, o);
4600                 }
4601                         break;
4602                 case OP_FBGE_UN:
4603                         EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4604                         break;
4605                 case OP_FBLE: {
4606                         short *o;
4607                         s390_jo (code, 0); CODEPTR(code, o);
4608                         EMIT_COND_BRANCH (ins, S390_CC_LE);
4609                         PTRSLOT (code, o);
4610                 }
4611                         break;
4612                 case OP_FBLE_UN:
4613                         EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4614                         break;
4615                 case OP_CKFINITE: {
4616                         short *o;
4617                         s390_lhi  (code, s390_r13, 0x7f);
4618                         s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4619                         s390_jz   (code, 0); CODEPTR(code, o);
4620                         mono_add_patch_info (cfg, code - cfg->native_code, 
4621                                              MONO_PATCH_INFO_EXC, "OverflowException");
4622                         s390_brasl (code, s390_r14,0);
4623                         PTRSLOT(code, o);
4624                 }
4625                         break;
4626                 case OP_S390_MOVE: {
4627                         if (ins->backend.size > 0) {
4628                                 if (ins->backend.size <= 256) {
4629                                         s390_mvc  (code, ins->backend.size, ins->dreg, 
4630                                                    ins->inst_offset, ins->sreg1, ins->inst_imm);
4631                                 } else {
4632                                         s390_lgr  (code, s390_r0, ins->dreg);
4633                                         if (ins->inst_offset > 0) {
4634                                                 if (s390_is_imm16 (ins->inst_offset)) {
4635                                                         s390_aghi (code, s390_r0, ins->inst_offset);
4636                                                 } else if (s390_is_imm32 (ins->inst_offset)) {
4637                                                         s390_agfi (code, s390_r0, ins->inst_offset);
4638                                                 } else {
4639                                                         S390_SET  (code, s390_r13, ins->inst_offset);
4640                                                         s390_agr  (code, s390_r0, s390_r13);
4641                                                 }
4642                                         }
4643                                         s390_lgr  (code, s390_r12, ins->sreg1);
4644                                         if (ins->inst_imm > 0) {
4645                                                 if (s390_is_imm16 (ins->inst_imm)) {
4646                                                         s390_aghi (code, s390_r12, ins->inst_imm);
4647                                                 } else if (s390_is_imm32 (ins->inst_imm)) {
4648                                                         s390_agfi (code, s390_r12, ins->inst_imm);
4649                                                 } else {
4650                                                         S390_SET  (code, s390_r13, ins->inst_imm);
4651                                                         s390_agr  (code, s390_r12, s390_r13);
4652                                                 }
4653                                         }
4654                                         if (s390_is_imm16 (ins->backend.size)) {
4655                                                 s390_lghi (code, s390_r1, ins->backend.size);
4656                                         } else if (s390_is_imm32 (ins->inst_offset)) {
4657                                                 s390_agfi (code, s390_r1, ins->backend.size);
4658                                         } else {
4659                                                 S390_SET  (code, s390_r13, ins->backend.size);
4660                                                 s390_agr  (code, s390_r1, s390_r13);
4661                                         }
4662                                         s390_lgr  (code, s390_r13, s390_r1);
4663                                         s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4664                                         s390_jo   (code, -2);
4665                                 }
4666                         }
4667                 }
4668                         break;
4669                 case OP_ATOMIC_ADD_I8: {
4670                         s390_lgr (code, s390_r1, ins->sreg2);
4671                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4672                         s390_agr (code, s390_r1, s390_r0);
4673                         s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4674                         s390_jnz (code, -10);
4675                         s390_lgr (code, ins->dreg, s390_r1);
4676                 }
4677                         break;  
4678                 case OP_ATOMIC_EXCHANGE_I8: {
4679                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4680                         s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4681                         s390_jnz (code, -6);
4682                         s390_lgr (code, ins->dreg, s390_r0);
4683                 }
4684                         break;  
4685                 case OP_ATOMIC_ADD_I4: {
4686                         s390_lgfr(code, s390_r1, ins->sreg2);
4687                         s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4688                         s390_agr (code, s390_r1, s390_r0);
4689                         s390_cs  (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4690                         s390_jnz (code, -9);
4691                         s390_lgfr(code, ins->dreg, s390_r1);
4692                 }
4693                         break;  
4694                 case OP_ATOMIC_EXCHANGE_I4: {
4695                         s390_l   (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4696                         s390_cs  (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4697                         s390_jnz (code, -4);
4698                         s390_lgfr(code, ins->dreg, s390_r0);
4699                 }
4700                         break;  
4701                 case OP_S390_BKCHAIN: {
4702                         s390_lgr  (code, ins->dreg, ins->sreg1);
4703                         if (s390_is_imm16 (cfg->stack_offset)) {
4704                                 s390_aghi (code, ins->dreg, cfg->stack_offset);
4705                         } else if (s390_is_imm32 (cfg->stack_offset)) {
4706                                 s390_agfi (code, ins->dreg, cfg->stack_offset);
4707                         } else {
4708                                 S390_SET  (code, s390_r13, cfg->stack_offset);
4709                                 s390_agr  (code, ins->dreg, s390_r13);
4710                         }
4711                 }
4712                         break;  
4713                 case OP_MEMORY_BARRIER:
4714                         s390_mem (code);
4715                         break;
4716                 case OP_GC_SAFE_POINT: {
4717                         guint8 *br;
4718
4719                         g_assert (mono_threads_is_coop_enabled ());
4720
4721                         s390_chi (code, ins->sreg1, 1); 
4722                         s390_je  (code, 0); CODEPTR(code, br);
4723                         mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4724                                              mono_threads_state_poll);
4725                         S390_CALL_TEMPLATE (code, s390_r14);
4726                         PTRSLOT (code, br);
4727                         break;
4728                 }
4729                 case OP_GC_LIVENESS_DEF:
4730                 case OP_GC_LIVENESS_USE:
4731                 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4732                         ins->backend.pc_offset = code - cfg->native_code;
4733                         break;
4734                 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4735                         ins->backend.pc_offset = code - cfg->native_code;
4736                         bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4737                         break;
4738 #ifdef MONO_ARCH_SIMD_INTRINSICS
4739                 case OP_ADDPS:
4740                         s390x_addps (code, ins->sreg1, ins->sreg2);
4741                         break;
4742                 case OP_DIVPS:
4743                         s390x_divps (code, ins->sreg1, ins->sreg2);
4744                         break;
4745                 case OP_MULPS:
4746                         s390x_mulps (code, ins->sreg1, ins->sreg2);
4747                         break;
4748                 case OP_SUBPS:
4749                         s390x_subps (code, ins->sreg1, ins->sreg2);
4750                         break;
4751                 case OP_MAXPS:
4752                         s390x_maxps (code, ins->sreg1, ins->sreg2);
4753                         break;
4754                 case OP_MINPS:
4755                         s390x_minps (code, ins->sreg1, ins->sreg2);
4756                         break;
4757                 case OP_COMPPS:
4758                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4759                         s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4760                         break;
4761                 case OP_ANDPS:
4762                         s390x_andps (code, ins->sreg1, ins->sreg2);
4763                         break;
4764                 case OP_ANDNPS:
4765                         s390x_andnps (code, ins->sreg1, ins->sreg2);
4766                         break;
4767                 case OP_ORPS:
4768                         s390x_orps (code, ins->sreg1, ins->sreg2);
4769                         break;
4770                 case OP_XORPS:
4771                         s390x_xorps (code, ins->sreg1, ins->sreg2);
4772                         break;
4773                 case OP_SQRTPS:
4774                         s390x_sqrtps (code, ins->dreg, ins->sreg1);
4775                         break;
4776                 case OP_RSQRTPS:
4777                         s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4778                         break;
4779                 case OP_RCPPS:
4780                         s390x_rcpps (code, ins->dreg, ins->sreg1);
4781                         break;
4782                 case OP_ADDSUBPS:
4783                         s390x_addsubps (code, ins->sreg1, ins->sreg2);
4784                         break;
4785                 case OP_HADDPS:
4786                         s390x_haddps (code, ins->sreg1, ins->sreg2);
4787                         break;
4788                 case OP_HSUBPS:
4789                         s390x_hsubps (code, ins->sreg1, ins->sreg2);
4790                         break;
4791                 case OP_DUPPS_HIGH:
4792                         s390x_movshdup (code, ins->dreg, ins->sreg1);
4793                         break;
4794                 case OP_DUPPS_LOW:
4795                         s390x_movsldup (code, ins->dreg, ins->sreg1);
4796                         break;
4797
4798                 case OP_PSHUFLEW_HIGH:
4799                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4800                         s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4801                         break;
4802                 case OP_PSHUFLEW_LOW:
4803                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4804                         s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4805                         break;
4806                 case OP_PSHUFLED:
4807                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4808                         s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4809                         break;
4810                 case OP_SHUFPS:
4811                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4812                         s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4813                         break;
4814                 case OP_SHUFPD:
4815                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4816                         s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4817                         break;
4818
4819                 case OP_ADDPD:
4820                         s390x_addpd (code, ins->sreg1, ins->sreg2);
4821                         break;
4822                 case OP_DIVPD:
4823                         s390x_divpd (code, ins->sreg1, ins->sreg2);
4824                         break;
4825                 case OP_MULPD:
4826                         s390x_mulpd (code, ins->sreg1, ins->sreg2);
4827                         break;
4828                 case OP_SUBPD:
4829                         s390x_subpd (code, ins->sreg1, ins->sreg2);
4830                         break;
4831                 case OP_MAXPD:
4832                         s390x_maxpd (code, ins->sreg1, ins->sreg2);
4833                         break;
4834                 case OP_MINPD:
4835                         s390x_minpd (code, ins->sreg1, ins->sreg2);
4836                         break;
4837                 case OP_COMPPD:
4838                         g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4839                         s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4840                         break;
4841                 case OP_ANDPD:
4842                         s390x_andpd (code, ins->sreg1, ins->sreg2);
4843                         break;
4844                 case OP_ANDNPD:
4845                         s390x_andnpd (code, ins->sreg1, ins->sreg2);
4846                         break;
4847                 case OP_ORPD:
4848                         s390x_orpd (code, ins->sreg1, ins->sreg2);
4849                         break;
4850                 case OP_XORPD:
4851                         s390x_xorpd (code, ins->sreg1, ins->sreg2);
4852                         break;
4853                 case OP_SQRTPD:
4854                         s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4855                         break;
4856                 case OP_ADDSUBPD:
4857                         s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4858                         break;
4859                 case OP_HADDPD:
4860                         s390x_haddpd (code, ins->sreg1, ins->sreg2);
4861                         break;
4862                 case OP_HSUBPD:
4863                         s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4864                         break;
4865                 case OP_DUPPD:
4866                         s390x_movddup (code, ins->dreg, ins->sreg1);
4867                         break;
4868
4869                 case OP_EXTRACT_MASK:
4870                         s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4871                         break;
4872
4873                 case OP_PAND:
4874                         s390x_pand (code, ins->sreg1, ins->sreg2);
4875                         break;
4876                 case OP_POR:
4877                         s390x_por (code, ins->sreg1, ins->sreg2);
4878                         break;
4879                 case OP_PXOR:
4880                         s390x_pxor (code, ins->sreg1, ins->sreg2);
4881                         break;
4882
4883                 case OP_PADDB:
4884                         s390x_paddb (code, ins->sreg1, ins->sreg2);
4885                         break;
4886                 case OP_PADDW:
4887                         s390x_paddw (code, ins->sreg1, ins->sreg2);
4888                         break;
4889                 case OP_PADDD:
4890                         s390x_paddd (code, ins->sreg1, ins->sreg2);
4891                         break;
4892                 case OP_PADDQ:
4893                         s390x_paddq (code, ins->sreg1, ins->sreg2);
4894                         break;
4895
4896                 case OP_PSUBB:
4897                         s390x_psubb (code, ins->sreg1, ins->sreg2);
4898                         break;
4899                 case OP_PSUBW:
4900                         s390x_psubw (code, ins->sreg1, ins->sreg2);
4901                         break;
4902                 case OP_PSUBD:
4903                         s390x_psubd (code, ins->sreg1, ins->sreg2);
4904                         break;
4905                 case OP_PSUBQ:
4906                         s390x_psubq (code, ins->sreg1, ins->sreg2);
4907                         break;
4908
4909                 case OP_PMAXB_UN:
4910                         s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4911                         break;
4912                 case OP_PMAXW_UN:
4913                         s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4914                         break;
4915                 case OP_PMAXD_UN:
4916                         s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4917                         break;
4918                 
4919                 case OP_PMAXB:
4920                         s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4921                         break;
4922                 case OP_PMAXW:
4923                         s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4924                         break;
4925                 case OP_PMAXD:
4926                         s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4927                         break;
4928
4929                 case OP_PAVGB_UN:
4930                         s390x_pavgb (code, ins->sreg1, ins->sreg2);
4931                         break;
4932                 case OP_PAVGW_UN:
4933                         s390x_pavgw (code, ins->sreg1, ins->sreg2);
4934                         break;
4935
4936                 case OP_PMINB_UN:
4937                         s390x_pminub (code, ins->sreg1, ins->sreg2);
4938                         break;
4939                 case OP_PMINW_UN:
4940                         s390x_pminuw (code, ins->sreg1, ins->sreg2);
4941                         break;
4942                 case OP_PMIND_UN:
4943                         s390x_pminud (code, ins->sreg1, ins->sreg2);
4944                         break;
4945
4946                 case OP_PMINB:
4947                         s390x_pminsb (code, ins->sreg1, ins->sreg2);
4948                         break;
4949                 case OP_PMINW:
4950                         s390x_pminsw (code, ins->sreg1, ins->sreg2);
4951                         break;
4952                 case OP_PMIND:
4953                         s390x_pminsd (code, ins->sreg1, ins->sreg2);
4954                         break;
4955
4956                 case OP_PCMPEQB:
4957                         s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4958                         break;
4959                 case OP_PCMPEQW:
4960                         s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4961                         break;
4962                 case OP_PCMPEQD:
4963                         s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4964                         break;
4965                 case OP_PCMPEQQ:
4966                         s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4967                         break;
4968
4969                 case OP_PCMPGTB:
4970                         s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4971                         break;
4972                 case OP_PCMPGTW:
4973                         s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4974                         break;
4975                 case OP_PCMPGTD:
4976                         s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4977                         break;
4978                 case OP_PCMPGTQ:
4979                         s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4980                         break;
4981
4982                 case OP_PSUM_ABS_DIFF:
4983                         s390x_psadbw (code, ins->sreg1, ins->sreg2);
4984                         break;
4985
4986                 case OP_UNPACK_LOWB:
4987                         s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4988                         break;
4989                 case OP_UNPACK_LOWW:
4990                         s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4991                         break;
4992                 case OP_UNPACK_LOWD:
4993                         s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4994                         break;
4995                 case OP_UNPACK_LOWQ:
4996                         s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4997                         break;
4998                 case OP_UNPACK_LOWPS:
4999                         s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5000                         break;
5001                 case OP_UNPACK_LOWPD:
5002                         s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5003                         break;
5004
5005                 case OP_UNPACK_HIGHB:
5006                         s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5007                         break;
5008                 case OP_UNPACK_HIGHW:
5009                         s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5010                         break;
5011                 case OP_UNPACK_HIGHD:
5012                         s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5013                         break;
5014                 case OP_UNPACK_HIGHQ:
5015                         s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5016                         break;
5017                 case OP_UNPACK_HIGHPS:
5018                         s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5019                         break;
5020                 case OP_UNPACK_HIGHPD:
5021                         s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5022                         break;
5023
5024                 case OP_PACKW:
5025                         s390x_packsswb (code, ins->sreg1, ins->sreg2);
5026                         break;
5027                 case OP_PACKD:
5028                         s390x_packssdw (code, ins->sreg1, ins->sreg2);
5029                         break;
5030                 case OP_PACKW_UN:
5031                         s390x_packuswb (code, ins->sreg1, ins->sreg2);
5032                         break;
5033                 case OP_PACKD_UN:
5034                         s390x_packusdw (code, ins->sreg1, ins->sreg2);
5035                         break;
5036
5037                 case OP_PADDB_SAT_UN:
5038                         s390x_paddusb (code, ins->sreg1, ins->sreg2);
5039                         break;
5040                 case OP_PSUBB_SAT_UN:
5041                         s390x_psubusb (code, ins->sreg1, ins->sreg2);
5042                         break;
5043                 case OP_PADDW_SAT_UN:
5044                         s390x_paddusw (code, ins->sreg1, ins->sreg2);
5045                         break;
5046                 case OP_PSUBW_SAT_UN:
5047                         s390x_psubusw (code, ins->sreg1, ins->sreg2);
5048                         break;
5049
5050                 case OP_PADDB_SAT:
5051                         s390x_paddsb (code, ins->sreg1, ins->sreg2);
5052                         break;
5053                 case OP_PSUBB_SAT:
5054                         s390x_psubsb (code, ins->sreg1, ins->sreg2);
5055                         break;
5056                 case OP_PADDW_SAT:
5057                         s390x_paddsw (code, ins->sreg1, ins->sreg2);
5058                         break;
5059                 case OP_PSUBW_SAT:
5060                         s390x_psubsw (code, ins->sreg1, ins->sreg2);
5061                         break;
5062                         
5063                 case OP_PMULW:
5064                         s390x_pmullw (code, ins->sreg1, ins->sreg2);
5065                         break;
5066                 case OP_PMULD:
5067                         s390x_pmulld (code, ins->sreg1, ins->sreg2);
5068                         break;
5069                 case OP_PMULQ:
5070                         s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5071                         break;
5072                 case OP_PMULW_HIGH_UN:
5073                         s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5074                         break;
5075                 case OP_PMULW_HIGH:
5076                         s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5077                         break;
5078
5079                 case OP_PSHRW:
5080                         s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5081                         break;
5082                 case OP_PSHRW_REG:
5083                         s390x_psrlw (code, ins->dreg, ins->sreg2);
5084                         break;
5085
5086                 case OP_PSARW:
5087                         s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5088                         break;
5089                 case OP_PSARW_REG:
5090                         s390x_psraw (code, ins->dreg, ins->sreg2);
5091                         break;
5092
5093                 case OP_PSHLW:
5094                         s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5095                         break;
5096                 case OP_PSHLW_REG:
5097                         s390x_psllw (code, ins->dreg, ins->sreg2);
5098                         break;
5099
5100                 case OP_PSHRD:
5101                         s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5102                         break;
5103                 case OP_PSHRD_REG:
5104                         s390x_psrld (code, ins->dreg, ins->sreg2);
5105                         break;
5106
5107                 case OP_PSARD:
5108                         s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5109                         break;
5110                 case OP_PSARD_REG:
5111                         s390x_psrad (code, ins->dreg, ins->sreg2);
5112                         break;
5113
5114                 case OP_PSHLD:
5115                         s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5116                         break;
5117                 case OP_PSHLD_REG:
5118                         s390x_pslld (code, ins->dreg, ins->sreg2);
5119                         break;
5120
5121                 case OP_PSHRQ:
5122                         s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5123                         break;
5124                 case OP_PSHRQ_REG:
5125                         s390x_psrlq (code, ins->dreg, ins->sreg2);
5126                         break;
5127                 
5128                 /*TODO: This is appart of the sse spec but not added
5129                 case OP_PSARQ:
5130                         s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5131                         break;
5132                 case OP_PSARQ_REG:
5133                         s390x_psraq (code, ins->dreg, ins->sreg2);
5134                         break;  
5135                 */
5136         
5137                 case OP_PSHLQ:
5138                         s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5139                         break;
5140                 case OP_PSHLQ_REG:
5141                         s390x_psllq (code, ins->dreg, ins->sreg2);
5142                         break;  
5143                 case OP_CVTDQ2PD:
5144                         s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5145                         break;
5146                 case OP_CVTDQ2PS:
5147                         s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5148                         break;
5149                 case OP_CVTPD2DQ:
5150                         s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5151                         break;
5152                 case OP_CVTPD2PS:
5153                         s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5154                         break;
5155                 case OP_CVTPS2DQ:
5156                         s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5157                         break;
5158                 case OP_CVTPS2PD:
5159                         s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5160                         break;
5161                 case OP_CVTTPD2DQ:
5162                         s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5163                         break;
5164                 case OP_CVTTPS2DQ:
5165                         s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5166                         break;
5167
5168                 case OP_ICONV_TO_X:
5169                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5170                         break;
5171                 case OP_EXTRACT_I4:
5172                         amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5173                         break;
5174                 case OP_EXTRACT_I8:
5175                         if (ins->inst_c0) {
5176                                 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5177                                 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5178                         } else {
5179                                 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5180                         }
5181                         break;
5182                 case OP_EXTRACT_I1:
5183                 case OP_EXTRACT_U1:
5184                         amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5185                         if (ins->inst_c0)
5186                                 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5187                         amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5188                         break;
5189                 case OP_EXTRACT_I2:
5190                 case OP_EXTRACT_U2:
5191                         /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5192                         if (ins->inst_c0)
5193                                 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5194                         s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5195                         amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5196                         break;
5197                 case OP_EXTRACT_R8:
5198                         if (ins->inst_c0)
5199                                 amd64_movhlps (code, ins->dreg, ins->sreg1);
5200                         else
5201                                 s390x_movsd (code, ins->dreg, ins->sreg1);
5202                         break;
5203                 case OP_INSERT_I2:
5204                         s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5205                         break;
5206                 case OP_EXTRACTX_U2:
5207                         s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5208                         break;
5209                 case OP_INSERTX_U1_SLOW:
5210                         /*sreg1 is the extracted ireg (scratch)
5211                         /sreg2 is the to be inserted ireg (scratch)
5212                         /dreg is the xreg to receive the value*/
5213
5214                         /*clear the bits from the extracted word*/
5215                         amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5216                         /*shift the value to insert if needed*/
5217                         if (ins->inst_c0 & 1)
5218                                 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5219                         /*join them together*/
5220                         amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5221                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5222                         break;
5223                 case OP_INSERTX_I4_SLOW:
5224                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5225                         amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5226                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5227                         break;
5228                 case OP_INSERTX_I8_SLOW:
5229                         amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5230                         if (ins->inst_c0)
5231                                 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5232                         else
5233                                 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5234                         break;
5235
5236                 case OP_INSERTX_R4_SLOW:
5237                         switch (ins->inst_c0) {
5238                         case 0:
5239                                 if (cfg->r4fp)
5240                                         s390x_movss (code, ins->dreg, ins->sreg2);
5241                                 else
5242                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5243                                 break;
5244                         case 1:
5245                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5246                                 if (cfg->r4fp)
5247                                         s390x_movss (code, ins->dreg, ins->sreg2);
5248                                 else
5249                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5250                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5251                                 break;
5252                         case 2:
5253                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5254                                 if (cfg->r4fp)
5255                                         s390x_movss (code, ins->dreg, ins->sreg2);
5256                                 else
5257                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5258                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5259                                 break;
5260                         case 3:
5261                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5262                                 if (cfg->r4fp)
5263                                         s390x_movss (code, ins->dreg, ins->sreg2);
5264                                 else
5265                                         s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5266                                 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5267                                 break;
5268                         }
5269                         break;
5270                 case OP_INSERTX_R8_SLOW:
5271                         if (ins->inst_c0)
5272                                 amd64_movlhps (code, ins->dreg, ins->sreg2);
5273                         else
5274                                 s390x_movsd (code, ins->dreg, ins->sreg2);
5275                         break;
5276                 case OP_STOREX_MEMBASE_REG:
5277                 case OP_STOREX_MEMBASE:
5278                         s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5279                         break;
5280                 case OP_LOADX_MEMBASE:
5281                         s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5282                         break;
5283                 case OP_LOADX_ALIGNED_MEMBASE:
5284                         s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5285                         break;
5286                 case OP_STOREX_ALIGNED_MEMBASE_REG:
5287                         s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5288                         break;
5289                 case OP_STOREX_NTA_MEMBASE_REG:
5290                         s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5291                         break;
5292                 case OP_PREFETCH_MEMBASE:
5293                         s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5294                         break;
5295
5296                 case OP_XMOVE:
5297                         /*FIXME the peephole pass should have killed this*/
5298                         if (ins->dreg != ins->sreg1)
5299                                 s390x_movaps (code, ins->dreg, ins->sreg1);
5300                         break;          
5301                 case OP_XZERO:
5302                         s390x_pxor (code, ins->dreg, ins->dreg);
5303                         break;
5304                 case OP_ICONV_TO_R4_RAW:
5305                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5306                         break;
5307
5308                 case OP_FCONV_TO_R8_X:
5309                         s390x_movsd (code, ins->dreg, ins->sreg1);
5310                         break;
5311
5312                 case OP_XCONV_R8_TO_I4:
5313                         s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5314                         switch (ins->backend.source_opcode) {
5315                         case OP_FCONV_TO_I1:
5316                                 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5317                                 break;
5318                         case OP_FCONV_TO_U1:
5319                                 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5320                                 break;
5321                         case OP_FCONV_TO_I2:
5322                                 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5323                                 break;
5324                         case OP_FCONV_TO_U2:
5325                                 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5326                                 break;
5327                         }                       
5328                         break;
5329
5330                 case OP_EXPAND_I2:
5331                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5332                         s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5333                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5334                         break;
5335                 case OP_EXPAND_I4:
5336                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5337                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5338                         break;
5339                 case OP_EXPAND_I8:
5340                         amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5341                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5342                         break;
5343                 case OP_EXPAND_R4:
5344                         if (cfg->r4fp) {
5345                                 s390x_movsd (code, ins->dreg, ins->sreg1);
5346                         } else {
5347                                 s390x_movsd (code, ins->dreg, ins->sreg1);
5348                                 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5349                         }
5350                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5351                         break;
5352                 case OP_EXPAND_R8:
5353                         s390x_movsd (code, ins->dreg, ins->sreg1);
5354                         s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5355                         break;
5356 #endif
5357                 default:
5358                         g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5359                         g_assert_not_reached ();
5360                 }
5361
5362                 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5363                         g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5364                                    mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5365                         g_assert_not_reached ();
5366                 }
5367                
5368                 last_offset = offset;
5369         }
5370
5371         cfg->code_len = code - cfg->native_code;
5372 }
5373
5374 /*========================= End of Function ========================*/
5375
5376 /*------------------------------------------------------------------*/
5377 /*                                                                  */
5378 /* Name         - mono_arch_register_lowlevel_calls                 */
5379 /*                                                                  */
5380 /* Function     - Register routines to help with --trace operation. */
5381 /*                                                                  */
5382 /*------------------------------------------------------------------*/
5383
5384 void
5385 mono_arch_register_lowlevel_calls (void)
5386 {
5387 }
5388
5389 /*========================= End of Function ========================*/
5390
5391 /*------------------------------------------------------------------*/
5392 /*                                                                  */
5393 /* Name         - mono_arch_patch_code                              */
5394 /*                                                                  */
5395 /* Function     - Process the patch data created during the         */
5396 /*                instruction build process. This resolves jumps,   */
5397 /*                calls, variables etc.                             */
5398 /*                                                                  */
5399 /*------------------------------------------------------------------*/
5400
5401 void
5402 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain, 
5403                       guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5404                       MonoError *error)
5405 {
5406         MonoJumpInfo *patch_info;
5407
5408         error_init (error);
5409
5410         for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5411                 unsigned char *ip = patch_info->ip.i + code;
5412                 gconstpointer target = NULL;
5413
5414                 target = mono_resolve_patch_target (method, domain, code, 
5415                                                                                         patch_info, run_cctors, error);
5416                 return_if_nok (error);
5417
5418                 switch (patch_info->type) {
5419                         case MONO_PATCH_INFO_IP:
5420                         case MONO_PATCH_INFO_LDSTR:
5421                         case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
5422                         case MONO_PATCH_INFO_LDTOKEN: 
5423                         case MONO_PATCH_INFO_EXC:
5424                                 s390_patch_addr (ip, (guint64) target);
5425                                 continue;
5426                         case MONO_PATCH_INFO_METHOD:
5427                         case MONO_PATCH_INFO_INTERNAL_METHOD:
5428                         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5429                         case MONO_PATCH_INFO_RGCTX_FETCH:
5430                         case MONO_PATCH_INFO_ABS: {
5431                                 S390_EMIT_CALL (ip, target);
5432                                 continue;
5433                         }
5434                         case MONO_PATCH_INFO_SWITCH: 
5435                                 /*----------------------------------*/
5436                                 /* ip points at the basr r13,0/j +4 */
5437                                 /* instruction the vtable value     */
5438                                 /* follows this (i.e. ip+6)         */
5439                                 /*----------------------------------*/
5440                                 S390_EMIT_LOAD (ip, target);
5441                                 continue;
5442                         case MONO_PATCH_INFO_METHODCONST:
5443                         case MONO_PATCH_INFO_CLASS:
5444                         case MONO_PATCH_INFO_IMAGE:
5445                         case MONO_PATCH_INFO_FIELD:
5446                         case MONO_PATCH_INFO_IID:
5447                         case MONO_PATCH_INFO_EXC_NAME:
5448                                 target = S390_RELATIVE(target, ip);
5449                                 s390_patch_rel (ip, (guint64) target);
5450                                 continue;
5451                         case MONO_PATCH_INFO_R4:
5452                         case MONO_PATCH_INFO_R8:
5453                         case MONO_PATCH_INFO_METHOD_REL:
5454                                 g_assert_not_reached ();
5455                                 continue;
5456                         default:
5457                                 target = S390_RELATIVE(target, ip);
5458                                 ip += 2;
5459                                 s390_patch_rel (ip, (guint64) target);
5460                 }
5461         }
5462 }
5463
5464 /*========================= End of Function ========================*/
5465
5466 /*------------------------------------------------------------------*/
5467 /*                                                                  */
5468 /* Name         - emit_load_volatile_arguments                      */
5469 /*                                                                  */
5470 /* Function     - Emit the instructions to reload parameter regist- */
5471 /*                registers for use with "tail" operations.         */
5472 /*                                                                  */
5473 /*                The register loading operations performed here    */
5474 /*                are the mirror of the store operations performed  */
5475 /*                in mono_arch_emit_prolog and need to be kept in   */
5476 /*                synchronization with it.                          */
5477 /*                                                                  */
5478 /*------------------------------------------------------------------*/
5479
5480 guint8 *
5481 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5482 {
5483         MonoInst *inst;
5484         MonoMethod *method = cfg->method;
5485         MonoMethodSignature *sig = mono_method_signature(method);
5486         int pos = 0, i;
5487         CallInfo *cinfo;
5488
5489         cinfo = get_call_info (NULL, NULL, sig);
5490
5491         if (cinfo->struct_ret) {
5492                 ArgInfo *ainfo = &cinfo->ret;
5493                 inst         = cfg->vret_addr;
5494                 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5495         }
5496
5497         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5498                 ArgInfo *ainfo = cinfo->args + i;
5499                 inst = cfg->args [pos];
5500
5501                 if (inst->opcode == OP_REGVAR) {
5502                         if (ainfo->regtype == RegTypeGeneral)
5503                                 s390_lgr (code, ainfo->reg, inst->dreg);
5504                         else if (ainfo->regtype == RegTypeFP) {
5505                                 if (inst->dreg != ainfo->reg) {
5506                                         if (ainfo->size == 4) {
5507                                                 s390_ldebr (code, ainfo->reg, inst->dreg);
5508                                         } else {
5509                                                 s390_ldr   (code, ainfo->reg, inst->dreg);
5510                                         }
5511                                 }
5512                         }
5513                         else if (ainfo->regtype == RegTypeBase) {
5514                         } else
5515                                 g_assert_not_reached ();
5516                 } else {
5517                         if (ainfo->regtype == RegTypeGeneral) {
5518                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5519                                         g_assert_not_reached();
5520                                 switch (ainfo->size) {
5521                                 case 1:
5522                                         s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5523                                         break;
5524                                 case 2:
5525                                         s390_lgh  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5526                                         break;
5527                                 case 4: 
5528                                         s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5529                                         break;
5530                                 case 8:
5531                                         s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532                                         break;
5533                                 }
5534                         } else if (ainfo->regtype == RegTypeBase) {
5535                         } else if (ainfo->regtype == RegTypeFP) {
5536                                 if (ainfo->size == 8)
5537                                         s390_ld  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538                                 else if (ainfo->size == 4)
5539                                         s390_le  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5540                                 else
5541                                         g_assert_not_reached ();
5542                         } else if (ainfo->regtype == RegTypeStructByVal) {
5543                                 if (ainfo->reg != STK_BASE) {
5544                                         switch (ainfo->size) {
5545                                         case 1:
5546                                                 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5547                                                 break;
5548                                         case 2:
5549                                                 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550                                                 break;
5551                                         case 4:
5552                                                 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5553                                                 break;
5554                                         case 8:
5555                                                 s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5556                                                 break;
5557                                         }
5558                                 }
5559                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5560                                 if (ainfo->reg != STK_BASE) {
5561                                         s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5562                                 }
5563                         } else
5564                                 g_assert_not_reached ();
5565                 }
5566                 pos++;
5567         }
5568
5569         return code;
5570 }
5571
5572 /*========================= End of Function ========================*/
5573
5574 /*------------------------------------------------------------------*/
5575 /*                                                                  */
5576 /* Name         - mono_arch_emit_prolog                             */
5577 /*                                                                  */
5578 /* Function     - Create the instruction sequence for a function    */
5579 /*                prolog.                                           */
5580 /*                                                                  */
5581 /*------------------------------------------------------------------*/
5582
5583 guint8 *
5584 mono_arch_emit_prolog (MonoCompile *cfg)
5585 {
5586         MonoMethod *method = cfg->method;
5587         MonoBasicBlock *bb;
5588         MonoMethodSignature *sig;
5589         MonoInst *inst;
5590         long alloc_size, pos, max_offset, i, cfa_offset = 0;
5591         guint8 *code;
5592         guint32 size;
5593         CallInfo *cinfo;
5594         int tracing = 0,
5595             argsClobbered = 0,
5596             lmfOffset,
5597             fpOffset;
5598
5599         cfg->code_size   = 512;
5600
5601         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5602                 tracing         = 1;
5603                 cfg->code_size += 256;
5604         }
5605
5606         if (method->save_lmf)
5607                 cfg->code_size += 200;
5608
5609         cfg->native_code = code = g_malloc (cfg->code_size);
5610
5611         mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5612         emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5613         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5614         mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5615         mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5616
5617         if (cfg->arch.bkchain_reg != -1)
5618                 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5619
5620         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5621                 cfg->used_int_regs |= 1 << 11;
5622         }
5623
5624         alloc_size = cfg->stack_offset;
5625
5626         cfg->stack_usage = cfa_offset = alloc_size;
5627         mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5628         s390_lgr  (code, s390_r11, STK_BASE);
5629         if (s390_is_imm16 (alloc_size)) {
5630                 s390_aghi (code, STK_BASE, -alloc_size);
5631         } else if (s390_is_imm32 (alloc_size)) { 
5632                 s390_agfi (code, STK_BASE, -alloc_size);
5633         } else {
5634                 int stackSize = alloc_size;
5635                 while (stackSize > INT_MAX) {
5636                         s390_agfi (code, STK_BASE, -INT_MAX);
5637                         stackSize -= INT_MAX;
5638                 }
5639                 s390_agfi (code, STK_BASE, -stackSize);
5640         }
5641         s390_stg  (code, s390_r11, 0, STK_BASE, 0);
5642
5643         if (cfg->frame_reg != STK_BASE)
5644                 s390_lgr (code, s390_r11, STK_BASE);
5645
5646         mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5647
5648         /* store runtime generic context */
5649         if (cfg->rgctx_var) {
5650                 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5651
5652                 s390_stg  (code, MONO_ARCH_RGCTX_REG, 0, 
5653                            cfg->rgctx_var->inst_basereg, 
5654                            cfg->rgctx_var->inst_offset);
5655         }
5656
5657         /* compute max_offset in order to use short forward jumps
5658          * we always do it on s390 because the immediate displacement
5659          * for jumps is too small 
5660          */
5661         max_offset = 0;
5662         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5663                 MonoInst *ins;
5664                 bb->max_offset = max_offset;
5665
5666                 MONO_BB_FOR_EACH_INS (bb, ins)
5667                         max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5668         }
5669
5670         /* load arguments allocated to register from the stack */
5671         sig = mono_method_signature (method);
5672         pos = 0;
5673
5674         cinfo = get_call_info (cfg, cfg->mempool, sig);
5675
5676         if (cinfo->struct_ret) {
5677                 ArgInfo *ainfo     = &cinfo->ret;
5678                 inst               = cfg->vret_addr;
5679                 inst->backend.size = ainfo->vtsize;
5680                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5681         }
5682
5683         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5684                 ArgInfo *ainfo = cinfo->args + i;
5685                 inst = cfg->args [pos];
5686                 
5687                 if (inst->opcode == OP_VTARG_ADDR)
5688                         inst = inst->inst_left;
5689
5690                 if (inst->opcode == OP_REGVAR) {
5691                         if (ainfo->regtype == RegTypeGeneral)
5692                                 s390_lgr (code, inst->dreg, ainfo->reg);
5693                         else if (ainfo->regtype == RegTypeFP) {
5694                                 if (inst->dreg != ainfo->reg) {
5695                                         if (ainfo->size == 4) {
5696                                                 s390_ledbr (code, inst->dreg, ainfo->reg);
5697                                         } else {
5698                                                 s390_ldr   (code, inst->dreg, ainfo->reg);
5699                                         }
5700                                 }
5701                         }
5702                         else if (ainfo->regtype == RegTypeBase) {
5703                                 s390_lgr  (code, s390_r13, STK_BASE);
5704                                 s390_aghi (code, s390_r13, alloc_size);
5705                                 s390_lg   (code, inst->dreg, 0, s390_r13, ainfo->offset);
5706                         } else
5707                                 g_assert_not_reached ();
5708
5709                         if (cfg->verbose_level > 2)
5710                                 g_print ("Argument %d assigned to register %s\n", 
5711                                          pos, mono_arch_regname (inst->dreg));
5712                 } else {
5713                         if (ainfo->regtype == RegTypeGeneral) {
5714                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5715                                         g_assert_not_reached();
5716                                 switch (ainfo->size) {
5717                                 case 1:
5718                                         s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5719                                         break;
5720                                 case 2:
5721                                         s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5722                                         break;
5723                                 case 4: 
5724                                         s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5725                                         break;
5726                                 case 8:
5727                                         s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5728                                         break;
5729                                 }
5730                         } else if (ainfo->regtype == RegTypeBase) {
5731                         } else if (ainfo->regtype == RegTypeFP) {
5732                                 if (ainfo->size == 8)
5733                                         s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5734                                 else if (ainfo->size == 4)
5735                                         s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5736                                 else
5737                                         g_assert_not_reached ();
5738                         } else if (ainfo->regtype == RegTypeStructByVal) {
5739                                 int doffset = inst->inst_offset;
5740                                 int reg;
5741                                 if (ainfo->reg != STK_BASE)
5742                                         reg = ainfo->reg;
5743                                 else {
5744                                         reg = s390_r0;
5745                                         s390_lgr  (code, s390_r13, STK_BASE);
5746                                         s390_aghi (code, s390_r13, alloc_size);
5747                                 }
5748
5749                                 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE  
5750                                         ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5751                                         : ainfo->size);
5752
5753                                 switch (size) {
5754                                         case 1:
5755                                                 if (ainfo->reg == STK_BASE)
5756                                                         s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5757                                                 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5758                                                 break;
5759                                         case 2:
5760                                                 if (ainfo->reg == STK_BASE)
5761                                                         s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5762                                                 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5763                                                 break;
5764                                         case 4:
5765                                                 if (ainfo->reg == STK_BASE)
5766                                                         s390_l  (code, reg, 0, s390_r13, ainfo->offset+4);
5767                                                 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5768                                                 break;
5769                                         case 8:
5770                                                 if (ainfo->reg == STK_BASE)
5771                                                         s390_lg  (code, reg, 0, s390_r13, ainfo->offset);
5772                                                 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5773                                                 break;
5774                                 }
5775                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5776                                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5777                         } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5778                         } else
5779                                 g_assert_not_reached ();
5780                 }
5781                 pos++;
5782         }
5783
5784         if (method->save_lmf) {
5785                 /*---------------------------------------------------------------*/
5786                 /* build the MonoLMF structure on the stack - see mini-s390x.h   */
5787                 /*---------------------------------------------------------------*/
5788                 lmfOffset = alloc_size - sizeof(MonoLMF);       
5789                                                                                         
5790                 s390_lgr   (code, s390_r13, cfg->frame_reg);            
5791                 s390_aghi  (code, s390_r13, lmfOffset);                                 
5792                                                                                         
5793                 /*---------------------------------------------------------------*/
5794                 /* Preserve the parameter registers while we fix up the lmf      */
5795                 /*---------------------------------------------------------------*/
5796                 s390_stmg  (code, s390_r2, s390_r6, s390_r13,
5797                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5798
5799                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5800                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5801                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5802                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5803                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5804
5805                 /*---------------------------------------------------------------*/
5806                 /* On return from this call r2 have the address of the &lmf      */
5807                 /*---------------------------------------------------------------*/
5808                 mono_add_patch_info (cfg, code - cfg->native_code, 
5809                                 MONO_PATCH_INFO_INTERNAL_METHOD, 
5810                                 (gpointer)"mono_tls_get_lmf_addr");
5811                 S390_CALL_TEMPLATE(code, s390_r1);
5812
5813                 /*---------------------------------------------------------------*/     
5814                 /* Set lmf.lmf_addr = jit_tls->lmf                               */     
5815                 /*---------------------------------------------------------------*/     
5816                 s390_stg   (code, s390_r2, 0, s390_r13,                                 
5817                             G_STRUCT_OFFSET(MonoLMF, lmf_addr));                        
5818                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5819                                                                                         
5820                 /*---------------------------------------------------------------*/     
5821                 /* Get current lmf                                               */     
5822                 /*---------------------------------------------------------------*/     
5823                 s390_lg    (code, s390_r0, 0, s390_r2, 0);                              
5824                                                                                         
5825                 /*---------------------------------------------------------------*/     
5826                 /* Set our lmf as the current lmf                                */     
5827                 /*---------------------------------------------------------------*/     
5828                 s390_stg   (code, s390_r13, 0, s390_r2, 0);                             
5829                                                                                         
5830                 /*---------------------------------------------------------------*/     
5831                 /* Have our lmf.previous_lmf point to the last lmf               */     
5832                 /*---------------------------------------------------------------*/     
5833                 s390_stg   (code, s390_r0, 0, s390_r13,                                 
5834                             G_STRUCT_OFFSET(MonoLMF, previous_lmf));                    
5835                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5836                                                                                         
5837                 /*---------------------------------------------------------------*/     
5838                 /* save method info                                              */     
5839                 /*---------------------------------------------------------------*/     
5840                 S390_SET   (code, s390_r1, method);
5841                 s390_stg   (code, s390_r1, 0, s390_r13,                                 
5842                             G_STRUCT_OFFSET(MonoLMF, method));                          
5843                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5844                                                                                 
5845                 /*---------------------------------------------------------------*/     
5846                 /* save the current IP                                           */     
5847                 /*---------------------------------------------------------------*/     
5848                 s390_stg   (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5849                 s390_basr  (code, s390_r1, 0);
5850                 s390_stg   (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); 
5851                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5852                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5853                                                                                         
5854                 /*---------------------------------------------------------------*/     
5855                 /* Save general and floating point registers                     */     
5856                 /*---------------------------------------------------------------*/     
5857                 s390_stmg  (code, s390_r2, s390_r12, s390_r13,                          
5858                             G_STRUCT_OFFSET(MonoLMF, gregs[2]));                        
5859                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5860                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5861                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5862                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5863                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5864                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5865                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5866                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5867                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5868                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5869                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5870
5871                 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5872                 for (i = 0; i < 16; i++) {                                              
5873                         s390_std  (code, i, 0, s390_r13,                                
5874                                    G_STRUCT_OFFSET(MonoLMF, fregs[i]));                 
5875                         mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5876                         fpOffset += sizeof(double);
5877                 }                                                                       
5878
5879                 /*---------------------------------------------------------------*/
5880                 /* Restore the parameter registers now that we've set up the lmf */
5881                 /*---------------------------------------------------------------*/
5882                 s390_lmg   (code, s390_r2, s390_r6, s390_r13,                           
5883                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));                        
5884         }
5885
5886         if (cfg->method->save_lmf)
5887                 argsClobbered = TRUE;
5888
5889         if (tracing) {
5890                 argsClobbered = TRUE;
5891                 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5892         }
5893
5894         /*
5895          * Optimize the common case of the first bblock making a call with the same
5896          * arguments as the method. This works because the arguments are still in their
5897          * original argument registers.
5898          */
5899         if (!argsClobbered) {
5900                 MonoBasicBlock *first_bb = cfg->bb_entry;
5901                 MonoInst *next;
5902                 int filter = FILTER_IL_SEQ_POINT;
5903
5904                 next = mono_bb_first_inst (first_bb, filter);
5905                 if (!next && first_bb->next_bb) {
5906                         first_bb = first_bb->next_bb;
5907                         next = mono_bb_first_inst (first_bb, filter);
5908                 }
5909
5910                 if (first_bb->in_count > 1)
5911                         next = NULL;
5912
5913                 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5914                         ArgInfo *ainfo = cinfo->args + i;
5915                         gboolean match = FALSE;
5916
5917                         inst = cfg->args [i];
5918                         if (inst->opcode != OP_REGVAR) {
5919                                 switch (ainfo->regtype) {
5920                                 case RegTypeGeneral: {
5921                                         if (((next->opcode == OP_LOAD_MEMBASE) || 
5922                                              (next->opcode == OP_LOADI4_MEMBASE)) && 
5923                                              next->inst_basereg == inst->inst_basereg && 
5924                                              next->inst_offset == inst->inst_offset) {
5925                                                 if (next->dreg == ainfo->reg) {
5926                                                         NULLIFY_INS (next);
5927                                                         match = TRUE;
5928                                                 } else {
5929                                                         next->opcode = OP_MOVE;
5930                                                         next->sreg1 = ainfo->reg;
5931                                                         /* Only continue if the instruction doesn't change argument regs */
5932                                                         if (next->dreg == ainfo->reg)
5933                                                                 match = TRUE;
5934                                                 }
5935                                         }
5936                                         break;
5937                                 }
5938                                 default:
5939                                         break;
5940                                 }
5941                         } else {
5942                                 /* Argument allocated to (non-volatile) register */
5943                                 switch (ainfo->regtype) {
5944                                 case RegTypeGeneral:
5945                                         if (next->opcode == OP_MOVE && 
5946                                             next->sreg1 == inst->dreg && 
5947                                             next->dreg == ainfo->reg) {
5948                                                 NULLIFY_INS (next);
5949                                                 match = TRUE;
5950                                         }
5951                                         break;
5952                                 default:
5953                                         break;
5954                                 }
5955                         }
5956
5957                         if (match) {
5958                                 next = mono_inst_next (next, filter);
5959                                 if (!next)
5960                                         break;
5961                         }
5962                 }
5963         }
5964
5965         cfg->code_len = code - cfg->native_code;
5966         g_assert (cfg->code_len < cfg->code_size);
5967
5968         return code;
5969 }
5970
5971 /*========================= End of Function ========================*/
5972
5973 /*------------------------------------------------------------------*/
5974 /*                                                                  */
5975 /* Name         - mono_arch_emit_epilog                             */
5976 /*                                                                  */
5977 /* Function     - Emit the instructions for a function epilog.      */
5978 /*                                                                  */
5979 /*------------------------------------------------------------------*/
5980
5981 void
5982 mono_arch_emit_epilog (MonoCompile *cfg)
5983 {
5984         MonoMethod *method = cfg->method;
5985         int tracing = 0;
5986         guint8 *code;
5987         int max_epilog_size = 96;
5988         
5989         if (cfg->method->save_lmf)
5990                 max_epilog_size += 128;
5991         
5992         if (mono_jit_trace_calls != NULL)
5993                 max_epilog_size += 128;
5994         
5995         while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
5996                 cfg->code_size  *= 2;
5997                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
5998                 cfg->stat_code_reallocs++;
5999         }
6000
6001         code = cfg->native_code + cfg->code_len;
6002
6003         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6004                 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6005                 tracing = 1;
6006         }
6007         
6008         if (method->save_lmf) 
6009                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6010
6011         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6012                 s390_lg  (code, STK_BASE, 0, STK_BASE, 0);
6013         } else
6014                 code = backUpStackPtr(cfg, code);
6015
6016         s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6017         s390_br  (code, s390_r14);
6018
6019         cfg->code_len = code - cfg->native_code;
6020
6021         g_assert (cfg->code_len < cfg->code_size);
6022
6023 }
6024
6025 /*========================= End of Function ========================*/
6026
6027 /*------------------------------------------------------------------*/
6028 /*                                                                  */
6029 /* Name         - mono_arch_emit_exceptions                         */
6030 /*                                                                  */
6031 /* Function     - Emit the blocks to handle exception conditions.   */
6032 /*                                                                  */
6033 /*------------------------------------------------------------------*/
6034
6035 void
6036 mono_arch_emit_exceptions (MonoCompile *cfg) 
6037 {
6038         MonoJumpInfo    *patch_info;
6039         guint8          *code;
6040         int             nThrows = 0,
6041                         exc_count = 0,
6042                         iExc;
6043         guint32         code_size;
6044         MonoClass       *exc_classes [MAX_EXC];
6045         guint8          *exc_throw_start [MAX_EXC];
6046
6047         for (patch_info = cfg->patch_info; 
6048              patch_info; 
6049              patch_info = patch_info->next) {
6050                 if (patch_info->type == MONO_PATCH_INFO_EXC)
6051                         exc_count++;
6052         }
6053
6054         code_size = exc_count * 48;
6055
6056         while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6057                 cfg->code_size  *= 2;
6058                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6059                 cfg->stat_code_reallocs++; 
6060         }
6061
6062         code = cfg->native_code + cfg->code_len;
6063
6064         /*---------------------------------------------------------------------*/
6065         /* Add code to raise exceptions                                        */
6066         /*---------------------------------------------------------------------*/
6067         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6068                 switch (patch_info->type) {
6069                 case MONO_PATCH_INFO_EXC: {
6070                         guint8 *ip = patch_info->ip.i + cfg->native_code;
6071                         MonoClass *exc_class;
6072                         guint64 throw_ip;
6073
6074                         /*-----------------------------------------------------*/
6075                         /* Patch the branch in epilog to come here             */
6076                         /*-----------------------------------------------------*/
6077                         s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6078
6079                         exc_class = mono_class_load_from_name (mono_defaults.corlib,
6080                                                           "System", 
6081                                                           patch_info->data.name);
6082                         throw_ip = patch_info->ip.i;
6083
6084                         for (iExc = 0; iExc < nThrows; ++iExc)
6085                                 if (exc_classes [iExc] == exc_class)
6086                                         break;
6087                 
6088                         if (iExc < nThrows) {
6089                                 s390_jcl (code, S390_CC_UN, 
6090                                           (guint64) exc_throw_start [iExc]);
6091                                 patch_info->type = MONO_PATCH_INFO_NONE;
6092                         } else {
6093         
6094                                 if (nThrows < MAX_EXC) {
6095                                         exc_classes [nThrows]     = exc_class;
6096                                         exc_throw_start [nThrows] = code;
6097                                 }
6098         
6099                                 /*---------------------------------------------*/
6100                                 /* Patch the parameter passed to the handler   */ 
6101                                 /*---------------------------------------------*/
6102                                 S390_SET  (code, s390_r2, exc_class->type_token);
6103                                 /*---------------------------------------------*/
6104                                 /* Load return address & parameter register    */
6105                                 /*---------------------------------------------*/
6106                                 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6107                                                            cfg->native_code + 8), code));
6108                                 /*---------------------------------------------*/
6109                                 /* Reuse the current patch to set the jump     */
6110                                 /*---------------------------------------------*/
6111                                 patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
6112                                 patch_info->data.name = "mono_arch_throw_corlib_exception";
6113                                 patch_info->ip.i      = code - cfg->native_code;
6114                                 S390_BR_TEMPLATE (code, s390_r1);
6115                         }
6116                         break;
6117                 }
6118                 default:
6119                         /* do nothing */
6120                         break;
6121                 }
6122         }
6123
6124         cfg->code_len = code - cfg->native_code;
6125
6126         g_assert (cfg->code_len < cfg->code_size);
6127
6128 }
6129
6130 /*========================= End of Function ========================*/
6131
6132 /*------------------------------------------------------------------*/
6133 /*                                                                  */
6134 /* Name         - mono_arch_finish_init                                 */
6135 /*                                                                  */
6136 /* Function     - Setup the JIT's Thread Level Specific Data.       */
6137 /*                                                                  */
6138 /*------------------------------------------------------------------*/
6139
6140 void
6141 mono_arch_finish_init (void)
6142 {
6143 }
6144
6145 /*========================= End of Function ========================*/
6146
6147 /*------------------------------------------------------------------*/
6148 /*                                                                  */
6149 /* Name         - mono_arch_free_jit_tls_data                       */
6150 /*                                                                  */
6151 /* Function     - Free tls data.                                    */
6152 /*                                                                  */
6153 /*------------------------------------------------------------------*/
6154
6155 void
6156 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6157 {
6158 }
6159
6160 /*========================= End of Function ========================*/
6161
6162 /*------------------------------------------------------------------*/
6163 /*                                                                  */
6164 /* Name         - mono_arch_emit_inst_for_method                    */
6165 /*                                                                  */
6166 /*------------------------------------------------------------------*/
6167
6168 MonoInst*
6169 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6170 {
6171         return NULL;
6172 }
6173
6174 /*========================= End of Function ========================*/
6175
6176 /*------------------------------------------------------------------*/
6177 /*                                                                  */
6178 /* Name         - mono_arch_decompose_opts                          */
6179 /*                                                                  */
6180 /* Function     - Decompose opcode into a System z opcode.          */
6181 /*                                                                  */
6182 /*------------------------------------------------------------------*/
6183
6184 void
6185 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6186 {
6187         /* 
6188          * Have to rename these to avoid being decomposed normally, since the normal 
6189          * decomposition does not work on S390.
6190          */
6191         switch (ins->opcode) {
6192         case OP_ISUB_OVF:
6193                 ins->opcode = OP_S390_ISUB_OVF;
6194                 break;
6195         case OP_ISUB_OVF_UN:
6196                 ins->opcode = OP_S390_ISUB_OVF_UN;
6197                 break;
6198         case OP_IADD_OVF:
6199                 ins->opcode = OP_S390_IADD_OVF;
6200                 break;
6201         case OP_IADD_OVF_UN:
6202                 ins->opcode = OP_S390_IADD_OVF_UN;
6203                 break;
6204         case OP_LADD_OVF:
6205                 ins->opcode = OP_S390_LADD_OVF;
6206                 break;
6207         case OP_LADD_OVF_UN:
6208                 ins->opcode = OP_S390_LADD_OVF_UN;
6209                 break;
6210         case OP_LSUB_OVF:
6211                 ins->opcode = OP_S390_LSUB_OVF;
6212                 break;
6213         case OP_LSUB_OVF_UN:
6214                 ins->opcode = OP_S390_LSUB_OVF_UN;
6215                 break;
6216         default:
6217                 break;
6218         }
6219 }
6220
6221 /*========================= End of Function ========================*/
6222
6223 /*------------------------------------------------------------------*/
6224 /*                                                                  */
6225 /* Name         - mono_arch_print_tree                              */
6226 /*                                                                  */
6227 /* Function     - Print platform-specific opcode details.           */
6228 /*                                                                  */
6229 /* Returns      - 1 - opcode details have been printed              */
6230 /*                0 - opcode details have not been printed          */
6231 /*                                                                  */
6232 /*------------------------------------------------------------------*/
6233
6234 gboolean
6235 mono_arch_print_tree (MonoInst *tree, int arity)
6236 {
6237         gboolean done;
6238
6239         switch (tree->opcode) {
6240                 case OP_S390_LOADARG:
6241                 case OP_S390_ARGREG:
6242                 case OP_S390_ARGPTR:
6243                         printf ("[0x%lx(%s)]", tree->inst_offset, 
6244                                 mono_arch_regname (tree->inst_basereg));
6245                         done = 1;
6246                         break;
6247                 case OP_S390_STKARG:
6248                         printf ("[0x%lx(previous_frame)]", 
6249                                 tree->inst_offset); 
6250                         done = 1;
6251                         break;
6252                 case OP_S390_MOVE:
6253                         printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6254                                 tree->inst_offset, tree->backend.size,
6255                                 mono_arch_regname(tree->dreg), 
6256                                 tree->inst_imm, 
6257                                 mono_arch_regname(tree->sreg1));
6258                         done = 1;
6259                         break;
6260                 case OP_S390_SETF4RET:
6261                         printf ("[f%s,f%s]", 
6262                                 mono_arch_regname (tree->dreg),
6263                                 mono_arch_regname (tree->sreg1));
6264                         done = 1;
6265                         break;
6266                 case OP_TLS_GET:
6267                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6268                         tree->inst_imm,
6269                         mono_arch_regname (tree->sreg1));
6270                         done = 1;
6271                         break;
6272                 case OP_TLS_SET:
6273                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6274                         tree->inst_imm,
6275                         mono_arch_regname (tree->sreg1));
6276                         done = 1;
6277                         break;
6278                 case OP_S390_BKCHAIN:
6279                         printf ("[previous_frame(%s)]", 
6280                                 mono_arch_regname (tree->sreg1));
6281                         done = 1;
6282                 default:
6283                         done = 0;
6284         }
6285         return (done);
6286 }
6287
6288 /*========================= End of Function ========================*/
6289
6290 /*------------------------------------------------------------------*/
6291 /*                                                                  */
6292 /* Name         - mono_arch_regalloc_cost                           */
6293 /*                                                                  */
6294 /* Function     - Determine the cost, in the number of memory       */
6295 /*                references, of the action of allocating the var-  */
6296 /*                iable VMV into a register during global register  */
6297 /*                allocation.                                       */
6298 /*                                                                  */
6299 /* Returns      - Cost                                              */
6300 /*                                                                  */
6301 /*------------------------------------------------------------------*/
6302
6303 guint32
6304 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6305 {
6306         /* FIXME: */
6307         return 2;
6308 }
6309
6310 /*========================= End of Function ========================*/
6311
6312 /*------------------------------------------------------------------*/
6313 /*                                                                  */
6314 /* Name         - mono_arch_flush_register_windows                  */
6315 /*                                                                  */
6316 /* Function     -                                                   */
6317 /*                                                                  */
6318 /* Returns      -                                                   */
6319 /*                                                                  */
6320 /*------------------------------------------------------------------*/
6321
6322 void 
6323 mono_arch_flush_register_windows (void)
6324 {
6325 }
6326
6327 /*========================= End of Function ========================*/
6328
6329 /*------------------------------------------------------------------*/
6330 /*                                                                  */
6331 /* Name         - mono_arch_is_inst_imm                             */
6332 /*                                                                  */
6333 /* Function     - Determine if operand qualifies as an immediate    */
6334 /*                value. For s390 this is a value -32768-32768      */
6335 /*                                                                  */
6336 /* Returns      - True|False - is [not] immediate value.            */
6337 /*                                                                  */
6338 /*------------------------------------------------------------------*/
6339
6340 gboolean 
6341 mono_arch_is_inst_imm (gint64 imm)
6342 {
6343         return s390_is_imm32 (imm);
6344 }
6345
6346 /*========================= End of Function ========================*/
6347
6348 /*------------------------------------------------------------------*/
6349 /*                                                                  */
6350 /* Name         - mono_arch_get_patch_offset                        */
6351 /*                                                                  */
6352 /* Function     - Dummy entry point until s390x supports aot.       */
6353 /*                                                                  */
6354 /* Returns      - Offset for patch.                                 */
6355 /*                                                                  */
6356 /*------------------------------------------------------------------*/
6357
6358 guint32
6359 mono_arch_get_patch_offset (guint8 *code)
6360 {
6361         return 0;
6362 }
6363
6364 /*========================= End of Function ========================*/
6365
6366 /*------------------------------------------------------------------*/
6367 /*                                                                  */
6368 /* Name         - mono_arch_context_get_int_reg.                    */
6369 /*                                                                  */
6370 /* Function     -                                                   */
6371 /*                                                                  */
6372 /* Returns      - Return a register from the context.               */
6373 /*                                                                  */
6374 /*------------------------------------------------------------------*/
6375
6376 mgreg_t
6377 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6378 {
6379         return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6380 }
6381
6382 /*========================= End of Function ========================*/
6383
6384 /*------------------------------------------------------------------*/
6385 /*                                                                  */
6386 /* Name         - mono_arch_context_set_int_reg.                    */
6387 /*                                                                  */
6388 /* Function     - Set a value in a specified register.              */
6389 /*                                                                  */
6390 /*------------------------------------------------------------------*/
6391
6392 void
6393 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6394 {
6395         ctx->uc_mcontext.gregs[reg] = val;
6396 }
6397
6398 /*========================= End of Function ========================*/
6399
6400 /*------------------------------------------------------------------*/
6401 /*                                                                  */
6402 /* Name         - mono_arch_get_this_arg_from_call.                 */
6403 /*                                                                  */
6404 /* Function     -                                                   */
6405 /*                                                                  */
6406 /*------------------------------------------------------------------*/
6407
6408 gpointer
6409 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6410 {
6411         return (gpointer) regs [s390_r2];
6412 }
6413
6414 /*========================= End of Function ========================*/
6415  
6416 /*------------------------------------------------------------------*/
6417 /*                                                                  */
6418 /* Name         - mono_arch_install_handler_block_guard             */
6419 /*                                                                  */
6420 /* Function     -                                                   */
6421 /*                                                                  */
6422 /*------------------------------------------------------------------*/
6423
6424 gpointer
6425 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, 
6426                                        MonoContext *ctx, gpointer new_value)
6427 {
6428         int offset;
6429         gpointer *sp, old_value;
6430         char *bp;
6431
6432         offset = clause->exvar_offset;
6433
6434         /*Load the spvar*/
6435         bp = MONO_CONTEXT_GET_BP (ctx);
6436         sp = *(gpointer*)(bp + offset);
6437
6438         old_value = *sp;
6439         if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6440                 return old_value;
6441
6442         *sp = new_value;
6443
6444         return old_value;
6445 }
6446
6447 /*========================= End of Function ========================*/
6448  
6449 /*------------------------------------------------------------------*/
6450 /*                                                                  */
6451 /* Name         - get_delegate_invoke_impl.                         */
6452 /*                                                                  */
6453 /* Function     -                                                   */
6454 /*                                                                  */
6455 /*------------------------------------------------------------------*/
6456
6457 static gpointer
6458 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6459 {
6460         guint8 *code, *start;
6461
6462         if (has_target) {
6463                 int size = 32;
6464
6465                 start = code = mono_global_codeman_reserve (size);
6466
6467                 /* Replace the this argument with the target */
6468                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6469                 s390_lg   (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6470                 s390_br   (code, s390_r1);
6471                 g_assert ((code - start) <= size);
6472
6473                 mono_arch_flush_icache (start, size);
6474         } else {
6475                 int size, i;
6476
6477                 size = 32 + param_count * 8;
6478                 start = code = mono_global_codeman_reserve (size);
6479
6480                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6481                 /* slide down the arguments */
6482                 for (i = 0; i < param_count; ++i) {
6483                         s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6484                 }
6485                 s390_br   (code, s390_r1);
6486
6487                 g_assert ((code - start) <= size);
6488
6489                 mono_arch_flush_icache (start, size);
6490         }
6491
6492         MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL));
6493
6494         if (has_target) {
6495                 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6496         } else {
6497                 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6498                 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6499                 g_free (name);
6500         }
6501
6502         return start;
6503 }
6504
6505 /*========================= End of Function ========================*/
6506
6507 /*------------------------------------------------------------------*/
6508 /*                                                                  */
6509 /* Name         - mono_arch_get_delegate_invoke_impls.              */
6510 /*                                                                  */
6511 /* Function     -                                                   */
6512 /*                                                                  */
6513 /*------------------------------------------------------------------*/
6514
6515 GSList*
6516 mono_arch_get_delegate_invoke_impls (void)
6517 {
6518         GSList *res = NULL;
6519         MonoTrampInfo *info;
6520         int i;
6521
6522         get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6523         res = g_slist_prepend (res, info);
6524
6525         for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6526                 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6527                 res = g_slist_prepend (res, info);
6528         }
6529
6530         return res;
6531 }
6532
6533 /*========================= End of Function ========================*/
6534
6535 /*------------------------------------------------------------------*/
6536 /*                                                                  */
6537 /* Name         - mono_arch_get_delegate_invoke_impl.               */
6538 /*                                                                  */
6539 /* Function     -                                                   */
6540 /*                                                                  */
6541 /*------------------------------------------------------------------*/
6542
6543 gpointer
6544 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6545 {
6546         guint8 *code, *start;
6547
6548         /* FIXME: Support more cases */
6549         if (MONO_TYPE_ISSTRUCT (sig->ret))
6550                 return NULL;
6551
6552         if (has_target) {
6553                 static guint8* cached = NULL;
6554
6555                 if (cached)
6556                         return cached;
6557
6558                 if (mono_aot_only) {
6559                         start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6560                 } else {
6561                         MonoTrampInfo *info;
6562                         start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6563                         mono_tramp_info_register (info, NULL);
6564                 }
6565
6566                 mono_memory_barrier ();
6567
6568                 cached = start;
6569         } else {
6570                 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6571                 int i;
6572
6573                 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6574                         return NULL;
6575                 for (i = 0; i < sig->param_count; ++i)
6576                         if (!mono_is_regsize_var (sig->params [i]))
6577                                 return NULL;
6578
6579
6580                 code = cache [sig->param_count];
6581                 if (code)
6582                         return code;
6583
6584                 if (mono_aot_only) {
6585                         char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6586                         start = mono_aot_get_trampoline (name);
6587                         g_free (name);
6588                 } else {
6589                         MonoTrampInfo *info;
6590                         start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6591                         mono_tramp_info_register (info, NULL);
6592                 }
6593
6594                 mono_memory_barrier ();
6595
6596                 cache [sig->param_count] = start;
6597         }
6598         return start;
6599 }
6600
6601 /*========================= End of Function ========================*/
6602
6603 /*------------------------------------------------------------------*/
6604 /*                                                                  */
6605 /* Name         - mono_arch_get_delegate_virtual_invoke_impl.       */
6606 /*                                                                  */
6607 /* Function     -                                                   */
6608 /*                                                                  */
6609 /*------------------------------------------------------------------*/
6610
6611 gpointer
6612 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, 
6613                                             int offset, gboolean load_imt_reg)
6614 {
6615         guint8 *code, *start;
6616         int size = 40;
6617
6618         start = code = mono_global_codeman_reserve (size);
6619
6620         /*
6621         * Replace the "this" argument with the target
6622         */
6623         s390_lgr  (code, s390_r1, s390_r2);
6624         s390_lg   (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));        
6625
6626         /*
6627         * Load the IMT register, if needed
6628         */
6629         if (load_imt_reg) {
6630                 s390_lg  (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6631         }
6632
6633         /*
6634         * Load the vTable
6635         */
6636         s390_lg  (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6637         if (offset != 0) {
6638                 s390_agfi(code, s390_r1, offset);
6639         }
6640         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6641         s390_br  (code, s390_r1);
6642
6643         return(start);
6644 }
6645
6646 /*========================= End of Function ========================*/
6647
6648 /*------------------------------------------------------------------*/
6649 /*                                                                  */
6650 /* Name         - mono_arch_build_imt_trampoline.                       */
6651 /*                                                                  */
6652 /* Function     -                                                   */
6653 /*                                                                  */
6654 /*------------------------------------------------------------------*/
6655
6656 gpointer
6657 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, 
6658                                                                 MonoIMTCheckItem **imt_entries, int count,
6659                                                                 gpointer fail_tramp)
6660 {
6661         int i;
6662         int size = 0;
6663         guchar *code, *start;
6664         char trampName[64];
6665
6666         for (i = 0; i < count; ++i) {
6667                 MonoIMTCheckItem *item = imt_entries [i];
6668                 if (item->is_equals) {
6669                         if (item->check_target_idx) {
6670                                 if (!item->compare_done)
6671                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6672                                 if (item->has_target_code)
6673                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6674                                 else
6675                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE + 
6676                                                             LOAD_SIZE;
6677                         } else {
6678                                 if (fail_tramp) {
6679                                         item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE + 
6680                                                             2 * LOADCON_SIZE;
6681                                         if (!item->has_target_code)
6682                                                 item->chunk_size += LOAD_SIZE;
6683                                 } else {
6684                                         item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6685 #if ENABLE_WRONG_METHOD_CHECK
6686                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6687 #endif
6688                                 }
6689                         }
6690                 } else {
6691                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6692                         imt_entries [item->check_target_idx]->compare_done = TRUE;
6693                 }
6694                 size += item->chunk_size;
6695         }
6696
6697         if (fail_tramp)
6698                 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6699         else
6700                 code = mono_domain_code_reserve (domain, size);
6701
6702         start = code;
6703
6704         for (i = 0; i < count; ++i) {
6705                 MonoIMTCheckItem *item = imt_entries [i];
6706                 item->code_target = (guint8 *) code;
6707                 if (item->is_equals) {
6708                         if (item->check_target_idx) {
6709                                 if (!item->compare_done) {
6710                                         S390_SET  (code, s390_r0, item->key);
6711                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6712                                 }
6713                                 item->jmp_code = (guint8*) code;
6714                                 s390_jcl (code, S390_CC_NE, 0);
6715                                 
6716                                 if (item->has_target_code) {
6717                                         S390_SET (code, s390_r1, item->value.target_code);
6718                                 } else {
6719                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6720                                         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6721                                 }
6722                                 s390_br   (code, s390_r1);
6723                         } else {
6724                                 if (fail_tramp) {
6725                                         gint64  target;
6726
6727                                         S390_SET  (code, s390_r0, item->key);
6728                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6729                                         item->jmp_code = (guint8*) code;
6730                                         s390_jcl  (code, S390_CC_NE, 0);
6731                                         if (item->has_target_code) {
6732                                                 S390_SET (code, s390_r1, item->value.target_code);
6733                                         } else {
6734                                                 g_assert (vtable);
6735                                                 S390_SET  (code, s390_r1, 
6736                                                            (&(vtable->vtable [item->value.vtable_slot])));
6737                                                 s390_lg   (code, s390_r1, 0, s390_r1, 0);
6738                                         }
6739                                         s390_br   (code, s390_r1);
6740                                         target = (gint64) S390_RELATIVE(code, item->jmp_code);
6741                                         s390_patch_rel(item->jmp_code+2, target);
6742                                         S390_SET  (code, s390_r1, fail_tramp);
6743                                         s390_br   (code, s390_r1);
6744                                         item->jmp_code = NULL;
6745                                 } else {
6746                                 /* enable the commented code to assert on wrong method */
6747 #if ENABLE_WRONG_METHOD_CHECK
6748                                         g_assert_not_reached ();
6749 #endif
6750                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6751                                         s390_lg   (code, s390_r1, 0, s390_r1, 0);
6752                                         s390_br   (code, s390_r1);
6753                                 }
6754                         }
6755                 } else {
6756                         S390_SET  (code, s390_r0, item->key);
6757                         s390_cgr  (code, MONO_ARCH_IMT_REG, s390_r0);
6758                         item->jmp_code = (guint8 *) code;
6759                         s390_jcl  (code, S390_CC_GE, 0);
6760                 }
6761         }
6762         /* 
6763          * patch the branches to get to the target items 
6764          */
6765         for (i = 0; i < count; ++i) {
6766                 MonoIMTCheckItem *item = imt_entries [i];
6767                 if (item->jmp_code) {
6768                         if (item->check_target_idx) {
6769                                 gint64 offset;
6770                                 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6771                                                        item->jmp_code);
6772                                 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6773                         }
6774                 }
6775         }
6776
6777         mono_arch_flush_icache ((guint8*)start, (code - start));
6778         MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL));
6779
6780         if (!fail_tramp) 
6781                 mono_stats.imt_trampolines_size += (code - start);
6782
6783         g_assert (code - start <= size);
6784
6785         snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6786         mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6787
6788         return (start);
6789 }
6790
6791 /*========================= End of Function ========================*/
6792
6793 /*------------------------------------------------------------------*/
6794 /*                                                                  */
6795 /* Name         - mono_arch_find_imt_method.                        */
6796 /*                                                                  */
6797 /* Function     - Get the method address from MONO_ARCH_IMT_REG     */
6798 /*                found in the save area.                           */
6799 /*                                                                  */
6800 /*------------------------------------------------------------------*/
6801
6802 MonoMethod*
6803 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6804 {
6805         return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6806 }
6807
6808 /*========================= End of Function ========================*/
6809
6810 /*------------------------------------------------------------------*/
6811 /*                                                                  */
6812 /* Name         - mono_arch_find_static_call_vtable                 */
6813 /*                                                                  */
6814 /* Function     - Find the static call vtable.                      */
6815 /*                                                                  */
6816 /*------------------------------------------------------------------*/
6817
6818 MonoVTable*
6819 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6820 {
6821         mgreg_t *r = (mgreg_t*)regs;
6822
6823         return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6824 }
6825
6826 /*========================= End of Function ========================*/
6827
6828 /*------------------------------------------------------------------*/
6829 /*                                                                  */
6830 /* Name         - mono_arch_get_cie_program                         */
6831 /*                                                                  */
6832 /* Function     - Find the static call vtable.                      */
6833 /*                                                                  */
6834 /*------------------------------------------------------------------*/
6835
6836 GSList*
6837 mono_arch_get_cie_program (void)
6838 {
6839         GSList *l = NULL;
6840
6841         mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6842
6843         return(l);
6844 }
6845
6846 /*========================= End of Function ========================*/
6847
6848 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6849
6850 /*------------------------------------------------------------------*/
6851 /*                                                                  */
6852 /* Name         - mono_arch_set_breakpoint.                         */
6853 /*                                                                  */
6854 /* Function     - Set a breakpoint at the native code corresponding */
6855 /*                to JI at NATIVE_OFFSET.  The location should      */
6856 /*                contain code emitted by OP_SEQ_POINT.             */
6857 /*                                                                  */
6858 /*------------------------------------------------------------------*/
6859
6860 void
6861 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6862 {
6863         guint8 *code = ip;
6864
6865         breakpointCode.pTrigger = bp_trigger_page;
6866         memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6867         code += BREAKPOINT_SIZE;
6868 }
6869
6870 /*========================= End of Function ========================*/
6871
6872 /*------------------------------------------------------------------*/
6873 /*                                                                  */
6874 /* Name         - mono_arch_clear_breakpoint.                       */
6875 /*                                                                  */
6876 /* Function     - Clear the breakpoint at IP.                       */
6877 /*                                                                  */
6878 /*------------------------------------------------------------------*/
6879
6880 void
6881 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6882 {
6883         guint8 *code = ip;
6884         int i;
6885
6886         for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6887                 s390_nop(code);
6888 }
6889
6890 /*========================= End of Function ========================*/
6891
6892 /*------------------------------------------------------------------*/
6893 /*                                                                  */
6894 /* Name         - mono_arch_is_breakpoint_event.                    */
6895 /*                                                                  */
6896 /* Function     -                                                   */
6897 /*                                                                  */
6898 /*------------------------------------------------------------------*/
6899
6900 gboolean
6901 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6902 {
6903         siginfo_t* sinfo = (siginfo_t*) info;
6904
6905         /* 
6906          * Sometimes the address is off by 4 
6907          */
6908         if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6909                 return TRUE;
6910         else
6911                 return FALSE;
6912 }
6913
6914 /*========================= End of Function ========================*/
6915
6916 /*------------------------------------------------------------------*/
6917 /*                                                                  */
6918 /* Name         - mono_arch_skip_breakpoint.                        */
6919 /*                                                                  */
6920 /* Function     - Modify the CTX so the IP is placed after the      */
6921 /*                breakpoint instruction, so when we resume, the    */
6922 /*                instruction is not executed again.                */
6923 /*                                                                  */
6924 /*------------------------------------------------------------------*/
6925
6926 void
6927 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6928 {
6929         MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6930 }
6931
6932 /*========================= End of Function ========================*/
6933         
6934 /*------------------------------------------------------------------*/
6935 /*                                                                  */
6936 /* Name         - mono_arch_start_single_stepping.                  */
6937 /*                                                                  */
6938 /* Function     - Start single stepping.                            */
6939 /*                                                                  */
6940 /*------------------------------------------------------------------*/
6941
6942 void
6943 mono_arch_start_single_stepping (void)
6944 {
6945         mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6946 }
6947
6948 /*========================= End of Function ========================*/
6949         
6950 /*------------------------------------------------------------------*/
6951 /*                                                                  */
6952 /* Name         - mono_arch_stop_single_stepping.                   */
6953 /*                                                                  */
6954 /* Function     - Stop single stepping.                             */
6955 /*                                                                  */
6956 /*------------------------------------------------------------------*/
6957
6958 void
6959 mono_arch_stop_single_stepping (void)
6960 {
6961         mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6962 }
6963
6964 /*========================= End of Function ========================*/
6965
6966 /*------------------------------------------------------------------*/
6967 /*                                                                  */
6968 /* Name         - mono_arch_is_single_step_event.                   */
6969 /*                                                                  */
6970 /* Function     - Return whether the machine state in sigctx cor-   */
6971 /*                responds to a single step event.                  */
6972 /*                                                                  */
6973 /*------------------------------------------------------------------*/
6974
6975 gboolean
6976 mono_arch_is_single_step_event (void *info, void *sigctx)
6977 {
6978         siginfo_t* sinfo = (siginfo_t*) info;
6979
6980         /* 
6981          * Sometimes the address is off by 4 
6982          */
6983         if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6984                 return TRUE;
6985         else
6986                 return FALSE;
6987 }
6988
6989 /*========================= End of Function ========================*/
6990
6991 /*------------------------------------------------------------------*/
6992 /*                                                                  */
6993 /* Name         - mono_arch_skip_single_step.                       */
6994 /*                                                                  */
6995 /* Function     - Modify the ctx so the IP is placed after the      */
6996 /*                single step trigger instruction, so that the      */
6997 /*                instruction is not executed again.                */
6998 /*                                                                  */
6999 /*------------------------------------------------------------------*/
7000
7001 void
7002 mono_arch_skip_single_step (MonoContext *ctx)
7003 {
7004         MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7005 }
7006
7007 /*========================= End of Function ========================*/
7008
7009 /*------------------------------------------------------------------*/
7010 /*                                                                  */
7011 /* Name         - mono_arch_create_seq_point_info.                  */
7012 /*                                                                  */
7013 /* Function     - Return a pointer to a data struction which is     */
7014 /*                used by the sequence point implementation in      */
7015 /*                AOTed code.                                       */
7016 /*                                                                  */
7017 /*------------------------------------------------------------------*/
7018
7019 gpointer
7020 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7021 {
7022         NOT_IMPLEMENTED;
7023         return NULL;
7024 }
7025
7026 /*========================= End of Function ========================*/
7027
7028 /*------------------------------------------------------------------*/
7029 /*                                                                  */
7030 /* Name         - mono_arch_init_lmf_ext.                           */
7031 /*                                                                  */
7032 /* Function -                                                       */
7033 /*                                                                  */
7034 /*------------------------------------------------------------------*/
7035
7036 void
7037 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7038 {
7039         ext->lmf.previous_lmf = prev_lmf;
7040         /* Mark that this is a MonoLMFExt */
7041         ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7042         ext->lmf.ebp = (gssize)ext;
7043 }
7044
7045 /*========================= End of Function ========================*/
7046
7047 #endif
7048
7049 /*------------------------------------------------------------------*/
7050 /*                                                                  */
7051 /* Name     - mono_arch_cpu_enumerate_simd_versions.                */
7052 /*                                                                  */
7053 /* Function - If this CPU supports vector operations then it        */
7054 /*            supports the equivalent of SSE1-4.                    */
7055 /*                                                                  */
7056 /*------------------------------------------------------------------*/
7057
7058 guint32
7059 mono_arch_cpu_enumerate_simd_versions (void)
7060 {
7061         guint32 sseOpts = 0;
7062
7063         if (mono_hwcap_s390x_has_vec)
7064                 sseOpts = (SIMD_VERSION_SSE1  | SIMD_VERSION_SSE2 |
7065                            SIMD_VERSION_SSE3  | SIMD_VERSION_SSSE3 |
7066                            SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7067                            SIMD_VERSION_SSE4a);
7068
7069         return (sseOpts);
7070 }
7071
7072 /*========================= End of Function ========================*/
7073
7074 /*------------------------------------------------------------------*/
7075 /*                                                                  */
7076 /* Name     - mono_arch_opcode_supported.                           */
7077 /*                                                                  */
7078 /* Function - Check if a given return code is supported.            */
7079 /*                                                                  */
7080 /*------------------------------------------------------------------*/
7081
7082 gboolean
7083 mono_arch_opcode_supported (int opcode)
7084 {
7085         switch (opcode) {
7086         case OP_ATOMIC_ADD_I4:
7087         case OP_ATOMIC_ADD_I8:
7088         case OP_ATOMIC_EXCHANGE_I4:
7089         case OP_ATOMIC_EXCHANGE_I8:
7090                 return TRUE;
7091         default:
7092                 return FALSE;
7093         }
7094 }
7095
7096 /*========================= End of Function ========================*/