Merge pull request #3406 from alexanderkyte/mobile_static_default
[mono.git] / mono / mini / mini-s390x.c
1 /*------------------------------------------------------------------*/
2 /*                                                                  */
3 /* Name        - mini-s390.c                                        */
4 /*                                                                  */
5 /* Function    - S/390 backend for the Mono code generator.         */
6 /*                                                                  */
7 /* Name        - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
8 /*                                                                  */
9 /* Date        - January, 2004                                      */
10 /*                                                                  */
11 /* Derivation  - From mini-x86 & mini-ppc by -                      */
12 /*               Paolo Molaro (lupus@ximian.com)                    */
13 /*               Dietmar Maurer (dietmar@ximian.com)                */
14 /*                                                                  */
15 /*------------------------------------------------------------------*/
16
17 /*------------------------------------------------------------------*/
18 /*                 D e f i n e s                                    */
19 /*------------------------------------------------------------------*/
20
21 #define MAX_ARCH_DELEGATE_PARAMS 7
22
23 #define EMIT_COND_BRANCH(ins,cond)                                              \
24 {                                                                               \
25 if (ins->inst_true_bb->native_offset) {                                         \
26         int displace;                                                           \
27         displace = ((cfg->native_code +                                         \
28                     ins->inst_true_bb->native_offset) - code) / 2;              \
29         if (s390_is_imm16(displace)) {                                          \
30                 s390_brc (code, cond, displace);                                \
31         } else {                                                                \
32                 s390_jcl (code, cond, displace);                                \
33         }                                                                       \
34 } else {                                                                        \
35         mono_add_patch_info (cfg, code - cfg->native_code,                      \
36                              MONO_PATCH_INFO_BB, ins->inst_true_bb);            \
37         s390_jcl (code, cond, 0);                                               \
38 }                                                                               \
39 }
40
41 #define EMIT_UNCOND_BRANCH(ins)                                                 \
42 {                                                                               \
43 if (ins->inst_target_bb->native_offset) {                                       \
44         int displace;                                                           \
45         displace = ((cfg->native_code +                                         \
46                     ins->inst_target_bb->native_offset) - code) / 2;            \
47         if (s390_is_imm16(displace)) {                                          \
48                 s390_brc (code, S390_CC_UN, displace);                          \
49         } else {                                                                \
50                 s390_jcl (code, S390_CC_UN, displace);                          \
51         }                                                                       \
52 } else {                                                                        \
53         mono_add_patch_info (cfg, code - cfg->native_code,                      \
54                              MONO_PATCH_INFO_BB, ins->inst_target_bb);          \
55         s390_jcl (code, S390_CC_UN, 0);                                         \
56 }                                                                               \
57 }
58
59 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name)                       \
60         do {                                                            \
61                 mono_add_patch_info (cfg, code - cfg->native_code,      \
62                                      MONO_PATCH_INFO_EXC, exc_name);    \
63                 s390_jcl (code, cond, 0);                               \
64         } while (0); 
65
66 #define CHECK_SRCDST_COM                                                \
67         if (ins->dreg == ins->sreg2) {                                  \
68                 src2 = ins->sreg1;                                      \
69         } else {                                                        \
70                 src2 = ins->sreg2;                                      \
71                 if (ins->dreg != ins->sreg1) {                          \
72                         s390_lgr (code, ins->dreg, ins->sreg1);         \
73                 }                                                       \
74         }
75
76 #define CHECK_SRCDST_NCOM                                               \
77         if (ins->dreg == ins->sreg2) {                                  \
78                 src2 = s390_r13;                                        \
79                 s390_lgr (code, s390_r13, ins->sreg2);                  \
80         } else {                                                        \
81                 src2 = ins->sreg2;                                      \
82         }                                                               \
83         if (ins->dreg != ins->sreg1) {                                  \
84                 s390_lgr (code, ins->dreg, ins->sreg1);                 \
85         }
86
87 #define CHECK_SRCDST_COM_I                                              \
88         if (ins->dreg == ins->sreg2) {                                  \
89                 src2 = ins->sreg1;                                      \
90         } else {                                                        \
91                 src2 = ins->sreg2;                                      \
92                 if (ins->dreg != ins->sreg1) {                          \
93                         s390_lgfr (code, ins->dreg, ins->sreg1);        \
94                 }                                                       \
95         }
96
97 #define CHECK_SRCDST_NCOM_I                                             \
98         if (ins->dreg == ins->sreg2) {                                  \
99                 src2 = s390_r13;                                        \
100                 s390_lgfr (code, s390_r13, ins->sreg2);                 \
101         } else {                                                        \
102                 src2 = ins->sreg2;                                      \
103         }                                                               \
104         if (ins->dreg != ins->sreg1) {                                  \
105                 s390_lgfr (code, ins->dreg, ins->sreg1);                \
106         }
107
108 #define CHECK_SRCDST_COM_F                                              \
109         if (ins->dreg == ins->sreg2) {                                  \
110                 src2 = ins->sreg1;                                      \
111         } else {                                                        \
112                 src2 = ins->sreg2;                                      \
113                 if (ins->dreg != ins->sreg1) {                          \
114                         s390_ldr (code, ins->dreg, ins->sreg1);         \
115                 }                                                       \
116         }
117
118 #define CHECK_SRCDST_NCOM_F                                             \
119         if (ins->dreg == ins->sreg2) {                                  \
120                 src2 = s390_f15;                                        \
121                 s390_ldr (code, s390_r13, ins->sreg2);                  \
122         } else {                                                        \
123                 src2 = ins->sreg2;                                      \
124         }                                                               \
125         if (ins->dreg != ins->sreg1) {                                  \
126                 s390_ldr (code, ins->dreg, ins->sreg1);                 \
127         }
128
129 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do {                   \
130                 MonoInst *inst;                                                 \
131                 int sReg, dReg;                                                 \
132                 MONO_INST_NEW (cfg, inst, OP_NOP);                              \
133                 if (size > 256) {                                               \
134                         inst->dreg        = dest;                               \
135                         inst->inst_offset = offset;                             \
136                         inst->sreg1       = src;                                \
137                         inst->inst_imm    = imm;                                \
138                 } else {                                                        \
139                         if (s390_is_uimm12(offset)) {                           \
140                                 inst->dreg        = dest;                       \
141                                 inst->inst_offset = offset;                     \
142                         } else {                                                \
143                                 dReg = mono_alloc_preg (cfg);                   \
144                                 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM,        \
145                                         dReg, dest, offset);                    \
146                                 inst->dreg        = dReg;                       \
147                                 inst->inst_offset = 0;                          \
148                         }                                                       \
149                         if (s390_is_uimm12(imm)) {                              \
150                                 inst->sreg1       = src;                        \
151                                 inst->inst_imm    = imm;                        \
152                         } else {                                                \
153                                 sReg = mono_alloc_preg (cfg);                   \
154                                 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM,        \
155                                         sReg, src, imm);                        \
156                                 inst->sreg1       = sReg;                       \
157                                 inst->inst_imm    = 0;                          \
158                         }                                                       \
159                 }                                                               \
160                 inst->opcode            = OP_S390_MOVE;                         \
161                 inst->backend.size      = size;                                 \
162         MONO_ADD_INS (cfg->cbb, inst);                                          \
163         } while (0)
164
165 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do {                             \
166         int reg = mono_alloc_preg (cfg); \
167         switch (size) {                                                         \
168                 case 0:                                                         \
169                         MONO_EMIT_NEW_ICONST(cfg, reg, 0);                      \
170                 break;                                                          \
171                 case 1:                                                         \
172                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE,   \
173                                 reg, sr, so);                                   \
174                 break;                                                          \
175                 case 2:                                                         \
176                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE,   \
177                                 reg, sr, so);                                   \
178                 break;                                                          \
179                 case 4:                                                         \
180                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE,   \
181                                 reg, sr, so);                                   \
182                 break;                                                          \
183                 case 8:                                                         \
184                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE,   \
185                                 reg, sr, so);                                   \
186                 break;                                                          \
187         }                                                                       \
188         mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE);               \
189 } while (0)
190
191 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do {                         \
192         int tmpr;                                                               \
193         switch (size) {                                                         \
194                 case 0:                                                         \
195                         tmpr = mono_alloc_preg (cfg); \
196                         MONO_EMIT_NEW_ICONST(cfg, tmpr, 0);                     \
197                         MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
198                                 dr, dx, tmpr);                                  \
199                 break;                                                          \
200                 case 1:                                                         \
201                         tmpr = mono_alloc_preg (cfg); \
202                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE,   \
203                                 tmpr, sr, so);                                  \
204                         MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
205                                 dr, dx, tmpr);                                  \
206                 break;                                                          \
207                 case 2:                                                         \
208                         tmpr = mono_alloc_preg (cfg);                           \
209                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE,   \
210                                 tmpr, sr, so);                                  \
211                         MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
212                                 dr, dx, tmpr);                                  \
213                 break;                                                          \
214                 case 4:                                                         \
215                         tmpr = mono_alloc_preg (cfg);                           \
216                         MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE,   \
217                                 tmpr, sr, so);                                  \
218                         MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
219                                 dr, dx, tmpr);                                  \
220                 break;                                                          \
221                 case 8:                                                         \
222                         MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size);         \
223                 break;                                                          \
224         }                                                                       \
225 } while (0)
226
227 #undef DEBUG
228 #define DEBUG(a) if (cfg->verbose_level > 1) a
229
230 #define MAX_EXC 16
231
232 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
233
234 #define BREAKPOINT_SIZE         sizeof(breakpoint_t)
235 #define S390X_NOP_SIZE          sizeof(RR_Format)
236
237 #define MAX(a, b) ((a) > (b) ? (a) : (b))
238
239 /*
240  * imt trampoline size values
241  */
242 #define CMP_SIZE        24
243 #define LOADCON_SIZE    20
244 #define LOAD_SIZE       6
245 #define BR_SIZE         2
246 #define JUMP_SIZE       6
247 #define ENABLE_WRONG_METHOD_CHECK 0
248
249 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
250 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
251
252 /*========================= End of Defines =========================*/
253
254 /*------------------------------------------------------------------*/
255 /*                 I n c l u d e s                                  */
256 /*------------------------------------------------------------------*/
257
258 #include "mini.h"
259 #include <string.h>
260 #include <sys/types.h>
261 #include <unistd.h>
262
263 #include <mono/metadata/abi-details.h>
264 #include <mono/metadata/appdomain.h>
265 #include <mono/metadata/debug-helpers.h>
266 #include <mono/metadata/profiler-private.h>
267 #include <mono/utils/mono-error.h>
268 #include <mono/utils/mono-error-internals.h>
269 #include <mono/utils/mono-math.h>
270 #include <mono/utils/mono-mmap.h>
271 #include <mono/utils/mono-hwcap.h>
272 #include <mono/utils/mono-threads.h>
273
274 #include "mini-s390x.h"
275 #include "cpu-s390x.h"
276 #include "support-s390x.h"
277 #include "jit-icalls.h"
278 #include "ir-emit.h"
279 #include "trace.h"
280 #include "mini-gc.h"
281
282 /*========================= End of Includes ========================*/
283
284 /*------------------------------------------------------------------*/
285 /*                 T y p e d e f s                                  */
286 /*------------------------------------------------------------------*/
287
288 typedef struct {
289         guint stack_size,
290               local_size,
291               code_size,
292               parm_size,
293               offset,
294               offStruct,
295               retStruct;
296 } size_data;    
297
298 /*------------------------------------------------------------------*/
299 /* Used by the instrument_emit_epilog                               */
300 /*------------------------------------------------------------------*/
301
302 enum {
303         SAVE_NONE,
304         SAVE_STRUCT,
305         SAVE_ONE,
306         SAVE_TWO,
307         SAVE_R4,
308         SAVE_R8
309 };
310
311 typedef struct InstList InstList;
312
313 struct InstList {
314         InstList *prev;
315         InstList *next;
316         MonoInst *data;
317 };
318
319 typedef enum {
320         RegTypeGeneral,
321         RegTypeBase,
322         RegTypeFP,
323         RegTypeFPR4,
324         RegTypeStructByVal,
325         RegTypeStructByValInFP,
326         RegTypeStructByAddr,
327         RegTypeStructByAddrOnStack
328 } ArgStorage;
329
330 typedef struct {
331         gint32  offset;         /* offset from caller's stack */
332         gint32  offparm;        /* offset from callee's stack */
333         guint16 vtsize;         /* in param area */
334         guint8  reg;
335         ArgStorage regtype;
336         guint32 size;           /* Size of structure used by RegTypeStructByVal */
337         gint32  type;           /* Data type of argument */
338 } ArgInfo;
339
340 typedef struct {
341         int nargs;
342         int lastgr;
343         guint32 stack_usage;
344         guint32 struct_ret;
345         ArgInfo ret;
346         ArgInfo sigCookie;
347         size_data sz;
348         int vret_arg_index;
349         ArgInfo args [1];
350 } CallInfo;
351
352 typedef struct {
353         gint64  gr[5];          /* R2-R6                            */
354         gdouble fp[3];          /* F0-F2                            */
355 } __attribute__ ((packed)) RegParm;
356
357 typedef struct {
358         RR_Format  basr;
359         RI_Format  j;
360         void       *pTrigger;
361         RXY_Format lg;
362         RXY_Format trigger;
363 } __attribute__ ((packed)) breakpoint_t;
364
365 /*========================= End of Typedefs ========================*/
366
367 /*------------------------------------------------------------------*/
368 /*                   P r o t o t y p e s                            */
369 /*------------------------------------------------------------------*/
370
371 static void indent (int);
372 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
373 static void decodeParm (MonoType *, void *, int);
374 static void enter_method (MonoMethod *, RegParm *, char *);
375 static void leave_method (MonoMethod *, ...);
376 static inline void add_general (guint *, size_data *, ArgInfo *);
377 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
378 static inline void add_float (guint *, size_data *, ArgInfo *);
379 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
380 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
381 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
382 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
383
384 /*========================= End of Prototypes ======================*/
385
386 /*------------------------------------------------------------------*/
387 /*                 G l o b a l   V a r i a b l e s                  */
388 /*------------------------------------------------------------------*/
389
390 int mono_exc_esp_offset = 0;
391
392 __thread int indent_level = 0;
393
394 static gint appdomain_tls_offset = -1,
395             lmf_tls_offset = -1,
396             lmf_addr_tls_offset = -1;
397
398 pthread_key_t lmf_addr_key;
399
400 gboolean lmf_addr_key_inited = FALSE; 
401
402 /*
403  * The code generated for sequence points reads from this location, 
404  * which is made read-only when single stepping is enabled.
405  */
406 static gpointer ss_trigger_page;
407
408 /*
409  * Enabled breakpoints read from this trigger page
410  */
411 static gpointer bp_trigger_page;
412
413 breakpoint_t breakpointCode;
414
415 static mono_mutex_t mini_arch_mutex;
416
417 static const char * grNames[] = {
418         "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
419         "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
420         "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
421         "s390_r15"
422 };
423
424 static const char * fpNames[] = {
425         "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
426         "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
427         "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
428         "s390_f15"
429 };
430
431 static const char * vrNames[] = {
432         "vr0",  "vr1",  "vr2",  "vr3",  "vr4",  "vr5",  "vr6",  "vr7", 
433         "vr8",  "vr9",  "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
434         "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
435         "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
436 };
437
438 /*====================== End of Global Variables ===================*/
439
440 /*------------------------------------------------------------------*/
441 /*                                                                  */
442 /* Name         - mono_arch_regname                                 */
443 /*                                                                  */
444 /* Function     - Returns the name of the register specified by     */
445 /*                the input parameter.                              */
446 /*                                                                  */
447 /*------------------------------------------------------------------*/
448
449 const char*
450 mono_arch_regname (int reg) 
451 {
452         if (reg >= 0 && reg < 16)
453                 return grNames [reg];
454         else
455                 return "unknown";
456 }
457
458 /*========================= End of Function ========================*/
459
460 /*------------------------------------------------------------------*/
461 /*                                                                  */
462 /* Name         - mono_arch_fregname                                */
463 /*                                                                  */
464 /* Function     - Returns the name of the register specified by     */
465 /*                the input parameter.                              */
466 /*                                                                  */
467 /*------------------------------------------------------------------*/
468
469 const char*
470 mono_arch_fregname (int reg) 
471 {
472         if (reg >= 0 && reg < 16)
473                 return fpNames [reg];
474         else
475                 return "unknown";
476 }
477
478 /*========================= End of Function ========================*/
479
480 /*------------------------------------------------------------------*/
481 /*                                                                  */
482 /* Name         - mono_arch_xregname                                */
483 /*                                                                  */
484 /* Function     - Returns the name of the register specified by     */
485 /*                the input parameter.                              */
486 /*                                                                  */
487 /*------------------------------------------------------------------*/
488
489 const char *
490 mono_arch_xregname (int reg)
491 {
492         if (reg < s390_VR_NREG)
493                 return vrNames [reg];
494         else
495                 return "unknown";
496 }
497
498 /*========================= End of Function ========================*/
499
500 /*------------------------------------------------------------------*/
501 /*                                                                  */
502 /* Name         - arch_get_argument_info                            */
503 /*                                                                  */
504 /* Function     - Gathers information on parameters such as size,   */
505 /*                alignment, and padding. arg_info should be large  */
506 /*                enough to hold param_count + 1 entries.           */
507 /*                                                                  */
508 /* Parameters   - @csig - Method signature                          */
509 /*                @param_count - No. of parameters to consider      */
510 /*                @arg_info - An array to store the result info     */
511 /*                                                                  */
512 /* Returns      - Size of the activation frame                      */
513 /*                                                                  */
514 /*------------------------------------------------------------------*/
515
516 int
517 mono_arch_get_argument_info (MonoMethodSignature *csig, 
518                              int param_count, 
519                              MonoJitArgumentInfo *arg_info)
520 {
521         int k, frame_size = 0;
522         int size, align, pad;
523         int offset = 8;
524
525         if (MONO_TYPE_ISSTRUCT (csig->ret)) { 
526                 frame_size += sizeof (gpointer);
527                 offset += 8;
528         }
529
530         arg_info [0].offset = offset;
531
532         if (csig->hasthis) {
533                 frame_size += sizeof (gpointer);
534                 offset += 8;
535         }
536
537         arg_info [0].size = frame_size;
538
539         for (k = 0; k < param_count; k++) {
540                 
541                 if (csig->pinvoke)
542                         size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
543                 else
544                         size = mini_type_stack_size (csig->params [k], &align);
545
546                 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1); 
547                 arg_info [k].pad = pad;
548                 frame_size += size;
549                 arg_info [k + 1].pad = 0;
550                 arg_info [k + 1].size = size;
551                 offset += pad;
552                 arg_info [k + 1].offset = offset;
553                 offset += size;
554         }
555
556         align = MONO_ARCH_FRAME_ALIGNMENT;
557         frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
558         arg_info [k].pad = pad;
559
560         return frame_size;
561 }
562
563 /*========================= End of Function ========================*/
564
565 /*------------------------------------------------------------------*/
566 /*                                                                  */
567 /* Name         - emit_unwind_regs.                                 */
568 /*                                                                  */
569 /* Function     - Determines if a value can be returned in one or   */
570 /*                two registers.                                    */
571 /*                                                                  */
572 /*------------------------------------------------------------------*/
573
574 static void __inline__
575 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
576 {
577         int i;
578
579         for (i = start; i < end; i++) {
580                 mono_emit_unwind_op_offset (cfg, code, i, offset);
581                 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
582                 offset += sizeof(gulong);
583         }
584 }
585
586 /*========================= End of Function ========================*/
587
588 /*------------------------------------------------------------------*/
589 /*                                                                  */
590 /* Name         - retFitsInReg.                                     */
591 /*                                                                  */
592 /* Function     - Determines if a value can be returned in one or   */
593 /*                two registers.                                    */
594 /*                                                                  */
595 /*------------------------------------------------------------------*/
596
597 static inline gboolean
598 retFitsInReg(guint32 size)
599 {
600         switch (size) {
601                 case 0:
602                 case 1:
603                 case 2:
604                 case 4:
605                 case 8:
606                         return (TRUE);
607                 break;
608                 default:
609                         return (FALSE);
610         }
611 }
612
613 /*========================= End of Function ========================*/
614
615 /*------------------------------------------------------------------*/
616 /*                                                                  */
617 /* Name         - backStackPtr.                                     */
618 /*                                                                  */
619 /* Function     - Restore Stack Pointer to previous frame.          */
620 /*                                                                  */
621 /*------------------------------------------------------------------*/
622
623 static inline guint8 *
624 backUpStackPtr(MonoCompile *cfg, guint8 *code)
625 {
626         int stackSize = cfg->stack_usage;
627
628         if (cfg->frame_reg != STK_BASE)
629                 s390_lgr (code, STK_BASE, cfg->frame_reg);
630
631         if (s390_is_imm16 (stackSize)) {
632                 s390_aghi  (code, STK_BASE, stackSize);
633         } else { 
634                 while (stackSize > 32767) {
635                         s390_aghi  (code, STK_BASE, 32767);
636                         stackSize -= 32767;
637                 }
638                 s390_aghi  (code, STK_BASE, stackSize);
639         }
640         return (code);
641 }
642
643 /*========================= End of Function ========================*/
644
645 /*------------------------------------------------------------------*/
646 /*                                                                  */
647 /* Name         - indent                                            */
648 /*                                                                  */
649 /* Function     - Perform nice indenting to current level           */
650 /*                                                                  */
651 /*------------------------------------------------------------------*/
652
653 static void 
654 indent (int diff) {
655         int v;
656         if (diff < 0)
657                 indent_level += diff;
658         v = indent_level;
659         printf("%p [%3d] ",(void *)pthread_self(),v);
660         while (v-- > 0) {
661                 printf (". ");
662         }
663         if (diff > 0) 
664                 indent_level += diff;
665 }
666
667 /*========================= End of Function ========================*/
668
669 /*------------------------------------------------------------------*/
670 /*                                                                  */
671 /* Name         - cvtMonoType                                       */
672 /*                                                                  */
673 /* Function     - Convert a mono-type to a string.                  */
674 /*                                                                  */
675 /*------------------------------------------------------------------*/
676
677 static const char *
678 cvtMonoType(MonoTypeEnum t)
679 {
680   switch(t)
681     {
682     case MONO_TYPE_END:
683       return "MONO_TYPE_END";
684     case MONO_TYPE_VOID:
685       return "MONO_TYPE_VOID";
686     case MONO_TYPE_BOOLEAN:
687       return "MONO_TYPE_BOOLEAN";
688     case MONO_TYPE_CHAR:
689       return "MONO_TYPE_CHAR";
690     case MONO_TYPE_I1:
691       return "MONO_TYPE_I1";
692     case MONO_TYPE_U1:
693       return "MONO_TYPE_U1";
694     case MONO_TYPE_I2:
695       return "MONO_TYPE_I2";
696     case MONO_TYPE_U2:
697       return "MONO_TYPE_U2";
698     case MONO_TYPE_I4:
699       return "MONO_TYPE_I4";
700     case MONO_TYPE_U4:
701       return "MONO_TYPE_U4";
702     case MONO_TYPE_I8:
703       return "MONO_TYPE_I8";
704     case MONO_TYPE_U8:
705       return "MONO_TYPE_U8";
706     case MONO_TYPE_R4:
707       return "MONO_TYPE_R4";
708     case MONO_TYPE_R8:
709       return "MONO_TYPE_R8";
710     case MONO_TYPE_STRING:
711       return "MONO_TYPE_STRING";
712     case MONO_TYPE_PTR:
713       return "MONO_TYPE_PTR";
714     case MONO_TYPE_BYREF:
715       return "MONO_TYPE_BYREF";
716     case MONO_TYPE_VALUETYPE:
717       return "MONO_TYPE_VALUETYPE";
718     case MONO_TYPE_CLASS:
719       return "MONO_TYPE_CLASS";
720     case MONO_TYPE_VAR:
721       return "MONO_TYPE_VAR";
722     case MONO_TYPE_ARRAY:
723       return "MONO_TYPE_ARRAY";
724     case MONO_TYPE_GENERICINST:
725       return "MONO_TYPE_GENERICINST";
726     case MONO_TYPE_TYPEDBYREF:
727       return "MONO_TYPE_TYPEDBYREF";
728     case MONO_TYPE_I:
729       return "MONO_TYPE_I";
730     case MONO_TYPE_U:
731       return "MONO_TYPE_U";
732     case MONO_TYPE_FNPTR:
733       return "MONO_TYPE_FNPTR";
734     case MONO_TYPE_OBJECT:
735       return "MONO_TYPE_OBJECT";
736     case MONO_TYPE_SZARRAY:
737       return "MONO_TYPE_SZARRAY";
738     case MONO_TYPE_MVAR:
739       return "MONO_TYPE_MVAR";
740     case MONO_TYPE_CMOD_REQD:
741       return "MONO_TYPE_CMOD_REQD";
742     case MONO_TYPE_CMOD_OPT:
743       return "MONO_TYPE_CMOD_OPT";
744     case MONO_TYPE_INTERNAL:
745       return "MONO_TYPE_INTERNAL";
746     case MONO_TYPE_MODIFIER:
747       return "MONO_TYPE_MODIFIER";
748     case MONO_TYPE_SENTINEL:
749       return "MONO_TYPE_SENTINEL";
750     case MONO_TYPE_PINNED:
751       return "MONO_TYPE_PINNED";
752     default:
753       ;
754     }
755   return "unknown";
756 }
757
758 /*========================= End of Function ========================*/
759
760 /*------------------------------------------------------------------*/
761 /*                                                                  */
762 /* Name         - decodeParm                                        */
763 /*                                                                  */
764 /* Function     - Decode a parameter for the trace.                 */
765 /*                                                                  */
766 /*------------------------------------------------------------------*/
767
768 static void
769 decodeParmString (MonoString *s)
770 {
771         MonoError error;
772         char *str = mono_string_to_utf8_checked(s, &error);
773         if (is_ok (&error))  {
774                 printf("[STRING:%p:%s], ", s, str);
775                 g_free (str);
776         } else {
777                 mono_error_cleanup (&error);
778                 printf("[STRING:%p:], ", s);
779         }
780 }
781
782 static void 
783 decodeParm(MonoType *type, void *curParm, int size)
784 {
785         guint32 simpleType;
786
787         if (type->byref) {
788                 printf("[BYREF:%p], ", *((char **) curParm));
789         } else {
790                 simpleType = mini_get_underlying_type(type)->type;
791 enum_parmtype:
792                 switch (simpleType) {
793                         case MONO_TYPE_I :
794                                 printf ("[INTPTR:%p], ", *((int **) curParm));
795                                 break;
796                         case MONO_TYPE_U :
797                                 printf ("[UINTPTR:%p], ", *((int **) curParm));
798                                 break;
799                         case MONO_TYPE_BOOLEAN :
800                                 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
801                                 break;
802                         case MONO_TYPE_CHAR :
803                                 printf ("[CHAR:%c], ", *((int  *) curParm));
804                                 break;
805                         case MONO_TYPE_I1 :
806                                 printf ("[INT1:%ld], ", *((gint64 *) curParm));
807                                 break; 
808                         case MONO_TYPE_I2 :
809                                 printf ("[INT2:%ld], ", *((gint64 *) curParm));
810                                 break; 
811                         case MONO_TYPE_I4 :
812                                 printf ("[INT4:%ld], ", *((gint64 *) curParm));
813                                 break; 
814                         case MONO_TYPE_U1 :
815                                 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
816                                 break; 
817                         case MONO_TYPE_U2 :
818                                 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
819                                 break; 
820                         case MONO_TYPE_U4 :
821                                 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
822                                 break; 
823                         case MONO_TYPE_U8 :
824                                 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
825                                 break; 
826                         case MONO_TYPE_STRING : {
827                                 MonoString *s = *((MonoString **) curParm);
828                                 if (s) {
829                                         g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
830                                         decodeParmString (s);
831                                 } else {
832                                         printf("[STRING:null], ");
833                                 }
834                                 break;
835                         }
836                         case MONO_TYPE_CLASS :
837                         case MONO_TYPE_OBJECT : {
838                                 MonoObject *obj = *((MonoObject **) curParm);
839                                 MonoClass *klass;
840                                 if ((obj) && (obj->vtable)) {
841                                         printf("[CLASS/OBJ:");
842                                         klass = obj->vtable->klass;
843                                         printf("%p [%p] ",obj,curParm);
844                                         if (klass == mono_defaults.string_class) {
845                                                 decodeParmString ((MonoString *)obj);
846                                         } else if (klass == mono_defaults.int32_class) { 
847                                                 printf("[INT32:%p:%d]", 
848                                                         obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
849                                         } else
850                                                 printf("[%s.%s:%p]", 
851                                                        klass->name_space, klass->name, obj);
852                                         printf("], ");
853                                 } else {
854                                         printf("[OBJECT:null], ");
855                                 }
856                                 break;
857                         }
858                         case MONO_TYPE_PTR :
859                                 printf("[PTR:%p], ", *((gpointer **) (curParm)));
860                                 break;
861                         case MONO_TYPE_FNPTR :
862                                 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
863                                 break;
864                         case MONO_TYPE_ARRAY :
865                                 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
866                                 break;
867                         case MONO_TYPE_SZARRAY :
868                                 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
869                                 break;
870                         case MONO_TYPE_I8 :
871                                 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
872                                 break;
873                         case MONO_TYPE_R4 :
874                                 printf("[FLOAT4:%g], ", *((float *) (curParm)));
875                                 break;
876                         case MONO_TYPE_R8 :
877                                 printf("[FLOAT8:%g], ", *((double *) (curParm)));
878                                 break;
879                         case MONO_TYPE_VALUETYPE : {
880                                 int i;
881                                 MonoMarshalType *info;
882
883                                 if (type->data.klass->enumtype) {
884                                         simpleType = mono_class_enum_basetype (type->data.klass)->type;
885                                         printf("{VALUETYPE} - ");
886                                         goto enum_parmtype;
887                                 }
888
889                                 info = mono_marshal_load_type_info (type->data.klass);
890
891                                 if ((info->native_size == sizeof(float)) &&
892                                     (info->num_fields  == 1) &&
893                                     (info->fields[0].field->type->type == MONO_TYPE_R4)) {
894                                                 printf("[FLOAT4:%f], ", *((float *) (curParm)));
895                                         break;
896                                 }
897
898                                 if ((info->native_size == sizeof(double)) &&
899                                     (info->num_fields  == 1) &&
900                                     (info->fields[0].field->type->type == MONO_TYPE_R8)) {
901                                         printf("[FLOAT8:%g], ", *((double *) (curParm)));
902                                         break;
903                                 }
904
905                                 printf("[VALUETYPE:");
906                                 for (i = 0; i < size; i++)
907                                         printf("%02x,", *((guint8 *)curParm+i));
908                                 printf("], ");
909                                 break;
910                         }
911                         case MONO_TYPE_TYPEDBYREF: {
912                                 int i;
913                                 printf("[TYPEDBYREF:");
914                                 for (i = 0; i < size; i++)
915                                         printf("%02x,", *((guint8 *)curParm+i));
916                                 printf("]");
917                                 break;
918                         }
919                         default :
920                                 printf("[%s], ",cvtMonoType(simpleType));
921                 }
922         }
923 }
924
925 /*========================= End of Function ========================*/
926
927 /*------------------------------------------------------------------*/
928 /*                                                                  */
929 /* Name         - enter_method                                      */
930 /*                                                                  */
931 /* Function     - Perform tracing of the entry to the current       */
932 /*                method.                                           */
933 /*                                                                  */
934 /*------------------------------------------------------------------*/
935
936 static void
937 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
938 {
939         int i, oParm = 0, iParm = 0;
940         MonoClass *klass;
941         MonoObject *obj;
942         MonoMethodSignature *sig;
943         char *fname;
944         guint64 ip;
945         CallInfo *cinfo;
946         ArgInfo *ainfo;
947         void *curParm;
948
949         fname = mono_method_full_name (method, TRUE);
950         indent (1);
951         printf ("ENTER: %s ", fname);
952         g_free (fname);
953
954         ip  = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
955         printf ("ip: %p sp: %p - ", (gpointer) ip, sp); 
956
957         if (rParm == NULL)
958                 return;
959         
960         sig = mono_method_signature (method);
961         
962         cinfo = get_call_info (NULL, NULL, sig);
963
964         if (cinfo->struct_ret) {
965                 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
966                 iParm = 1;
967         }
968
969         if (sig->hasthis) {
970                 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
971                 obj = (MonoObject *) this_arg;
972                 switch(method->klass->this_arg.type) {
973                 case MONO_TYPE_VALUETYPE:
974                         if (obj) {
975                                 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
976                                 printf("this:[value:%p:%016lx], ", this_arg, *value);
977                         } else 
978                                 printf ("this:[NULL], ");
979                         break;
980                 case MONO_TYPE_STRING:
981                         if (obj) {
982                                 if (obj->vtable) {
983                                         klass = obj->vtable->klass;
984                                         if (klass == mono_defaults.string_class) {
985                                                 printf ("this:");
986                                                 decodeParmString((MonoString *)obj);
987                                         } else {
988                                                 printf ("this:%p[%s.%s], ", 
989                                                         obj, klass->name_space, klass->name);
990                                         }
991                                 } else 
992                                         printf("vtable:[NULL], ");
993                         } else 
994                                 printf ("this:[NULL], ");
995                         break;
996                 default :
997                         printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
998                 }
999                 oParm++;
1000         }
1001                                         
1002         for (i = 0; i < sig->param_count; ++i) {
1003                 ainfo = &cinfo->args[i + oParm];
1004                 switch (ainfo->regtype) {
1005                         case RegTypeGeneral :
1006                                 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1007                                 break;
1008                         case RegTypeFP :
1009                                 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1010                                 break;
1011                         case RegTypeBase :
1012                                 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1013                                 break;
1014                         case RegTypeStructByVal :
1015                                 if (ainfo->reg != STK_BASE) {
1016                                         int offset = sizeof(glong) - ainfo->size;
1017                                         curParm = &(rParm->gr[ainfo->reg-2])+offset;
1018                                 }
1019                                 else
1020                                         curParm = sp+ainfo->offset;
1021
1022                                 if (retFitsInReg (ainfo->vtsize)) 
1023                                         decodeParm(sig->params[i], 
1024                                                    curParm,
1025                                                    ainfo->size);
1026                                 else
1027                                         decodeParm(sig->params[i], 
1028                                                    *((char **) curParm),
1029                                                    ainfo->vtsize);
1030                                 break;
1031                         case RegTypeStructByAddr :
1032                                 if (ainfo->reg != STK_BASE) 
1033                                         curParm = &(rParm->gr[ainfo->reg-2]);
1034                                 else
1035                                         curParm = sp+ainfo->offset;
1036
1037                                 decodeParm(sig->params[i], 
1038                                            *((char **) curParm),
1039                                            ainfo->vtsize);
1040                                 break;
1041                                 
1042                         default :
1043                                 printf("???, ");
1044                 }
1045         }       
1046         printf("\n");
1047         g_free(cinfo);
1048 }
1049
1050 /*========================= End of Function ========================*/
1051
1052 /*------------------------------------------------------------------*/
1053 /*                                                                  */
1054 /* Name         - leave_method                                      */
1055 /*                                                                  */
1056 /* Function     -                                                   */
1057 /*                                                                  */
1058 /*------------------------------------------------------------------*/
1059
1060 static void
1061 leave_method (MonoMethod *method, ...)
1062 {
1063         MonoType *type;
1064         char *fname;
1065         guint64 ip;
1066         va_list ap;
1067
1068         va_start(ap, method);
1069
1070         fname = mono_method_full_name (method, TRUE);
1071         indent (-1);
1072         printf ("LEAVE: %s", fname);
1073         g_free (fname);
1074
1075         type = mono_method_signature (method)->ret;
1076
1077 handle_enum:
1078         switch (type->type) {
1079         case MONO_TYPE_VOID:
1080                 break;
1081         case MONO_TYPE_BOOLEAN: {
1082                 int val = va_arg (ap, int);
1083                 if (val)
1084                         printf ("[TRUE:%d]", val);
1085                 else 
1086                         printf ("[FALSE]");
1087                         
1088                 break;
1089         }
1090         case MONO_TYPE_CHAR: {
1091                 int val = va_arg (ap, int);
1092                 printf ("[CHAR:%d]", val);
1093                 break;
1094         }
1095         case MONO_TYPE_I1: {
1096                 int val = va_arg (ap, int);
1097                 printf ("[INT1:%d]", val);
1098                 break;
1099         }
1100         case MONO_TYPE_U1: {
1101                 int val = va_arg (ap, int);
1102                 printf ("[UINT1:%d]", val);
1103                 break;
1104         }
1105         case MONO_TYPE_I2: {
1106                 int val = va_arg (ap, int);
1107                 printf ("[INT2:%d]", val);
1108                 break;
1109         }
1110         case MONO_TYPE_U2: {
1111                 int val = va_arg (ap, int);
1112                 printf ("[UINT2:%d]", val);
1113                 break;
1114         }
1115         case MONO_TYPE_I4: {
1116                 int val = va_arg (ap, int);
1117                 printf ("[INT4:%d]", val);
1118                 break;
1119         }
1120         case MONO_TYPE_U4: {
1121                 int val = va_arg (ap, int);
1122                 printf ("[UINT4:%d]", val);
1123                 break;
1124         }
1125         case MONO_TYPE_I: {
1126                 gint64 val = va_arg (ap, gint64);
1127                 printf ("[INT:%ld]", val);
1128                 printf("]");
1129                 break;
1130         }
1131         case MONO_TYPE_U: {
1132                 gint64 val = va_arg (ap, gint64);
1133                 printf ("[UINT:%lu]", val);
1134                 printf("]");
1135                 break;
1136         }
1137         case MONO_TYPE_STRING: {
1138                 MonoString *s = va_arg (ap, MonoString *);
1139 ;
1140                 if (s) {
1141                         g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1142                         decodeParmString (s);
1143                 } else 
1144                         printf ("[STRING:null], ");
1145                 break;
1146         }
1147         case MONO_TYPE_CLASS: 
1148         case MONO_TYPE_OBJECT: {
1149                 MonoObject *o = va_arg (ap, MonoObject *);
1150
1151                 if ((o) && (o->vtable)) {
1152                         if (o->vtable->klass == mono_defaults.boolean_class) {
1153                                 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));            
1154                         } else if  (o->vtable->klass == mono_defaults.int32_class) {
1155                                 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));    
1156                         } else if  (o->vtable->klass == mono_defaults.int64_class) {
1157                                 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));   
1158                         } else
1159                                 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1160                 } else
1161                         printf ("[OBJECT:%p]", o);
1162                
1163                 break;
1164         }
1165         case MONO_TYPE_PTR:
1166         case MONO_TYPE_FNPTR:
1167         case MONO_TYPE_ARRAY:
1168         case MONO_TYPE_SZARRAY: {
1169                 gpointer p = va_arg (ap, gpointer);
1170                 printf ("[result=%p]", p);
1171                 break;
1172         }
1173         case MONO_TYPE_I8: {
1174                 gint64 l =  va_arg (ap, gint64);
1175                 printf ("[LONG:%ld]", l);
1176                 break;
1177         }
1178         case MONO_TYPE_U8: {
1179                 guint64 l =  va_arg (ap, guint64);
1180                 printf ("[ULONG:%lu]", l);
1181                 break;
1182         }
1183         case MONO_TYPE_R4: {
1184                 double f = va_arg (ap, double);
1185                 printf ("[FLOAT4:%g]\n", f);
1186                 break;
1187         }
1188         case MONO_TYPE_R8: {
1189                 double f = va_arg (ap, double);
1190                 printf ("[FLOAT8:%g]\n", f);
1191                 break;
1192         }
1193         case MONO_TYPE_VALUETYPE: {
1194                 MonoMarshalType *info;
1195                 if (type->data.klass->enumtype) {
1196                         type = mono_class_enum_basetype (type->data.klass);
1197                         goto handle_enum;
1198                 } else {
1199                         int size, align;
1200
1201                         info = mono_marshal_load_type_info (type->data.klass);
1202
1203                         if ((info->native_size == sizeof(float)) &&
1204                             (info->num_fields  == 1) &&
1205                             (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1206                                 double f = va_arg (ap, double);
1207                                 printf("[FLOAT4:%g]\n", (double) f);
1208                                 break;
1209                         }
1210
1211                         if ((info->native_size == sizeof(double)) &&
1212                             (info->num_fields  == 1) &&
1213                             (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1214                                 double f = va_arg (ap, double);
1215                                 printf("[FLOAT8:%g]\n", f);
1216                                 break;
1217                         }
1218
1219                         size = mono_type_size (type, &align);
1220                         switch (size) {
1221                                 case 1: {
1222                                         guint32 p = va_arg (ap, guint32);
1223                                         printf ("[%02x]\n",p);
1224                                         break;
1225                                 }
1226                                 case 2: {
1227                                         guint32 p = va_arg (ap, guint32);
1228                                         printf ("[%04x]\n",p);
1229                                         break;
1230                                 }
1231                                 case 4: {
1232                                         guint32 p = va_arg (ap, guint32);
1233                                         printf ("[%08x]\n",p);
1234                                         break;
1235                                 }
1236                                 case 8: {
1237                                         guint64 p = va_arg (ap, guint64);
1238                                         printf ("[%016lx]\n",p);
1239                                         break;
1240                                 }
1241                                 default: {
1242                                         gpointer p = va_arg (ap, gpointer);
1243                                         printf ("[VALUETYPE] %p\n",p);
1244                                 }
1245                         }
1246                 }
1247                 break;
1248         }
1249         case MONO_TYPE_TYPEDBYREF: {
1250                 guint8 *p = va_arg (ap, gpointer);
1251                 int j, size, align;
1252                 size = mono_type_size (type, &align);
1253                 switch (size) {
1254                 case 1:
1255                 case 2:
1256                 case 4:
1257                 case 8:
1258                         printf ("[");
1259                         for (j = 0; p && j < size; j++)
1260                                 printf ("%02x,", p [j]);
1261                         printf ("]\n");
1262                         break;
1263                 default:
1264                         printf ("[TYPEDBYREF]\n");
1265                 }
1266         }
1267                 break;
1268         case MONO_TYPE_GENERICINST: {
1269                 printf("[GENERICINST]\n");
1270         }
1271                 break;
1272         case MONO_TYPE_MVAR: {
1273                 printf("[MVAR]\n");
1274         }
1275                 break;
1276         case MONO_TYPE_CMOD_REQD: {
1277                 printf("[CMOD_REQD]\n");
1278         }
1279                 break;
1280         case MONO_TYPE_CMOD_OPT: {
1281                 printf("[CMOD_OPT]\n");
1282         }
1283                 break;
1284         case MONO_TYPE_INTERNAL: {
1285                 printf("[INTERNAL]\n");
1286         }
1287                 break;
1288         default:
1289                 printf ("(unknown return type %x)", 
1290                         mono_method_signature (method)->ret->type);
1291         }
1292
1293         ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1294         printf (" ip: %p\n", (gpointer) ip);
1295         va_end (ap);
1296 }
1297
1298 /*========================= End of Function ========================*/
1299
1300 /*------------------------------------------------------------------*/
1301 /*                                                                  */
1302 /* Name         - mono_arch_cpu_init                                */
1303 /*                                                                  */
1304 /* Function     - Perform CPU specific initialization to execute    */
1305 /*                managed code.                                     */
1306 /*                                                                  */
1307 /*------------------------------------------------------------------*/
1308
1309 void
1310 mono_arch_cpu_init (void)
1311 {
1312 }
1313
1314 /*========================= End of Function ========================*/
1315
1316 /*------------------------------------------------------------------*/
1317 /*                                                                  */
1318 /* Name         - mono_arch_init.                                   */
1319 /*                                                                  */
1320 /* Function     - Initialize architecture specific code.            */
1321 /*                                                                  */
1322 /*------------------------------------------------------------------*/
1323
1324 void
1325 mono_arch_init (void)
1326 {
1327         guint8 *code;
1328
1329         mono_set_partial_sharing_supported (FALSE);
1330         mono_os_mutex_init_recursive (&mini_arch_mutex);
1331
1332         ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1333         bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1334         mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1335         
1336         code = (guint8 *) &breakpointCode;
1337         s390_basr(code, s390_r13, 0);
1338         s390_j(code, 6);
1339         s390_llong(code, 0);
1340         s390_lg(code, s390_r13, 0, s390_r13, 4);
1341         s390_lg(code, s390_r0, 0, s390_r13, 0);
1342 }
1343
1344 /*========================= End of Function ========================*/
1345
1346 /*------------------------------------------------------------------*/
1347 /*                                                                  */
1348 /* Name         - mono_arch_cleanup.                                */
1349 /*                                                                  */
1350 /* Function     - Cleanup architecture specific code    .           */
1351 /*                                                                  */
1352 /*------------------------------------------------------------------*/
1353
1354 void
1355 mono_arch_cleanup (void)
1356 {
1357         if (ss_trigger_page)
1358                 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1359         if (bp_trigger_page)
1360                 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1361         mono_os_mutex_destroy (&mini_arch_mutex);
1362 }
1363
1364 /*========================= End of Function ========================*/
1365
1366 /*------------------------------------------------------------------*/
1367 /*                                                                  */
1368 /* Name         - mono_arch_cpu_optimizations                       */
1369 /*                                                                  */
1370 /* Function     - Returns the optimizations supported on this CPU   */
1371 /*                                                                  */
1372 /*------------------------------------------------------------------*/
1373
1374 guint32
1375 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1376 {
1377         guint32 opts = 0;
1378
1379         /*----------------------------------------------------------*/
1380         /* No s390-specific optimizations yet                       */
1381         /*----------------------------------------------------------*/
1382         *exclude_mask = MONO_OPT_LINEARS;
1383         return opts;
1384 }
1385
1386 /*========================= End of Function ========================*/
1387
1388 /*------------------------------------------------------------------*/
1389 /*                                                                  */
1390 /* Name         - mono_arch_get_allocatable_int_vars                */
1391 /*                                                                  */
1392 /* Function     -                                                   */
1393 /*                                                                  */
1394 /*------------------------------------------------------------------*/
1395
1396 GList *
1397 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1398 {
1399         GList *vars = NULL;
1400         int i;
1401
1402         for (i = 0; i < cfg->num_varinfo; i++) {
1403                 MonoInst *ins = cfg->varinfo [i];
1404                 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1405
1406                 /* unused vars */
1407                 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1408                         continue;
1409
1410                 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || 
1411                     (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1412                         continue;
1413
1414                 /* we can only allocate 32 bit values */
1415                 if (mono_is_regsize_var(ins->inst_vtype)) {
1416                         g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1417                         g_assert (i == vmv->idx);
1418                         vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1419                 }
1420         }
1421
1422         return vars;
1423 }
1424
1425 /*========================= End of Function ========================*/
1426
1427 /*------------------------------------------------------------------*/
1428 /*                                                                  */
1429 /* Name         - mono_arch_global_int_regs                         */
1430 /*                                                                  */
1431 /* Function     - Return a list of usable integer registers.        */
1432 /*                                                                  */
1433 /*------------------------------------------------------------------*/
1434
1435 GList *
1436 mono_arch_get_global_int_regs (MonoCompile *cfg)
1437 {
1438         GList *regs = NULL;
1439         MonoMethodHeader *header;
1440         int i, top = 13;
1441
1442         header = cfg->header;
1443         if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1444                 cfg->frame_reg = s390_r11;
1445
1446
1447         /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1448         top = 12;
1449         for (i = 8; i < top; ++i) {
1450                 if (cfg->frame_reg != i)
1451                         regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1452         }
1453
1454         return regs;
1455 }
1456
1457 /*========================= End of Function ========================*/
1458
1459 /*------------------------------------------------------------------*/
1460 /*                                                                  */
1461 /* Name         -  mono_arch_flush_icache                           */
1462 /*                                                                  */
1463 /* Function     -  Flush the CPU icache.                            */
1464 /*                                                                  */
1465 /*------------------------------------------------------------------*/
1466
1467 void
1468 mono_arch_flush_icache (guint8 *code, gint size)
1469 {
1470 }
1471
1472 /*========================= End of Function ========================*/
1473
1474 /*------------------------------------------------------------------*/
1475 /*                                                                  */
1476 /* Name         - add_general                                       */
1477 /*                                                                  */
1478 /* Function     - Determine code and stack size incremements for a  */
1479 /*                parameter.                                        */
1480 /*                                                                  */
1481 /*------------------------------------------------------------------*/
1482
1483 static void inline
1484 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1485 {
1486         if (*gr > S390_LAST_ARG_REG) {
1487                 sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1488                 ainfo->offset   = sz->stack_size;
1489                 ainfo->reg      = STK_BASE;
1490                 ainfo->regtype  = RegTypeBase;
1491                 sz->stack_size += sizeof(long);
1492                 sz->local_size += sizeof(long);
1493                 sz->offStruct  += sizeof(long);
1494                 sz->code_size  += 12;    
1495         } else {
1496                 ainfo->reg      = *gr;
1497                 sz->code_size  += 8;    
1498         }
1499         (*gr) ++;
1500 }
1501
1502 /*========================= End of Function ========================*/
1503
1504 /*------------------------------------------------------------------*/
1505 /*                                                                  */
1506 /* Name         - add_stackParm                                     */
1507 /*                                                                  */
1508 /* Function     - Determine code and stack size incremements for a  */
1509 /*                parameter.                                        */
1510 /*                                                                  */
1511 /*------------------------------------------------------------------*/
1512
1513 static void inline
1514 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1515 {
1516         if (*gr > S390_LAST_ARG_REG) {
1517                 sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1518                 ainfo->reg          = STK_BASE;
1519                 ainfo->offset   = sz->stack_size;
1520                 ainfo->regtype  = RegTypeStructByAddrOnStack; 
1521                 sz->stack_size += sizeof (gpointer);
1522                 sz->parm_size  += sizeof(gpointer);
1523                 sz->offStruct  += sizeof(gpointer);
1524         } else {
1525                 ainfo->reg      = *gr;
1526                 ainfo->offset   = sz->stack_size;
1527                 ainfo->regtype  = RegTypeStructByAddr; 
1528         }
1529         (*gr) ++;
1530         ainfo->offparm  = sz->offset;
1531         sz->offset      = S390_ALIGN(sz->offset+size, sizeof(long));
1532         ainfo->size     = size;
1533         ainfo->vtsize   = size;
1534         sz->parm_size  += size;
1535 }
1536
1537 /*========================= End of Function ========================*/
1538
1539 /*------------------------------------------------------------------*/
1540 /*                                                                  */
1541 /* Name         - add_float                                         */
1542 /*                                                                  */
1543 /* Function     - Determine code and stack size incremements for a  */
1544 /*                float parameter.                                  */
1545 /*                                                                  */
1546 /*------------------------------------------------------------------*/
1547
1548 static void inline
1549 add_float (guint *fr,  size_data *sz, ArgInfo *ainfo)
1550 {
1551         if ((*fr) <= S390_LAST_FPARG_REG) {
1552                 ainfo->regtype = RegTypeFP;
1553                 ainfo->reg     = *fr;
1554                 sz->code_size += 4;
1555                 (*fr) += 2;
1556         }
1557         else {
1558                 ainfo->offset   = sz->stack_size;
1559                 ainfo->reg      = STK_BASE;
1560                 ainfo->regtype  = RegTypeBase;
1561                 sz->code_size  += 4;
1562                 sz->stack_size += sizeof(double);
1563                 sz->local_size += sizeof(double);
1564                 sz->offStruct  += sizeof(double);
1565         }
1566 }
1567
1568 /*========================= End of Function ========================*/
1569
1570 /*------------------------------------------------------------------*/
1571 /*                                                                  */
1572 /* Name         - get_call_info                                     */
1573 /*                                                                  */
1574 /* Function     - Determine the amount of space required for code   */
1575 /*                and stack. In addition determine starting points  */
1576 /*                for stack-based parameters, and area for struct-  */
1577 /*                ures being returned on the stack.                 */
1578 /*                                                                  */
1579 /*------------------------------------------------------------------*/
1580
1581 static CallInfo *
1582 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1583 {
1584         guint i, fr, gr, size, pstart;
1585         int nParm = sig->hasthis + sig->param_count;
1586         MonoType *ret_type;
1587         guint32 simpleType, align;
1588         gboolean is_pinvoke = sig->pinvoke;
1589         CallInfo *cinfo;
1590         size_data *sz;
1591
1592         if (mp)
1593                 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1594         else
1595                 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1596
1597         fr                = 0;
1598         gr                = s390_r2;
1599         nParm             = 0;
1600         cinfo->struct_ret = 0;
1601         sz                = &cinfo->sz;
1602         sz->retStruct     = 0;
1603         sz->offset        = 0;
1604         sz->offStruct     = S390_MINIMAL_STACK_SIZE;
1605         sz->stack_size    = S390_MINIMAL_STACK_SIZE;
1606         sz->code_size     = 0;
1607         sz->parm_size     = 0;
1608         sz->local_size    = 0;
1609         align             = 0;
1610         size              = 0;
1611
1612         /*----------------------------------------------------------*/
1613         /* We determine the size of the return code/stack in case we*/
1614         /* need to reserve a register to be used to address a stack */
1615         /* area that the callee will use.                           */
1616         /*----------------------------------------------------------*/
1617
1618         ret_type = mini_get_underlying_type (sig->ret);
1619         simpleType = ret_type->type;
1620 enum_retvalue:
1621         switch (simpleType) {
1622                 case MONO_TYPE_BOOLEAN:
1623                 case MONO_TYPE_I1:
1624                 case MONO_TYPE_U1:
1625                 case MONO_TYPE_I2:
1626                 case MONO_TYPE_U2:
1627                 case MONO_TYPE_CHAR:
1628                 case MONO_TYPE_I4:
1629                 case MONO_TYPE_U4:
1630                 case MONO_TYPE_I:
1631                 case MONO_TYPE_U:
1632                 case MONO_TYPE_CLASS:
1633                 case MONO_TYPE_OBJECT:
1634                 case MONO_TYPE_SZARRAY:
1635                 case MONO_TYPE_ARRAY:
1636                 case MONO_TYPE_PTR:
1637                 case MONO_TYPE_FNPTR:
1638                 case MONO_TYPE_STRING:
1639                         cinfo->ret.reg = s390_r2;
1640                         sz->code_size += 4;
1641                         break;
1642                 case MONO_TYPE_R4:
1643                 case MONO_TYPE_R8:
1644                         cinfo->ret.reg = s390_f0;
1645                         sz->code_size += 4;
1646                         break;
1647                 case MONO_TYPE_I8:
1648                 case MONO_TYPE_U8:
1649                         cinfo->ret.reg = s390_r2;
1650                         sz->code_size += 4;
1651                         break;
1652                 case MONO_TYPE_GENERICINST:
1653                         if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1654                                 cinfo->ret.reg = s390_r2;
1655                                 sz->code_size += 4;
1656                                 break;
1657                         }
1658                         /* Fall through */
1659                 case MONO_TYPE_VALUETYPE: {
1660                         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1661                         if (klass->enumtype) {
1662                                 simpleType = mono_class_enum_basetype (klass)->type;
1663                                 goto enum_retvalue;
1664                         }
1665                         size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1666         
1667                         cinfo->struct_ret = 1;
1668                         cinfo->ret.size   = size;
1669                         cinfo->ret.vtsize = size;
1670                         break;
1671                 }
1672                 case MONO_TYPE_TYPEDBYREF:
1673                         size = sizeof (MonoTypedRef);
1674                         cinfo->struct_ret = 1;
1675                         cinfo->ret.size   = size;
1676                         cinfo->ret.vtsize = size;
1677                         break;
1678                 case MONO_TYPE_VOID:
1679                         break;
1680                 default:
1681                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
1682         }
1683
1684
1685         pstart = 0;
1686         /*
1687          * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1688          * the first argument, allowing 'this' to be always passed in the first arg reg.
1689          * Also do this if the first argument is a reference type, since virtual calls
1690          * are sometimes made using calli without sig->hasthis set, like in the delegate
1691          * invoke wrappers.
1692          */
1693         if (cinfo->struct_ret && !is_pinvoke && 
1694             (sig->hasthis || 
1695              (sig->param_count > 0 && 
1696               MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1697                 if (sig->hasthis) {
1698                         cinfo->args[nParm].size = sizeof (gpointer);
1699                         add_general (&gr, sz, cinfo->args + nParm);
1700                 } else {
1701                         cinfo->args[nParm].size = sizeof (gpointer);
1702                         add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1703                         pstart = 1;
1704                 }
1705                 nParm ++;
1706                 cinfo->vret_arg_index = 1;
1707                 cinfo->ret.reg = gr;
1708                 gr ++;
1709         } else {
1710                 /* this */
1711                 if (sig->hasthis) {
1712                         cinfo->args[nParm].size = sizeof (gpointer);
1713                         add_general (&gr, sz, cinfo->args + nParm);
1714                         nParm ++;
1715                 }
1716
1717                 if (cinfo->struct_ret) {
1718                         cinfo->ret.reg = gr;
1719                         gr ++;
1720                 }
1721         }
1722
1723         if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1724                 gr = S390_LAST_ARG_REG + 1;
1725                 fr = S390_LAST_FPARG_REG + 1;
1726
1727                 /* Emit the signature cookie just before the implicit arguments */
1728                 add_general (&gr, sz, &cinfo->sigCookie);
1729         }
1730
1731         /*----------------------------------------------------------*/
1732         /* We determine the size of the parameter code and stack    */
1733         /* requirements by checking the types and sizes of the      */
1734         /* parameters.                                              */
1735         /*----------------------------------------------------------*/
1736
1737         for (i = pstart; i < sig->param_count; ++i) {
1738                 MonoType *ptype;
1739
1740                 /*--------------------------------------------------*/
1741                 /* Handle vararg type calls. All args are put on    */
1742                 /* the stack.                                       */
1743                 /*--------------------------------------------------*/
1744                 if ((sig->call_convention == MONO_CALL_VARARG) &&
1745                     (i == sig->sentinelpos)) {
1746                         gr = S390_LAST_ARG_REG + 1;
1747                         fr = S390_LAST_FPARG_REG + 1;
1748                         add_general (&gr, sz, &cinfo->sigCookie);
1749                 }
1750
1751                 if (sig->params [i]->byref) {
1752                         add_general (&gr, sz, cinfo->args+nParm);
1753                         cinfo->args[nParm].size = sizeof(gpointer);
1754                         nParm++;
1755                         continue;
1756                 }
1757
1758                 ptype = mini_get_underlying_type (sig->params [i]);
1759                 simpleType = ptype->type;
1760                 cinfo->args[nParm].type = simpleType;
1761                 switch (simpleType) {
1762                 case MONO_TYPE_BOOLEAN:
1763                 case MONO_TYPE_I1:
1764                 case MONO_TYPE_U1:
1765                         cinfo->args[nParm].size = sizeof(char);
1766                         add_general (&gr, sz, cinfo->args+nParm);
1767                         nParm++;
1768                         break;
1769                 case MONO_TYPE_I2:
1770                 case MONO_TYPE_U2:
1771                 case MONO_TYPE_CHAR:
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_CLASS:
1787                 case MONO_TYPE_OBJECT:
1788                 case MONO_TYPE_STRING:
1789                 case MONO_TYPE_SZARRAY:
1790                 case MONO_TYPE_ARRAY:
1791                         cinfo->args[nParm].size = sizeof(gpointer);
1792                         add_general (&gr, sz, cinfo->args+nParm);
1793                         nParm++;
1794                         break;
1795                 case MONO_TYPE_I8:
1796                 case MONO_TYPE_U8:
1797                         cinfo->args[nParm].size = sizeof(long long);
1798                         add_general (&gr, sz, cinfo->args+nParm);
1799                         nParm++;
1800                         break;
1801                 case MONO_TYPE_R4:
1802                         cinfo->args[nParm].size = sizeof(float);
1803                         add_float (&fr, sz, cinfo->args+nParm);
1804                         nParm++;
1805                         break;
1806                 case MONO_TYPE_R8:
1807                         cinfo->args[nParm].size = sizeof(double);
1808                         add_float (&fr, sz, cinfo->args+nParm);
1809                         nParm++;
1810                         break;
1811                 case MONO_TYPE_GENERICINST:
1812                         if (!mono_type_generic_inst_is_valuetype (ptype)) {
1813                                 cinfo->args[nParm].size = sizeof(gpointer);
1814                                 add_general (&gr, sz, cinfo->args+nParm);
1815                                 nParm++;
1816                                 break;
1817                         }
1818                         /* Fall through */
1819                 case MONO_TYPE_VALUETYPE: {
1820                         MonoMarshalType *info;
1821                         MonoClass *klass = mono_class_from_mono_type (ptype);
1822
1823                         if (sig->pinvoke)
1824                                 size = mono_class_native_size(klass, NULL);
1825                         else
1826                                 size = mono_class_value_size(klass, NULL);
1827
1828                         if (simpleType != MONO_TYPE_GENERICINST) {
1829                                 info = mono_marshal_load_type_info(klass);
1830
1831                                 if ((info->native_size == sizeof(float)) &&
1832                                     (info->num_fields  == 1) &&
1833                                     (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1834                                         cinfo->args[nParm].size = sizeof(float);
1835                                         add_float(&fr, sz, cinfo->args+nParm);
1836                                         nParm ++;
1837                                         break;
1838                                 }
1839
1840                                 if ((info->native_size == sizeof(double)) &&
1841                                     (info->num_fields  == 1) &&
1842                                     (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1843                                         cinfo->args[nParm].size = sizeof(double);
1844                                         add_float(&fr, sz, cinfo->args+nParm);
1845                                         nParm ++;
1846                                         break;
1847                                 }
1848                         }
1849
1850                         cinfo->args[nParm].vtsize  = 0;
1851                         cinfo->args[nParm].size    = 0;
1852
1853                         switch (size) {
1854                                 /*----------------------------------*/
1855                                 /* On S/390, structures of size 1,  */
1856                                 /* 2, 4, and 8 bytes are passed in  */
1857                                 /* (a) register(s).                 */
1858                                 /*----------------------------------*/
1859                                 case 0:
1860                                 case 1:
1861                                 case 2:
1862                                 case 4:
1863                                 case 8:
1864                                         add_general(&gr, sz, cinfo->args+nParm);
1865                                         cinfo->args[nParm].size    = size;
1866                                         cinfo->args[nParm].regtype = RegTypeStructByVal; 
1867                                         nParm++;
1868                                         sz->local_size            += sizeof(long);
1869                                         break;
1870                                 default:
1871                                         add_stackParm(&gr, sz, cinfo->args+nParm, size);
1872                                         nParm++;
1873                         }
1874                 }
1875                         break;
1876                 case MONO_TYPE_TYPEDBYREF: {
1877                         int size = sizeof (MonoTypedRef);
1878
1879                         cinfo->args[nParm].vtsize  = 0;
1880                         cinfo->args[nParm].size    = 0;
1881
1882                         switch (size) {
1883                                 /*----------------------------------*/
1884                                 /* On S/390, structures of size 1,  */
1885                                 /* 2, 4, and 8 bytes are passed in  */
1886                                 /* (a) register(s).                 */
1887                                 /*----------------------------------*/
1888                                 case 0:
1889                                 case 1:
1890                                 case 2:
1891                                 case 4:
1892                                 case 8:
1893                                         add_general(&gr, sz, cinfo->args+nParm);
1894                                         cinfo->args[nParm].size    = size;
1895                                         cinfo->args[nParm].regtype = RegTypeStructByVal; 
1896                                         nParm++;
1897                                         sz->local_size            += sizeof(long);
1898                                         break;
1899                                 default:
1900                                         add_stackParm(&gr, sz, cinfo->args+nParm, size);
1901                                         nParm++;
1902                         }
1903                 }
1904                         break;
1905                 default:
1906                         g_error ("Can't trampoline 0x%x", ptype);
1907                 }
1908         }
1909
1910         /*----------------------------------------------------------*/
1911         /* Handle the case where there are no implicit arguments    */
1912         /*----------------------------------------------------------*/
1913         if ((sig->call_convention == MONO_CALL_VARARG) &&
1914             (nParm > 0) &&
1915             (!sig->pinvoke) &&
1916             (sig->param_count == sig->sentinelpos)) {
1917                 gr = S390_LAST_ARG_REG + 1;
1918                 fr = S390_LAST_FPARG_REG + 1;
1919                 add_general (&gr, sz, &cinfo->sigCookie);
1920         }
1921
1922         /*----------------------------------------------------------*/
1923         /* If we are passing a structure back then if it won't be   */
1924         /* in a register(s) then we make room at the end of the     */
1925         /* parameters that may have been placed on the stack        */
1926         /*----------------------------------------------------------*/
1927         if (cinfo->struct_ret) {
1928                 cinfo->ret.offset = sz->stack_size;
1929                 switch (cinfo->ret.size) {
1930                 case 0:
1931                 case 1:
1932                 case 2:
1933                 case 4:
1934                 case 8:
1935                         break;
1936                 default:
1937                         sz->stack_size   += S390_ALIGN(cinfo->ret.size, align);
1938                 }
1939         }
1940
1941         cinfo->lastgr   = gr;
1942         sz->stack_size  = sz->stack_size + sz->local_size + sz->parm_size + 
1943                           sz->offset;
1944         sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1945
1946         return (cinfo);
1947 }
1948
1949 /*========================= End of Function ========================*/
1950
1951 /*------------------------------------------------------------------*/
1952 /*                                                                  */
1953 /* Name         - mono_arch_allocate_vars                           */
1954 /*                                                                  */
1955 /* Function     - Set var information according to the calling      */
1956 /*                convention for S/390. The local var stuff should  */
1957 /*                most likely be split in another method.           */
1958 /*                                                                  */
1959 /* Parameter    - @m - Compile unit.                                */
1960 /*                                                                  */
1961 /*------------------------------------------------------------------*/
1962
1963 void
1964 mono_arch_allocate_vars (MonoCompile *cfg)
1965 {
1966         MonoMethodSignature *sig;
1967         MonoMethodHeader *header;
1968         MonoInst *inst;
1969         CallInfo *cinfo;
1970         int iParm, iVar, offset, align, size, curinst;
1971         int frame_reg = STK_BASE;
1972         int sArg, eArg;
1973
1974         header  = cfg->header;
1975
1976         cfg->flags |= MONO_CFG_HAS_SPILLUP;
1977
1978         /*---------------------------------------------------------*/    
1979         /* We use the frame register also for any method that has  */ 
1980         /* filter clauses. This way, when the handlers are called, */
1981         /* the code will reference local variables using the frame */
1982         /* reg instead of the stack pointer: if we had to restore  */
1983         /* the stack pointer, we'd corrupt the method frames that  */
1984         /* are already on the stack (since filters get called      */
1985         /* before stack unwinding happens) when the filter code    */
1986         /* would call any method.                                  */
1987         /*---------------------------------------------------------*/    
1988         if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1989                 frame_reg = s390_r11;
1990
1991         cfg->frame_reg = frame_reg;
1992
1993         cfg->arch.bkchain_reg = -1;
1994
1995         if (frame_reg != STK_BASE) 
1996                 cfg->used_int_regs |= (1 << frame_reg);         
1997
1998         if (cfg->uses_rgctx_reg)
1999                 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2000
2001         sig     = mono_method_signature (cfg->method);
2002         
2003         cinfo   = get_call_info (cfg, cfg->mempool, sig);
2004
2005         if (!cinfo->struct_ret) {
2006                 switch (mini_get_underlying_type (sig->ret)->type) {
2007                 case MONO_TYPE_VOID:
2008                         break;
2009                 default:
2010                         cfg->ret->opcode = OP_REGVAR;
2011                         cfg->ret->dreg   = s390_r2;
2012                         break;
2013                 }
2014         }
2015
2016         /*--------------------------------------------------------------*/
2017         /* local vars are at a positive offset from the stack pointer   */
2018         /* also note that if the function uses alloca, we use s390_r11  */
2019         /* to point at the local variables.                             */
2020         /* add parameter area size for called functions                 */
2021         /*--------------------------------------------------------------*/
2022         if (cfg->param_area == 0)
2023                 offset = S390_MINIMAL_STACK_SIZE;
2024         else
2025                 offset = cfg->param_area;
2026
2027         cfg->sig_cookie = 0;
2028
2029         if (cinfo->struct_ret) {
2030                 inst               = cfg->vret_addr;
2031                 offset             = S390_ALIGN(offset, sizeof(gpointer));
2032                 inst->inst_offset  = offset;
2033                 inst->opcode       = OP_REGOFFSET;
2034                 inst->inst_basereg = frame_reg;
2035                 offset            += sizeof(gpointer);
2036                 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2037                         printf ("vret_addr =");
2038                         mono_print_ins (cfg->vret_addr);
2039                 }
2040         }
2041
2042         if (sig->hasthis) {
2043                 inst = cfg->args [0];
2044                 if (inst->opcode != OP_REGVAR) {
2045                         inst->opcode       = OP_REGOFFSET;
2046                         inst->inst_basereg = frame_reg;
2047                         offset             = S390_ALIGN(offset, sizeof(gpointer));
2048                         inst->inst_offset  = offset;
2049                         offset            += sizeof (gpointer);
2050                 }
2051                 curinst = sArg = 1;
2052         } else {
2053                 curinst = sArg = 0;
2054         }
2055
2056         eArg = sig->param_count + sArg;
2057
2058         if (sig->call_convention == MONO_CALL_VARARG)
2059                 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2060
2061         for (iParm = sArg; iParm < eArg; ++iParm) {
2062                 inst = cfg->args [curinst];
2063                 if (inst->opcode != OP_REGVAR) {
2064                         switch (cinfo->args[iParm].regtype) {
2065                         case RegTypeStructByAddr : {
2066                                 MonoInst *indir;
2067
2068                                 size = sizeof (gpointer);
2069
2070                                 inst->opcode       = OP_REGOFFSET;
2071                                 inst->inst_basereg = frame_reg;
2072                                 offset             = S390_ALIGN (offset, sizeof (gpointer));
2073                                 inst->inst_offset  = offset;
2074
2075                                 /* Add a level of indirection */
2076                                 MONO_INST_NEW (cfg, indir, 0);
2077                                 *indir          = *inst;
2078                                 inst->opcode    = OP_VTARG_ADDR;
2079                                 inst->inst_left = indir;
2080                         }
2081                                 break;
2082                         case RegTypeStructByAddrOnStack : {
2083                                 MonoInst *indir;
2084
2085                                 size = sizeof (gpointer);
2086
2087                                 /* Similar to the == STK_BASE case below */
2088                                 cfg->arch.bkchain_reg = s390_r12;
2089                                 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2090
2091                                 inst->opcode = OP_REGOFFSET;
2092                                 inst->dreg = mono_alloc_preg (cfg);
2093                                 inst->inst_basereg = cfg->arch.bkchain_reg;
2094                                 inst->inst_offset = cinfo->args [iParm].offset;
2095
2096                                 /* Add a level of indirection */
2097                                 MONO_INST_NEW (cfg, indir, 0);
2098                                 *indir = *inst;
2099                                 inst->opcode = OP_VTARG_ADDR;
2100                                 inst->inst_left = indir;
2101                                 break;
2102                         }
2103                         case RegTypeStructByVal :
2104                                 size               = cinfo->args[iParm].size;
2105                                 offset             = S390_ALIGN(offset, size);
2106                                 inst->opcode       = OP_REGOFFSET;
2107                                 inst->inst_basereg = frame_reg;
2108                                 inst->inst_offset  = offset;
2109                                 break;
2110                         default :
2111                                 if (cinfo->args [iParm].reg == STK_BASE) {
2112                                         /*
2113                                          * These arguments are in the previous frame, so we can't 
2114                                          * compute their offset from the current frame pointer right
2115                                          * now, since cfg->stack_offset is not yet known, so dedicate a 
2116                                          * register holding the previous frame pointer.
2117                                          */
2118                                         cfg->arch.bkchain_reg = s390_r12;
2119                                         cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2120
2121                                         inst->opcode       = OP_REGOFFSET;
2122                                         inst->inst_basereg = cfg->arch.bkchain_reg;
2123                                         size               = (cinfo->args[iParm].size < 8
2124                                                                           ? 8 - cinfo->args[iParm].size
2125                                                                           : 0);
2126                                         inst->inst_offset  = cinfo->args [iParm].offset + size;
2127                                         size = sizeof (long);
2128                                 } else {
2129                                         inst->opcode       = OP_REGOFFSET;
2130                                         inst->inst_basereg = frame_reg;
2131                                         size               = (cinfo->args[iParm].size < 8
2132                                                                           ? sizeof(int)  
2133                                                                           : sizeof(long));
2134                                         offset             = S390_ALIGN(offset, size);
2135                                         if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) 
2136                                                 inst->inst_offset  = offset;
2137                                         else
2138                                                 inst->inst_offset  = offset + (8 - size);
2139                                 }
2140                                 break;
2141                         }
2142 #if 0
2143                         if ((sig->call_convention == MONO_CALL_VARARG) && 
2144                             (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2145                             (iParm < sig->sentinelpos)) 
2146                                 cfg->sig_cookie += size;
2147 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2148 #endif
2149
2150                         offset += MAX(size, 8);
2151                 }
2152                 curinst++;
2153         }
2154
2155         cfg->locals_min_stack_offset = offset;
2156
2157         curinst = cfg->locals_start;
2158         for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2159                 inst = cfg->varinfo [iVar];
2160                 if ((inst->flags & MONO_INST_IS_DEAD) || 
2161                     (inst->opcode == OP_REGVAR))
2162                         continue;
2163
2164                 /*--------------------------------------------------*/
2165                 /* inst->backend.is_pinvoke indicates native sized  */
2166                 /* value typs this is used by the pinvoke wrappers  */
2167                 /* when they call functions returning structure     */
2168                 /*--------------------------------------------------*/
2169                 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2170                         size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype), 
2171                                                        (guint32 *) &align);
2172                 else
2173                         size = mono_type_size (inst->inst_vtype, &align);
2174
2175                 offset             = S390_ALIGN(offset, align);
2176                 inst->inst_offset  = offset;
2177                 inst->opcode       = OP_REGOFFSET;
2178                 inst->inst_basereg = frame_reg;
2179                 offset            += size;
2180                 DEBUG (g_print("allocating local %d to %ld, size: %d\n", 
2181                                 iVar, inst->inst_offset, size));
2182         }
2183
2184         cfg->locals_max_stack_offset = offset;
2185
2186         /*------------------------------------------------------*/
2187         /* Allow space for the trace method stack area if needed*/
2188         /*------------------------------------------------------*/
2189         if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)) 
2190             || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2191                 offset += S390_TRACE_STACK_SIZE;
2192
2193         /*------------------------------------------------------*/
2194         /* Reserve space to save LMF and caller saved registers */
2195         /*------------------------------------------------------*/
2196         if (cfg->method->save_lmf)
2197                 offset += sizeof (MonoLMF);
2198
2199         /*------------------------------------------------------*/
2200         /* align the offset                                     */
2201         /*------------------------------------------------------*/
2202         cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2203
2204         /*------------------------------------------------------*/
2205         /* Fix offsets for args whose value is in parent frame  */
2206         /*------------------------------------------------------*/
2207         for (iParm = sArg; iParm < eArg; ++iParm) {
2208                 inst = cfg->args [iParm];
2209
2210                 if (inst->opcode == OP_S390_STKARG) {
2211                         inst->opcode = OP_REGOFFSET;
2212                         inst->inst_offset += cfg->stack_offset;
2213                 }
2214         }
2215 }
2216
2217 /*========================= End of Function ========================*/
2218
2219 /*------------------------------------------------------------------*/
2220 /*                                                                  */
2221 /* Name         - mono_arch_create_vars                             */
2222 /*                                                                  */
2223 /*------------------------------------------------------------------*/
2224
2225 void
2226 mono_arch_create_vars (MonoCompile *cfg)
2227 {
2228         MonoMethodSignature *sig;
2229         CallInfo *cinfo;
2230
2231         sig = mono_method_signature (cfg->method);
2232
2233         cinfo = get_call_info (cfg, cfg->mempool, sig);
2234
2235         if (cinfo->struct_ret) {
2236                 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2237                 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2238                         printf ("vret_addr = ");
2239                         mono_print_ins (cfg->vret_addr);
2240                 }
2241         }
2242 }
2243
2244 /*========================= End of Function ========================*/
2245
2246 /*------------------------------------------------------------------*/
2247 /*                                                                  */
2248 /* Name         - add_outarg_reg2.                                  */
2249 /*                                                                  */
2250 /*------------------------------------------------------------------*/
2251
2252 static void
2253 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2254 {
2255         MonoInst *ins;
2256
2257         switch (storage) {
2258         case RegTypeGeneral:
2259                 MONO_INST_NEW (cfg, ins, OP_MOVE);
2260                 ins->dreg = mono_alloc_ireg (cfg);
2261                 ins->sreg1 = tree->dreg;
2262                 MONO_ADD_INS (cfg->cbb, ins);
2263                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2264                 break;
2265         case RegTypeFP:
2266                 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2267                 ins->dreg = mono_alloc_freg (cfg);
2268                 ins->sreg1 = tree->dreg;
2269                 MONO_ADD_INS (cfg->cbb, ins);
2270                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2271                 break;
2272         case RegTypeFPR4:
2273                 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2274                 ins->dreg = mono_alloc_freg (cfg);
2275                 ins->sreg1 = tree->dreg;
2276                 MONO_ADD_INS (cfg->cbb, ins);
2277                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2278                 break;
2279         default:
2280                 g_assert_not_reached ();
2281         }
2282 }
2283
2284 /*========================= End of Function ========================*/
2285
2286 /*------------------------------------------------------------------*/
2287 /*                                                                  */
2288 /* Name         - emit_sig_cookie.                                  */
2289 /*                                                                  */
2290 /*------------------------------------------------------------------*/
2291
2292 static void
2293 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2294 {
2295         MonoMethodSignature *tmpSig;
2296         MonoInst *sig_arg;
2297                         
2298         cfg->disable_aot = TRUE;
2299
2300         /*----------------------------------------------------------*/
2301         /* mono_ArgIterator_Setup assumes the signature cookie is   */
2302         /* passed first and all the arguments which were before it  */
2303         /* passed on the stack after the signature. So compensate   */
2304         /* by passing a different signature.                        */
2305         /*----------------------------------------------------------*/
2306         tmpSig = mono_metadata_signature_dup (call->signature);
2307         tmpSig->param_count -= call->signature->sentinelpos;
2308         tmpSig->sentinelpos  = 0;
2309         if (tmpSig->param_count > 0)
2310                 memcpy (tmpSig->params, 
2311                         call->signature->params + call->signature->sentinelpos, 
2312                         tmpSig->param_count * sizeof(MonoType *));
2313
2314         MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2315         sig_arg->dreg = mono_alloc_ireg (cfg);
2316         sig_arg->inst_p0 = tmpSig;
2317         MONO_ADD_INS (cfg->cbb, sig_arg);
2318
2319         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE, 
2320                                      cinfo->sigCookie.offset, sig_arg->dreg);
2321 }
2322
2323 /*========================= End of Function ========================*/
2324
2325 /*------------------------------------------------------------------*/
2326 /*                                                                  */
2327 /* Name         - mono_arch_emit_call                               */
2328 /*                                                                  */
2329 /*------------------------------------------------------------------*/
2330
2331 void
2332 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2333 {
2334         MonoInst *in;
2335         MonoMethodSignature *sig;
2336         MonoInst *ins;
2337         int i, n, lParamArea;
2338         CallInfo *cinfo;
2339         ArgInfo *ainfo = NULL;
2340         int stackSize;    
2341         MonoMethodHeader *header;
2342         int frmReg;
2343
2344         sig = call->signature;
2345         n = sig->param_count + sig->hasthis;
2346         DEBUG (g_print ("Call requires: %d parameters\n",n));
2347         
2348         cinfo = get_call_info (cfg, cfg->mempool, sig);
2349
2350         stackSize         = cinfo->sz.stack_size + cinfo->sz.local_size + 
2351                             cinfo->sz.parm_size + cinfo->sz.offset;
2352         call->stack_usage = MAX(stackSize, call->stack_usage);
2353         lParamArea        = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2354         cfg->param_area   = MAX(((signed) cfg->param_area), lParamArea);
2355         cfg->flags       |= MONO_CFG_HAS_CALLS;
2356
2357         if (cinfo->struct_ret) {
2358                 MONO_INST_NEW (cfg, ins, OP_MOVE);
2359                 ins->sreg1 = call->vret_var->dreg;
2360                 ins->dreg = mono_alloc_preg (cfg);
2361                 MONO_ADD_INS (cfg->cbb, ins);
2362                 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2363         }
2364
2365         header = cfg->header;
2366         if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2367                 frmReg = s390_r11;
2368         else
2369                 frmReg = STK_BASE;
2370
2371         for (i = 0; i < n; ++i) {
2372                 MonoType *t;
2373
2374                 ainfo = cinfo->args + i;
2375                 if (i >= sig->hasthis)
2376                         t = sig->params [i - sig->hasthis];
2377                 else
2378                         t = &mono_defaults.int_class->byval_arg;
2379                 t = mini_get_underlying_type (t);
2380
2381                 in = call->args [i];
2382
2383                 if ((sig->call_convention == MONO_CALL_VARARG) &&
2384                     (!sig->pinvoke) &&
2385                     (i == sig->sentinelpos)) {
2386                         emit_sig_cookie (cfg, call, cinfo);
2387                 }
2388
2389                 switch (ainfo->regtype) {
2390                 case RegTypeGeneral:
2391                         add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2392                         break;
2393                 case RegTypeFP:
2394                         if (MONO_TYPE_ISSTRUCT (t)) {
2395                                 /* Valuetype passed in one fp register */
2396                                 ainfo->regtype = RegTypeStructByValInFP;
2397                                 /* Fall through */
2398                         } else {
2399                                 if (ainfo->size == 4)
2400                                         ainfo->regtype = RegTypeFPR4;
2401                                 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2402                                 break;
2403                         }
2404                 case RegTypeStructByVal:
2405                 case RegTypeStructByAddr:
2406                 case RegTypeStructByAddrOnStack: {
2407                         guint32 align;
2408                         guint32 size;
2409
2410                         if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2411                                 size = sizeof (MonoTypedRef);
2412                                 align = sizeof (gpointer);
2413                         }
2414                         else
2415                                 if (sig->pinvoke)
2416                                         size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2417                                 else {
2418                                         /* 
2419                                          * Other backends use mono_type_stack_size (), but that
2420                                          * aligns the size to 8, which is larger than the size of
2421                                          * the source, leading to reads of invalid memory if the
2422                                          * source is at the end of address space.
2423                                          */
2424                                         size = mono_class_value_size (in->klass, &align);
2425                                 }
2426
2427                         g_assert (in->klass);
2428
2429                         ainfo->offparm += cinfo->sz.offStruct;
2430
2431                         MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2432                         ins->sreg1 = in->dreg;
2433                         ins->klass = in->klass;
2434                         ins->backend.size = ainfo->size;
2435                         ins->inst_p0 = call;
2436                         ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2437                         memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2438
2439                         MONO_ADD_INS (cfg->cbb, ins);
2440
2441                         if (ainfo->regtype == RegTypeStructByAddr) {
2442                                 /* 
2443                                  * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2444                                  * use the normal OUTARG opcodes to pass the address of the location to
2445                                  * the callee.
2446                                  */
2447                                 int treg = mono_alloc_preg (cfg);
2448                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg, 
2449                                                          frmReg, ainfo->offparm);
2450                                 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2451                         } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2452                                 /* The address of the valuetype is passed on the stack */
2453                                 int treg = mono_alloc_preg (cfg);
2454                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg, 
2455                                                          frmReg, ainfo->offparm);
2456                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2457                                                              ainfo->reg, ainfo->offset, treg);
2458
2459                                 if (cfg->compute_gc_maps) {
2460                                         MonoInst *def;
2461
2462                                         EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2463                                 }
2464                         }
2465                         break;
2466                 }
2467                 case RegTypeBase:
2468                         if (!t->byref && t->type == MONO_TYPE_R4) {
2469                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG, 
2470                                                              STK_BASE, ainfo->offset + 4,
2471                                                              in->dreg);
2472                         } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2473                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG, 
2474                                                              STK_BASE, ainfo->offset,
2475                                                              in->dreg);
2476                         } else {
2477                                 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2478                                 ins->inst_destbasereg = STK_BASE;
2479                                 ins->inst_offset = ainfo->offset;
2480                                 ins->sreg1 = in->dreg;
2481
2482 #if 0
2483                                 /* This is needed by MonoTypedRef->value to point to the correct data */
2484                                 if ((sig->call_convention == MONO_CALL_VARARG) &&
2485                                         (i >= sig->sentinelpos)) {
2486                                         switch (ainfo->size) {
2487                                         case 1:
2488                                                 ins->opcode = OP_STOREI1_MEMBASE_REG;
2489                                                 break;
2490                                         case 2:
2491                                                 ins->opcode = OP_STOREI2_MEMBASE_REG;
2492                                                 break;
2493                                         case 4:
2494                                                 ins->opcode = OP_STOREI4_MEMBASE_REG;
2495                                                 break;
2496                                         default:
2497                                                 break;
2498                                         }
2499                                 }
2500 #endif
2501
2502                                 MONO_ADD_INS (cfg->cbb, ins);
2503                         }
2504                         break;
2505                 default:
2506                         g_assert_not_reached ();
2507                         break;
2508                 }
2509         }
2510
2511         /*
2512          * Handle the case where there are no implicit arguments 
2513          */
2514         if ((sig->call_convention == MONO_CALL_VARARG) &&
2515             (!sig->pinvoke) &&
2516             (i == sig->sentinelpos)) {
2517                 emit_sig_cookie (cfg, call, cinfo);
2518         }
2519 }
2520
2521 /*========================= End of Function ========================*/
2522
2523 /*------------------------------------------------------------------*/
2524 /*                                                                  */
2525 /* Name         - mono_arch_emit_outarg_vt                          */
2526 /*                                                                  */
2527 /*------------------------------------------------------------------*/
2528
2529 void
2530 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2531 {
2532         MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2533         ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2534         int size = ins->backend.size;
2535
2536         if (ainfo->regtype == RegTypeStructByVal) {
2537                 /*
2538                                 arg->ins.sreg1  = ainfo->reg;
2539                                 arg->ins.opcode = OP_OUTARG_VT;
2540                                 arg->size       = ainfo->size;
2541                                 arg->offset     = ainfo->offset;
2542                                 arg->offPrm     = ainfo->offparm + cinfo->sz.offStruct;
2543                 */
2544                 if (ainfo->reg != STK_BASE) {
2545                         MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2546                 } else {
2547                         MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2548                                                           src->dreg, 0);
2549                 }       
2550         } else if (ainfo->regtype == RegTypeStructByValInFP) {
2551                 int dreg = mono_alloc_freg (cfg);
2552
2553                 if (ainfo->size == 4) {
2554                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2555                         MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2556                 } else {
2557                         g_assert (ainfo->size == 8);
2558
2559                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2560                 }
2561
2562                 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2563         } else {
2564                 MonoError error;
2565                 MonoMethodHeader *header;
2566                 int srcReg;
2567
2568                 header = mono_method_get_header_checked (cfg->method, &error);
2569                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2570                 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2571                         srcReg = s390_r11;
2572                 else
2573                         srcReg = STK_BASE;
2574
2575                 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2576                                                          src->dreg, 0, size);
2577
2578                 if (cfg->compute_gc_maps) {
2579                         MonoInst *def;
2580
2581                         EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2582                 }
2583         }
2584 }
2585
2586 /*========================= End of Function ========================*/
2587
2588 /*------------------------------------------------------------------*/
2589 /*                                                                  */
2590 /* Name         - mono_arch_emit_setret                             */
2591 /*                                                                  */
2592 /*------------------------------------------------------------------*/
2593
2594 void
2595 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2596 {
2597         MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2598
2599         if (!ret->byref) {
2600                 if (ret->type == MONO_TYPE_R4) {
2601                         MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2602                         return;
2603                 } else if (ret->type == MONO_TYPE_R8) {
2604                         MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2605                         return;
2606                 }
2607         }
2608                         
2609         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2610 }
2611
2612 /*========================= End of Function ========================*/
2613
2614 /*------------------------------------------------------------------*/
2615 /*                                                                  */
2616 /* Name         - mono_arch_instrument_mem_needs                    */
2617 /*                                                                  */
2618 /* Function     - Allow tracing to work with this interface (with   */
2619 /*                an optional argument).                            */
2620 /*                                                                  */
2621 /*------------------------------------------------------------------*/
2622
2623 void
2624 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2625 {
2626         /* no stack room needed now (may be needed for FASTCALL-trace support) */
2627         *stack = 0;
2628         /* split prolog-epilog requirements? */
2629         *code = 50; /* max bytes needed: check this number */
2630 }
2631
2632 /*========================= End of Function ========================*/
2633
2634 /*------------------------------------------------------------------*/
2635 /*                                                                  */
2636 /* Name         - mono_arch_instrument_prolog                       */
2637 /*                                                                  */
2638 /* Function     - Create an "instrumented" prolog.                  */
2639 /*                                                                  */
2640 /*------------------------------------------------------------------*/
2641
2642 void*
2643 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, 
2644                              gboolean enable_arguments)
2645 {
2646         guchar  *code = p;
2647         int     parmOffset, 
2648                 fpOffset,
2649                 baseReg;
2650
2651         parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2652         if (cfg->method->save_lmf)
2653                 parmOffset -= sizeof(MonoLMF);
2654         fpOffset   = parmOffset + (5*sizeof(gpointer));
2655         baseReg = STK_BASE;
2656
2657         s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2658         s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2659         s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2660         s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2661         s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2662         S390_SET  (code, s390_r1, func);
2663         S390_SET  (code, s390_r2, cfg->method);
2664         s390_lay  (code, s390_r3, 0, STK_BASE, parmOffset);
2665         s390_lgr  (code, s390_r4, STK_BASE);
2666         s390_aghi (code, s390_r4, cfg->stack_usage);
2667         s390_basr (code, s390_r14, s390_r1);
2668         s390_ldy  (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2669         s390_ldy  (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2670         s390_ldy  (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2671         s390_ldy  (code, s390_f0, 0, STK_BASE, fpOffset);
2672         s390_lmg  (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2673
2674         return code;
2675 }
2676
2677 /*========================= End of Function ========================*/
2678
2679 /*------------------------------------------------------------------*/
2680 /*                                                                  */
2681 /* Name         - mono_arch_instrument_epilog                       */
2682 /*                                                                  */
2683 /* Function     - Create an epilog that will handle the returned    */
2684 /*                values used in instrumentation.                   */
2685 /*                                                                  */
2686 /*------------------------------------------------------------------*/
2687
2688 void*
2689 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2690 {
2691         guchar     *code = p;
2692         int        save_mode = SAVE_NONE,
2693                    saveOffset,
2694                    offset;
2695         MonoMethod *method = cfg->method;
2696         int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2697
2698         offset = code - cfg->native_code;
2699         /*-----------------------------------------*/
2700         /* We need about 128 bytes of instructions */
2701         /*-----------------------------------------*/
2702         if (offset > (cfg->code_size - 128)) {
2703                 cfg->code_size *= 2;
2704                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2705                 code = cfg->native_code + offset;
2706         }
2707
2708         saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2709         if (method->save_lmf)
2710                 saveOffset -= sizeof(MonoLMF);
2711
2712 handle_enum:
2713         switch (rtype) {
2714         case MONO_TYPE_VOID:
2715                 /* special case string .ctor icall */
2716                 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2717                         save_mode = SAVE_ONE;
2718                 else
2719                         save_mode = SAVE_NONE;
2720                 break;
2721         case MONO_TYPE_I8:
2722         case MONO_TYPE_U8:
2723                 save_mode = SAVE_ONE;
2724                 break;
2725         case MONO_TYPE_R4:
2726                 save_mode = SAVE_R4;
2727                 break;
2728         case MONO_TYPE_R8:
2729                 save_mode = SAVE_R8;
2730                 break;
2731         case MONO_TYPE_VALUETYPE:
2732                 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2733                         rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2734                         goto handle_enum;
2735                 }
2736                 save_mode = SAVE_STRUCT;
2737                 break;
2738         default:
2739                 save_mode = SAVE_ONE;
2740                 break;
2741         }
2742
2743         switch (save_mode) {
2744         case SAVE_ONE:
2745                 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2746                 if (enable_arguments) {
2747                         s390_lgr (code, s390_r3, s390_r2);
2748                 }
2749                 break;
2750         case SAVE_R4:
2751                 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2752                 if (enable_arguments) {
2753                         s390_ldebr (code, s390_f0, s390_f0);
2754                 }
2755                 break;
2756         case SAVE_R8:
2757                 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2758                 break;
2759         case SAVE_STRUCT:
2760                 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2761                 if (enable_arguments) {
2762                         s390_lg (code, s390_r3, 0, cfg->frame_reg, 
2763                                  S390_MINIMAL_STACK_SIZE+cfg->param_area);
2764                 }
2765                 break;
2766         case SAVE_NONE:
2767         default:
2768                 break;
2769         }
2770
2771         S390_SET  (code, s390_r1, func);
2772         S390_SET  (code, s390_r2, cfg->method);
2773         s390_basr (code, s390_r14, s390_r1);
2774
2775         switch (save_mode) {
2776         case SAVE_ONE:
2777                 s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2778                 break;
2779         case SAVE_R4:
2780         case SAVE_R8:
2781                 s390_ld  (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2782                 break;
2783         case SAVE_STRUCT:
2784                 s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2785                 break;
2786         case SAVE_NONE:
2787         default:
2788                 break;
2789         }
2790
2791         return code;
2792 }
2793
2794 /*========================= End of Function ========================*/
2795
2796 /*------------------------------------------------------------------*/
2797 /*                                                                  */
2798 /* Name         - mono_arch_peephole_pass_1                         */
2799 /*                                                                  */
2800 /* Function     - Form a peephole pass at the code looking for      */
2801 /*                simple optimizations.                             */
2802 /*                                                                  */
2803 /*------------------------------------------------------------------*/
2804
2805 void
2806 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2807 {
2808 }
2809
2810 /*========================= End of Function ========================*/
2811
2812 /*------------------------------------------------------------------*/
2813 /*                                                                  */
2814 /* Name         - mono_arch_peephole_pass_2                         */
2815 /*                                                                  */
2816 /* Function     - Form a peephole pass at the code looking for      */
2817 /*                simple optimizations.                             */
2818 /*                                                                  */
2819 /*------------------------------------------------------------------*/
2820
2821 void
2822 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2823 {
2824         MonoInst *ins, *n;
2825
2826         MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2827                 mono_peephole_ins (bb, ins);
2828         }
2829 }
2830
2831 /*========================= End of Function ========================*/
2832
2833 /*------------------------------------------------------------------*/
2834 /*                                                                  */
2835 /* Name         - mono_arch_lowering_pass.                          */
2836 /*                                                                  */
2837 /*------------------------------------------------------------------*/
2838
2839 void
2840 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2841 {
2842         MonoInst *ins, *next;
2843
2844         MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2845                 switch (ins->opcode) {
2846                 case OP_DIV_IMM:
2847                 case OP_REM_IMM:
2848                 case OP_IDIV_IMM:
2849                 case OP_IREM_IMM:
2850                 case OP_IDIV_UN_IMM:
2851                 case OP_IREM_UN_IMM:
2852                 case OP_LAND_IMM:
2853                 case OP_LOR_IMM:
2854                 case OP_LREM_IMM:
2855                 case OP_LXOR_IMM:
2856                 case OP_LOCALLOC_IMM:
2857                         mono_decompose_op_imm (cfg, bb, ins);
2858                         break;
2859                 case OP_LADD_IMM:
2860                         if (!s390_is_imm16 (ins->inst_imm))
2861                                 /* This is created by the memcpy code which ignores is_inst_imm */
2862                                 mono_decompose_op_imm (cfg, bb, ins);
2863                         break;
2864                 default:
2865                         break;
2866                 }
2867         }
2868
2869         bb->max_vreg = cfg->next_vreg;
2870 }
2871
2872 /*========================= End of Function ========================*/
2873
2874 /*------------------------------------------------------------------*/
2875 /*                                                                  */
2876 /* Name         - emit_float_to_int                                 */
2877 /*                                                                  */
2878 /* Function     - Create instructions which will convert a floating */
2879 /*                point value to integer.                           */
2880 /*                                                                  */
2881 /*------------------------------------------------------------------*/
2882
2883 static guchar*
2884 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2885 {
2886         /* sreg is a float, dreg is an integer reg. */
2887         if (is_signed) {
2888                 s390_cgdbr (code, dreg, 5, sreg);
2889                 switch (size) {
2890                 case 1:
2891                         s390_ltgr (code, dreg, dreg);
2892                         s390_jnl  (code, 4);
2893                         s390_oill (code, dreg, 0x80);
2894                         s390_lghi (code, s390_r0, 0xff);
2895                         s390_ngr  (code, dreg, s390_r0);
2896                         break;
2897                 case 2:
2898                         s390_ltgr (code, dreg, dreg);
2899                         s390_jnl  (code, 4);
2900                         s390_oill (code, dreg, 0x8000);
2901                         s390_llill(code, s390_r0, 0xffff);
2902                         s390_ngr  (code, dreg, s390_r0);
2903                         break;
2904                 }
2905         } else {
2906                 short *o[1];
2907                 S390_SET    (code, s390_r13, 0x41e0000000000000llu);
2908                 s390_ldgr   (code, s390_f14, s390_r13);
2909                 s390_ldr    (code, s390_f15, sreg);
2910                 s390_cdbr   (code, s390_f15, s390_f14);
2911                 s390_jl     (code, 0); CODEPTR (code, o[0]);
2912                 S390_SET    (code, s390_r13, 0x41f0000000000000llu);
2913                 s390_ldgr   (code, s390_f14, s390_r13);
2914                 s390_sdbr   (code, s390_f15, s390_f14);
2915                 s390_cfdbr  (code, dreg, 7, s390_f15);
2916                 s390_j      (code, 4);
2917                 PTRSLOT (code, o[0]);
2918                 s390_cfdbr  (code, dreg, 5, sreg);
2919                 switch (size) {
2920                 case 1: 
2921                         s390_lghi (code, s390_r0, 0xff);
2922                         s390_ngr  (code, dreg, s390_r0);
2923                         break;
2924                 case 2:
2925                         s390_llill(code, s390_r0, 0xffff);
2926                         s390_ngr  (code, dreg, s390_r0);
2927                         break;
2928                 }
2929         }
2930         return code;
2931 }
2932
2933 /*========================= End of Function ========================*/
2934
2935 /*------------------------------------------------------------------*/
2936 /*                                                                  */
2937 /* Name         - gboolean_is_unsigned.                             */
2938 /*                                                                  */
2939 /* Function     - Return TRUE if next opcode is checking for un-    */
2940 /*                signed value.                                     */
2941 /*                                                                  */
2942 /*------------------------------------------------------------------*/
2943
2944 static 
2945 gboolean is_unsigned (MonoInst *next)
2946 {
2947         if ((next) && 
2948                 (((next->opcode >= OP_IBNE_UN) &&
2949                   (next->opcode <= OP_IBLT_UN)) || 
2950                  ((next->opcode >= OP_LBNE_UN) &&
2951                   (next->opcode <= OP_LBLT_UN)) ||
2952                  ((next->opcode >= OP_COND_EXC_NE_UN) &&
2953                   (next->opcode <= OP_COND_EXC_LT_UN)) ||
2954                  ((next->opcode >= OP_COND_EXC_INE_UN) &&
2955                   (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2956                  ((next->opcode == OP_CLT_UN) ||
2957                   (next->opcode == OP_CGT_UN)) ||
2958                  ((next->opcode == OP_ICLT_UN) ||
2959                   (next->opcode == OP_ICGT_UN) ||
2960                   (next->opcode == OP_LCLT_UN) ||
2961                   (next->opcode == OP_LCGT_UN))))
2962                 return TRUE;
2963         else
2964                 return FALSE;
2965 }
2966
2967 /*========================= End of Function ========================*/
2968
2969 /*------------------------------------------------------------------*/
2970 /*                                                                  */
2971 /* Name         - mono_arch_output_basic_block                      */
2972 /*                                                                  */
2973 /* Function     - Perform the "real" work of emitting instructions  */
2974 /*                that will do the work of in the basic block.      */
2975 /*                                                                  */
2976 /*------------------------------------------------------------------*/
2977
2978 void
2979 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2980 {
2981         MonoInst *ins;
2982         MonoCallInst *call;
2983         guint offset;
2984         guint8 *code = cfg->native_code + cfg->code_len;
2985         guint last_offset = 0;
2986         int max_len, src2;
2987
2988         /* we don't align basic blocks of loops on s390 */
2989
2990         if (cfg->verbose_level > 2)
2991                 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2992
2993         if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2994                 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2995                 g_assert (!mono_compile_aot);
2996                 cov->data [bb->dfn].cil_code = bb->cil_code;
2997                 /* This is not thread save, but good enough */
2998                 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2999                 s390_alsi (code, 0, s390_r1, 1);
3000         }
3001
3002         MONO_BB_FOR_EACH_INS (bb, ins) {
3003                 offset = code - cfg->native_code;
3004
3005                 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3006
3007                 if (offset > (cfg->code_size - max_len - 16)) {
3008                         cfg->code_size *= 2;
3009                         cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3010                         code = cfg->native_code + offset;
3011                 }
3012
3013                 mono_debug_record_line_number (cfg, ins, offset);
3014
3015                 switch (ins->opcode) {
3016                 case OP_STOREI1_MEMBASE_IMM: {
3017                         s390_lghi (code, s390_r0, ins->inst_imm);
3018                         S390_LONG (code, stcy, stc, s390_r0, 0, 
3019                                    ins->inst_destbasereg, ins->inst_offset);
3020                 }
3021                         break;
3022                 case OP_STOREI2_MEMBASE_IMM: {
3023                         s390_lghi (code, s390_r0, ins->inst_imm);
3024                         S390_LONG (code, sthy, sth, s390_r0, 0, 
3025                                    ins->inst_destbasereg, ins->inst_offset);
3026                 }
3027                         break;
3028                 case OP_STOREI4_MEMBASE_IMM: {
3029                         s390_lgfi (code, s390_r0, ins->inst_imm);
3030                         S390_LONG (code, sty, st, s390_r0, 0, 
3031                                    ins->inst_destbasereg, ins->inst_offset);
3032                 }
3033                         break;
3034                 case OP_STORE_MEMBASE_IMM:
3035                 case OP_STOREI8_MEMBASE_IMM: {
3036                         S390_SET (code, s390_r0, ins->inst_imm);
3037                         S390_LONG (code, stg, stg, s390_r0, 0, 
3038                                    ins->inst_destbasereg, ins->inst_offset);
3039                 }
3040                         break;
3041                 case OP_STOREI1_MEMBASE_REG: {
3042                         S390_LONG (code, stcy, stc, ins->sreg1, 0, 
3043                                    ins->inst_destbasereg, ins->inst_offset);
3044                 }
3045                         break;
3046                 case OP_STOREI2_MEMBASE_REG: {
3047                         S390_LONG (code, sthy, sth, ins->sreg1, 0, 
3048                                    ins->inst_destbasereg, ins->inst_offset);
3049                 }
3050                         break;
3051                 case OP_STOREI4_MEMBASE_REG: {
3052                         S390_LONG (code, sty, st, ins->sreg1, 0, 
3053                                    ins->inst_destbasereg, ins->inst_offset);
3054                 }
3055                         break;
3056                 case OP_STORE_MEMBASE_REG:
3057                 case OP_STOREI8_MEMBASE_REG: {
3058                         S390_LONG (code, stg, stg, ins->sreg1, 0, 
3059                                    ins->inst_destbasereg, ins->inst_offset);
3060                 }
3061                         break;
3062                 case OP_LOADU4_MEM:
3063                         g_assert_not_reached ();
3064                         break;
3065                 case OP_LOAD_MEMBASE:
3066                 case OP_LOADI8_MEMBASE: {
3067                         S390_LONG (code, lg, lg, ins->dreg, 0, 
3068                                    ins->inst_basereg, ins->inst_offset);
3069                 }
3070                         break;
3071                 case OP_LOADI4_MEMBASE: {
3072                         S390_LONG (code, lgf, lgf, ins->dreg, 0, 
3073                                    ins->inst_basereg, ins->inst_offset);
3074                 }
3075                         break;
3076                 case OP_LOADU4_MEMBASE: {
3077                         S390_LONG (code, llgf, llgf, ins->dreg, 0, 
3078                                    ins->inst_basereg, ins->inst_offset);
3079                 }
3080                         break;
3081                 case OP_LOADU1_MEMBASE: {
3082                         S390_LONG (code, llgc, llgc, ins->dreg, 0, 
3083                                    ins->inst_basereg, ins->inst_offset);
3084                 }
3085                         break;
3086                 case OP_LOADI1_MEMBASE: {
3087                         S390_LONG (code, lgb, lgb, ins->dreg, 0, 
3088                                    ins->inst_basereg, ins->inst_offset);
3089                 }
3090                         break;
3091                 case OP_LOADU2_MEMBASE: {
3092                         S390_LONG (code, llgh, llgh, ins->dreg, 0, 
3093                                    ins->inst_basereg, ins->inst_offset);
3094                 }
3095                         break;
3096                 case OP_LOADI2_MEMBASE: {
3097                         S390_LONG (code, lgh, lgh, ins->dreg, 0, 
3098                                    ins->inst_basereg, ins->inst_offset);
3099                 }
3100                         break;
3101                 case OP_LCONV_TO_I1: {
3102                         s390_lgbr (code, ins->dreg, ins->sreg1);
3103                 }
3104                         break;
3105                 case OP_LCONV_TO_I2: {
3106                         s390_lghr (code, ins->dreg, ins->sreg1);
3107                 }
3108                         break;
3109                 case OP_LCONV_TO_U1: {
3110                         s390_llgcr (code, ins->dreg, ins->sreg1);
3111                 }
3112                         break;
3113                 case OP_LCONV_TO_U2: {
3114                         s390_llghr (code, ins->dreg, ins->sreg1);
3115                 }
3116                         break;
3117                 case OP_ICONV_TO_I1: {
3118                         s390_lgbr  (code, ins->dreg, ins->sreg1);
3119                 }
3120                         break;
3121                 case OP_ICONV_TO_I2: {
3122                         s390_lghr  (code, ins->dreg, ins->sreg1);
3123                 }
3124                         break;
3125                 case OP_ICONV_TO_U1: {
3126                         s390_llgcr (code, ins->dreg, ins->sreg1);
3127                 }
3128                         break;
3129                 case OP_ICONV_TO_U2: {
3130                         s390_llghr (code, ins->dreg, ins->sreg1);
3131                 }
3132                         break;
3133                 case OP_COMPARE: 
3134                 case OP_LCOMPARE: {
3135                         if (is_unsigned (ins->next))
3136                                 s390_clgr (code, ins->sreg1, ins->sreg2);
3137                         else
3138                                 s390_cgr  (code, ins->sreg1, ins->sreg2);
3139                 }
3140                         break;
3141                 case OP_ICOMPARE: {
3142                         if (is_unsigned (ins->next))
3143                                 s390_clr  (code, ins->sreg1, ins->sreg2);
3144                         else
3145                                 s390_cr   (code, ins->sreg1, ins->sreg2);
3146                 }
3147                         break;
3148                 case OP_COMPARE_IMM:
3149                 case OP_LCOMPARE_IMM: {
3150                         S390_SET (code, s390_r0, ins->inst_imm);
3151                         if (is_unsigned (ins->next))
3152                                 s390_clgr (code, ins->sreg1, s390_r0);
3153                         else
3154                                 s390_cgr  (code, ins->sreg1, s390_r0);
3155                 }
3156                         break;
3157                 case OP_ICOMPARE_IMM: {
3158                         S390_SET (code, s390_r0, ins->inst_imm);
3159                         if (is_unsigned (ins->next))
3160                                 s390_clr  (code, ins->sreg1, s390_r0);
3161                         else
3162                                 s390_cr   (code, ins->sreg1, s390_r0);
3163                 }
3164                         break;
3165                 case OP_BREAK: {
3166                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS, 
3167                                              mono_break);
3168                         S390_CALL_TEMPLATE (code, s390_r14);
3169                 }
3170                         break;
3171                 case OP_ADDCC: {
3172                         CHECK_SRCDST_COM;
3173                         s390_agr  (code, ins->dreg, src2);
3174                 }
3175                         break;
3176                 case OP_LADD: {
3177                         CHECK_SRCDST_COM;
3178                         s390_agr   (code, ins->dreg, src2);
3179                 }
3180                         break;
3181                 case OP_ADC: {
3182                         CHECK_SRCDST_COM;
3183                         s390_alcgr (code, ins->dreg, src2);
3184                 }
3185                         break;
3186                 case OP_ADD_IMM: {
3187                         if (ins->dreg != ins->sreg1) {
3188                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3189                         }
3190                         if (s390_is_imm16 (ins->inst_imm)) {
3191                                 s390_aghi (code, ins->dreg, ins->inst_imm);
3192                         } else if (s390_is_imm32 (ins->inst_imm)) {
3193                                 s390_agfi (code, ins->dreg, ins->inst_imm);
3194                         } else {
3195                                 S390_SET  (code, s390_r0, ins->inst_imm);
3196                                 s390_agr  (code, ins->dreg, s390_r0);
3197                         }
3198                 }
3199                         break;
3200                 case OP_LADD_IMM: {
3201                         if (ins->dreg != ins->sreg1) {
3202                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3203                         }
3204                         g_assert (s390_is_imm16 (ins->inst_imm));
3205                         s390_aghi (code, ins->dreg, ins->inst_imm);
3206                 }
3207                         break;
3208                 case OP_ADC_IMM: {
3209                         if (ins->dreg != ins->sreg1) {
3210                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3211                         }
3212                         if (s390_is_imm16 (ins->inst_imm)) {
3213                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3214                                 s390_alcgr (code, ins->dreg, s390_r0);
3215                         } else {
3216                                 S390_SET   (code, s390_r0, ins->inst_imm);
3217                                 s390_alcgr (code, ins->dreg, s390_r0);
3218                         }
3219                 }
3220                         break;
3221                 case OP_IADD_OVF:
3222                 case OP_S390_IADD_OVF: {
3223                         CHECK_SRCDST_COM;
3224                         s390_ar    (code, ins->dreg, src2);
3225                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3226                         s390_lgfr  (code, ins->dreg, ins->dreg);
3227                 }
3228                         break;
3229                 case OP_IADD_OVF_UN:
3230                 case OP_S390_IADD_OVF_UN: {
3231                         CHECK_SRCDST_COM;
3232                         s390_algr  (code, ins->dreg, src2);
3233                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3234                         s390_llgfr (code, ins->dreg, ins->dreg);
3235                 }
3236                         break;
3237                 case OP_ADD_OVF_CARRY: {
3238                         CHECK_SRCDST_COM;
3239                         s390_lghi  (code, s390_r0, 0);
3240                         s390_lgr   (code, s390_r1, s390_r0);
3241                         s390_alcgr (code, s390_r0, s390_r1);
3242                         s390_agr   (code, ins->dreg, src2);
3243                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3244                         s390_agr   (code, ins->dreg, s390_r0);
3245                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3246                 }
3247                         break;
3248                 case OP_ADD_OVF_UN_CARRY: {
3249                         CHECK_SRCDST_COM;
3250                         s390_alcgr (code, ins->dreg, src2);
3251                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3252                 }
3253                         break;
3254                 case OP_SUBCC: {
3255                         CHECK_SRCDST_NCOM;
3256                         s390_sgr (code, ins->dreg, src2);
3257                 }
3258                         break;
3259                 case OP_LSUB: {
3260                         CHECK_SRCDST_NCOM;
3261                         s390_sgr  (code, ins->dreg, src2);
3262                 }
3263                         break;
3264                 case OP_SBB: {
3265                         CHECK_SRCDST_NCOM;
3266                         s390_slbgr(code, ins->dreg, src2);
3267                 }
3268                         break;
3269                 case OP_SUB_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_LSUB_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_aghi  (code, ins->dreg, -ins->inst_imm);
3289                         } else if (s390_is_imm32 (-ins->inst_imm)) {
3290                                 s390_slgfi (code, ins->dreg, ins->inst_imm);
3291                         } else {
3292                                 S390_SET  (code, s390_r0, ins->inst_imm);
3293                                 s390_slgr (code, ins->dreg, s390_r0);
3294                         }
3295                 }
3296                         break;
3297                 case OP_SBB_IMM: {
3298                         if (ins->dreg != ins->sreg1) {
3299                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3300                         }
3301                         if (s390_is_imm16 (-ins->inst_imm)) {
3302                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3303                                 s390_slbgr (code, ins->dreg, s390_r0);
3304                         } else {
3305                                 S390_SET  (code, s390_r0, ins->inst_imm);
3306                                 s390_slbgr(code, ins->dreg, s390_r0);
3307                         }
3308                 }
3309                         break;
3310                 case OP_SUB_OVF_CARRY: {
3311                         CHECK_SRCDST_NCOM;
3312                         s390_lghi  (code, s390_r0, 0);
3313                         s390_lgr   (code, s390_r1, s390_r0);
3314                         s390_slbgr (code, s390_r0, s390_r1);
3315                         s390_sgr   (code, ins->dreg, src2);
3316                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3317                         s390_agr   (code, ins->dreg, s390_r0);
3318                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3319                 }
3320                         break;
3321                 case OP_SUB_OVF_UN_CARRY: {
3322                         CHECK_SRCDST_NCOM;
3323                         s390_slbgr (code, ins->dreg, src2);
3324                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3325                 }
3326                         break;
3327                 case OP_LAND: {
3328                         if (ins->sreg1 == ins->dreg) {
3329                                 s390_ngr  (code, ins->dreg, ins->sreg2);
3330                         } 
3331                         else { 
3332                                 if (ins->sreg2 == ins->dreg) { 
3333                                         s390_ngr (code, ins->dreg, ins->sreg1);
3334                                 }
3335                                 else { 
3336                                         s390_lgr (code, ins->dreg, ins->sreg1);
3337                                         s390_ngr (code, ins->dreg, ins->sreg2);
3338                                 }
3339                         }
3340                 }
3341                         break;
3342                 case OP_AND_IMM: {
3343                         if (ins->dreg != ins->sreg1) {
3344                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3345                         }
3346                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3347                         s390_ngr (code, ins->dreg, s390_r0);
3348                 }
3349                         break;
3350                 case OP_LDIV: {
3351                         s390_lgr  (code, s390_r1, ins->sreg1);
3352                         s390_dsgr (code, s390_r0, ins->sreg2);
3353                         s390_lgr  (code, ins->dreg, s390_r1);
3354                 }
3355                         break;
3356                 case OP_LDIV_UN: {
3357                         s390_lgr   (code, s390_r1, ins->sreg1);
3358                         s390_lghi  (code, s390_r0, 0);
3359                         s390_dlgr  (code, s390_r0, ins->sreg2);
3360                         s390_lgr   (code, ins->dreg, s390_r1);
3361                 }
3362                         break;
3363                 case OP_LREM: {
3364                         s390_lgr  (code, s390_r1, ins->sreg1);
3365                         s390_dsgr (code, s390_r0, ins->sreg2);
3366                         s390_lgr  (code, ins->dreg, s390_r0);
3367                         break;
3368                 }
3369                 case OP_LREM_IMM: {
3370                         if (s390_is_imm16 (ins->inst_imm)) {
3371                                 s390_lghi (code, s390_r13, ins->inst_imm);
3372                         } else {
3373                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3374                         }
3375                         s390_lgr  (code, s390_r0, ins->sreg1);
3376                         s390_dsgr (code, s390_r0, s390_r13);
3377                         s390_lgfr (code, ins->dreg, s390_r0);
3378                 }
3379                         break;
3380                 case OP_LREM_UN: {
3381                         s390_lgr   (code, s390_r1, ins->sreg1);
3382                         s390_lghi  (code, s390_r0, 0);
3383                         s390_dlgr  (code, s390_r0, ins->sreg2);
3384                         s390_lgr   (code, ins->dreg, s390_r0);
3385                 }
3386                         break;
3387                 case OP_LOR: {
3388                         if (ins->sreg1 == ins->dreg) {
3389                                 s390_ogr  (code, ins->dreg, ins->sreg2);
3390                         } 
3391                         else { 
3392                                 if (ins->sreg2 == ins->dreg) { 
3393                                         s390_ogr (code, ins->dreg, ins->sreg1);
3394                                 }
3395                                 else { 
3396                                         s390_lgr (code, ins->dreg, ins->sreg1);
3397                                         s390_ogr (code, ins->dreg, ins->sreg2);
3398                                 }
3399                         }
3400                 }
3401                         break;
3402                 case OP_OR_IMM: {
3403                         if (ins->dreg != ins->sreg1) {
3404                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3405                         }
3406                         S390_SET_MASK(code, s390_r0, ins->inst_imm);
3407                         s390_ogr (code, ins->dreg, s390_r0);
3408                 }
3409                         break;
3410                 case OP_LXOR: {
3411                         if (ins->sreg1 == ins->dreg) {
3412                                 s390_xgr  (code, ins->dreg, ins->sreg2);
3413                         } 
3414                         else { 
3415                                 if (ins->sreg2 == ins->dreg) { 
3416                                         s390_xgr (code, ins->dreg, ins->sreg1);
3417                                 }
3418                                 else { 
3419                                         s390_lgr (code, ins->dreg, ins->sreg1);
3420                                         s390_xgr (code, ins->dreg, ins->sreg2);
3421                                 }
3422                         }
3423                 }
3424                         break;
3425                 case OP_XOR_IMM: {
3426                         if (ins->dreg != ins->sreg1) {
3427                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3428                         }
3429                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3430                         s390_xgr (code, ins->dreg, s390_r0);
3431                 }
3432                         break;
3433                 case OP_LSHL: {
3434                         CHECK_SRCDST_NCOM;
3435                         s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3436                 }
3437                         break;
3438                 case OP_SHL_IMM: 
3439                 case OP_LSHL_IMM: {
3440                         if (ins->sreg1 != ins->dreg) {
3441                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3442                         }
3443                         s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3444                 }
3445                         break;
3446                 case OP_LSHR: {
3447                         CHECK_SRCDST_NCOM;
3448                         s390_srag  (code, ins->dreg, ins->dreg, src2, 0);
3449                 }
3450                         break;
3451                 case OP_SHR_IMM:
3452                 case OP_LSHR_IMM: {
3453                         if (ins->sreg1 != ins->dreg) {
3454                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3455                         }
3456                         s390_srag  (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3457                 }
3458                         break;
3459                 case OP_SHR_UN_IMM: 
3460                 case OP_LSHR_UN_IMM: {
3461                         if (ins->sreg1 != ins->dreg) {
3462                                 s390_lgr   (code, ins->dreg, ins->sreg1);
3463                         }
3464                         s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3465                 }
3466                         break;
3467                 case OP_LSHR_UN: {
3468                         CHECK_SRCDST_NCOM;
3469                         s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3470                 }
3471                         break;
3472                 case OP_LNOT: {
3473                         if (ins->sreg1 != ins->dreg) {
3474                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3475                         }
3476                         s390_lghi (code, s390_r0, -1);
3477                         s390_xgr  (code, ins->dreg, s390_r0);
3478                 }
3479                         break;
3480                 case OP_LNEG: {
3481                         s390_lcgr (code, ins->dreg, ins->sreg1);
3482                 }
3483                         break;
3484                 case OP_LMUL: {
3485                         CHECK_SRCDST_COM;
3486                         s390_msgr (code, ins->dreg, src2);
3487                 }
3488                         break;
3489                 case OP_MUL_IMM: 
3490                 case OP_LMUL_IMM: {
3491                         if (ins->dreg != ins->sreg1) {
3492                                 s390_lgr  (code, ins->dreg, ins->sreg1);
3493                         }
3494                         if (s390_is_imm16 (ins->inst_imm)) {
3495                                 s390_lghi (code, s390_r13, ins->inst_imm);
3496                         } else if (s390_is_imm32 (ins->inst_imm)) {
3497                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3498                         } else {
3499                                 S390_SET (code, s390_r13, ins->inst_imm);
3500                         }
3501                         s390_msgr (code, ins->dreg, s390_r13);
3502                 }
3503                         break;
3504                 case OP_LMUL_OVF: {
3505                         short int *o[2];
3506                         s390_ltgr (code, s390_r1, ins->sreg1);
3507                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3508                         s390_ltgr (code, s390_r0, ins->sreg2);
3509                         s390_jnz  (code, 6);
3510                         s390_lghi (code, s390_r1, 0);
3511                         s390_j    (code, 0); CODEPTR(code, o[1]);
3512                         s390_xgr  (code, s390_r0, s390_r1);
3513                         s390_msgr (code, s390_r1, ins->sreg2);
3514                         s390_xgr  (code, s390_r0, s390_r1);
3515                         s390_srlg (code, s390_r0, s390_r0, 0, 63);
3516                         s390_ltgr (code, s390_r0, s390_r0);
3517                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3518                         PTRSLOT   (code, o[0]); 
3519                         PTRSLOT   (code, o[1]);
3520                         s390_lgr  (code, ins->dreg, s390_r1);
3521                 }
3522                         break;
3523                 case OP_LMUL_OVF_UN: {
3524                         s390_lghi  (code, s390_r0, 0);
3525                         s390_lgr   (code, s390_r1, ins->sreg1);
3526                         s390_mlgr  (code, s390_r0, ins->sreg2);
3527                         s390_ltgr  (code, s390_r0, s390_r0);
3528                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3529                         s390_lgr   (code, ins->dreg, s390_r1);
3530                 }
3531                         break;
3532                 case OP_IADDCC: {
3533                         g_assert_not_reached ();
3534                         CHECK_SRCDST_COM_I;
3535                         s390_algr (code, ins->dreg, src2);
3536                 }
3537                         break;
3538                 case OP_IADD: {
3539                         CHECK_SRCDST_COM_I;
3540                         s390_agr  (code, ins->dreg, src2);
3541                 }
3542                         break;
3543                 case OP_IADC: {
3544                         g_assert_not_reached ();
3545                         CHECK_SRCDST_COM_I;
3546                         s390_alcgr (code, ins->dreg, src2);
3547                 }
3548                         break;
3549                 case OP_IADD_IMM: {
3550                         if (ins->dreg != ins->sreg1) {
3551                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3552                         }
3553                         if (s390_is_imm16 (ins->inst_imm)) {
3554                                 s390_aghi (code, ins->dreg, ins->inst_imm);
3555                         } else {
3556                                 s390_afi  (code, ins->dreg, ins->inst_imm);
3557                         }
3558                 }
3559                         break;
3560                 case OP_IADC_IMM: {
3561                         if (ins->dreg != ins->sreg1) {
3562                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3563                         } 
3564                         if (s390_is_imm16 (ins->inst_imm)) {
3565                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3566                                 s390_alcgr (code, ins->dreg, s390_r0);
3567                         } else {
3568                                 S390_SET   (code, s390_r0, ins->inst_imm);
3569                                 s390_alcgr (code, ins->dreg, s390_r0);
3570                         }
3571                 }
3572                         break;
3573                 case OP_LADD_OVF:
3574                 case OP_S390_LADD_OVF: {
3575                         CHECK_SRCDST_COM;
3576                         s390_agr    (code, ins->dreg, src2);
3577                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3578                 }
3579                         break;
3580                 case OP_LADD_OVF_UN:
3581                 case OP_S390_LADD_OVF_UN: {
3582                         CHECK_SRCDST_COM;
3583                         s390_algr  (code, ins->dreg, src2);
3584                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3585                 }
3586                         break;
3587                 case OP_ISUBCC: {
3588                         CHECK_SRCDST_NCOM_I;
3589                         s390_slgr (code, ins->dreg, src2);
3590                 }
3591                         break;
3592                 case OP_ISUB: {
3593                         CHECK_SRCDST_NCOM_I;
3594                         s390_sgr  (code, ins->dreg, src2);
3595                 }
3596                         break;
3597                 case OP_ISBB: {
3598                         CHECK_SRCDST_NCOM_I;
3599                         s390_slbgr (code, ins->dreg, src2);
3600                 }
3601                         break;
3602                 case OP_ISUB_IMM: {
3603                         if (ins->dreg != ins->sreg1) {
3604                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3605                         }
3606                         if (s390_is_imm16 (-ins->inst_imm)) {
3607                                 s390_aghi (code, ins->dreg, -ins->inst_imm);
3608                         } else {
3609                                 s390_agfi (code, ins->dreg, -ins->inst_imm);
3610                         }
3611                 }
3612                         break;
3613                 case OP_ISBB_IMM: {
3614                         S390_SET (code, s390_r0, ins->inst_imm);
3615                         s390_slgfr (code, ins->dreg, s390_r0);
3616                 }
3617                         break;
3618                 case OP_ISUB_OVF:
3619                 case OP_S390_ISUB_OVF: {
3620                         CHECK_SRCDST_NCOM;
3621                         s390_sr   (code, ins->dreg, src2);
3622                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3623                         s390_lgfr (code, ins->dreg, ins->dreg);
3624                 }
3625                         break;
3626                 case OP_ISUB_OVF_UN:
3627                 case OP_S390_ISUB_OVF_UN: {
3628                         CHECK_SRCDST_NCOM;
3629                         s390_slr  (code, ins->dreg, src2);
3630                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3631                         s390_llgfr(code, ins->dreg, ins->dreg);
3632                 }
3633                         break;
3634                 case OP_LSUB_OVF:
3635                 case OP_S390_LSUB_OVF: {
3636                         CHECK_SRCDST_NCOM;
3637                         s390_sgr   (code, ins->dreg, src2);
3638                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3639                 }
3640                         break;
3641                 case OP_LSUB_OVF_UN:
3642                 case OP_S390_LSUB_OVF_UN: {
3643                         CHECK_SRCDST_NCOM;
3644                         s390_slgr  (code, ins->dreg, src2);
3645                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3646                 }
3647                         break;
3648                 case OP_IAND: {
3649                         CHECK_SRCDST_NCOM_I;
3650                         s390_ngr (code, ins->dreg, src2);
3651                 }
3652                         break;
3653                 case OP_IAND_IMM: {
3654                         if (ins->dreg != ins->sreg1) {
3655                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3656                         }
3657                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3658                         s390_ngr  (code, ins->dreg, s390_r0);
3659                 }
3660                         break;
3661                 case OP_IDIV: {
3662                         s390_lgfr (code, s390_r0, ins->sreg1);
3663                         s390_srda (code, s390_r0, 0, 32);
3664                         s390_dr   (code, s390_r0, ins->sreg2);
3665                         s390_lgfr (code, ins->dreg, s390_r1);
3666                 }
3667                         break;
3668                 case OP_IDIV_UN: {
3669                         s390_lgfr (code, s390_r0, ins->sreg1);
3670                         s390_srdl (code, s390_r0, 0, 32);
3671                         s390_dlr  (code, s390_r0, ins->sreg2);
3672                         s390_lgfr (code, ins->dreg, s390_r1);
3673                 }
3674                         break;
3675                 case OP_IDIV_IMM: {
3676                         if (s390_is_imm16 (ins->inst_imm)) {
3677                                 s390_lghi (code, s390_r13, ins->inst_imm);
3678                         } else {
3679                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3680                         }
3681                         s390_lgfr (code, s390_r0, ins->sreg1);
3682                         s390_srda (code, s390_r0, 0, 32);
3683                         s390_dr   (code, s390_r0, ins->sreg2);
3684                         s390_lgfr (code, ins->dreg, s390_r1);
3685                 }
3686                         break;
3687                 case OP_IREM: {
3688                         s390_lgfr (code, s390_r0, ins->sreg1);
3689                         s390_srda (code, s390_r0, 0, 32);
3690                         s390_dr   (code, s390_r0, ins->sreg2);
3691                         s390_lgfr (code, ins->dreg, s390_r0);
3692                         break;
3693                 case OP_IREM_UN:
3694                         s390_lgfr (code, s390_r0, ins->sreg1);
3695                         s390_srdl (code, s390_r0, 0, 32);
3696                         s390_dlr  (code, s390_r0, ins->sreg2);
3697                         s390_lgfr (code, ins->dreg, s390_r0);
3698                 }
3699                         break;
3700                 case OP_IREM_IMM: {
3701                         if (s390_is_imm16 (ins->inst_imm)) {
3702                                 s390_lghi (code, s390_r13, ins->inst_imm);
3703                         } else {
3704                                 s390_lgfi (code, s390_r13, ins->inst_imm);
3705                         }
3706                         s390_lgfr (code, s390_r0, ins->sreg1);
3707                         s390_srda (code, s390_r0, 0, 32);
3708                         s390_dr   (code, s390_r0, ins->sreg2);
3709                         s390_lgfr (code, ins->dreg, s390_r0);
3710                 }
3711                         break;
3712                 case OP_IOR: {
3713                         CHECK_SRCDST_COM_I;
3714                         s390_ogr (code, ins->dreg, src2);
3715                 }
3716                         break;
3717                 case OP_IOR_IMM: {
3718                         if (ins->dreg != ins->sreg1) {
3719                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3720                         }
3721                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3722                         s390_ogr  (code, ins->dreg, s390_r0);
3723                 }
3724                         break;
3725                 case OP_IXOR: {
3726                         CHECK_SRCDST_COM_I;
3727                         s390_xgr (code, ins->dreg, src2);
3728                 }
3729                         break;
3730                 case OP_IXOR_IMM: {
3731                         if (ins->dreg != ins->sreg1) {
3732                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3733                         }
3734                         S390_SET_MASK (code, s390_r0, ins->inst_imm);
3735                         s390_xgr  (code, ins->dreg, s390_r0);
3736                 }
3737                         break;
3738                 case OP_ISHL: {
3739                         CHECK_SRCDST_NCOM;
3740                         s390_sll  (code, ins->dreg, src2, 0);
3741                 }
3742                         break;
3743                 case OP_ISHL_IMM: {
3744                         if (ins->sreg1 != ins->dreg) {
3745                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3746                         }
3747                         s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3748                 }
3749                         break;
3750                 case OP_ISHR: {
3751                         CHECK_SRCDST_NCOM;
3752                         s390_sra (code, ins->dreg, src2, 0);
3753                 }
3754                         break;
3755                 case OP_ISHR_IMM: {
3756                         if (ins->sreg1 != ins->dreg) {
3757                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3758                         }
3759                         s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3760                 }
3761                         break;
3762                 case OP_ISHR_UN_IMM: {
3763                         if (ins->sreg1 != ins->dreg) {
3764                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3765                         }
3766                         s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3767                 }
3768                         break;
3769                 case OP_ISHR_UN: {
3770                         CHECK_SRCDST_NCOM;
3771                         s390_srl  (code, ins->dreg, src2, 0);
3772                 }
3773                         break;
3774                 case OP_INOT: {
3775                         if (ins->sreg1 != ins->dreg) {
3776                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3777                         }
3778                         s390_lghi (code, s390_r0, -1);
3779                         s390_xgr  (code, ins->dreg, s390_r0);
3780                 }
3781                         break;
3782                 case OP_INEG: {
3783                         s390_lcgr (code, ins->dreg, ins->sreg1);
3784                 }
3785                         break;
3786                 case OP_IMUL: {
3787                         CHECK_SRCDST_COM_I;
3788                         s390_msr (code, ins->dreg, src2);
3789                 }
3790                         break;
3791                 case OP_IMUL_IMM: {
3792                         if (ins->dreg != ins->sreg1) {
3793                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3794                         }
3795                         if (s390_is_imm16 (ins->inst_imm)) {
3796                                 s390_lghi (code, s390_r0, ins->inst_imm);
3797                         } else {
3798                                 s390_lgfi (code, s390_r0, ins->inst_imm);
3799                         }
3800                         s390_msr  (code, ins->dreg, s390_r0);
3801                 }
3802                         break;
3803                 case OP_IMUL_OVF: {
3804                         short int *o[2];
3805                         s390_ltr  (code, s390_r1, ins->sreg1);
3806                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3807                         s390_ltr  (code, s390_r0, ins->sreg2);
3808                         s390_jnz  (code, 6);
3809                         s390_lhi  (code, s390_r1, 0);
3810                         s390_j    (code, 0); CODEPTR(code, o[1]);
3811                         s390_xr   (code, s390_r0, s390_r1);
3812                         s390_msr  (code, s390_r1, ins->sreg2);
3813                         s390_xr   (code, s390_r0, s390_r1);
3814                         s390_srl  (code, s390_r0, 0, 31);
3815                         s390_ltr  (code, s390_r0, s390_r0);
3816                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3817                         PTRSLOT   (code, o[0]); 
3818                         PTRSLOT   (code, o[1]);
3819                         s390_lgfr (code, ins->dreg, s390_r1);
3820                 }
3821                         break;
3822                 case OP_IMUL_OVF_UN: {
3823                         s390_lhi  (code, s390_r0, 0);
3824                         s390_lr   (code, s390_r1, ins->sreg1);
3825                         s390_mlr  (code, s390_r0, ins->sreg2);
3826                         s390_ltr  (code, s390_r0, s390_r0);
3827                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3828                         s390_lgfr (code, ins->dreg, s390_r1);
3829                 }
3830                         break;
3831                 case OP_ICONST: 
3832                 case OP_I8CONST: {
3833                         S390_SET (code, ins->dreg, ins->inst_c0);
3834                 }
3835                         break;
3836                 case OP_AOTCONST: {
3837                         mono_add_patch_info (cfg, code - cfg->native_code, 
3838                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3839                         S390_LOAD_TEMPLATE (code, ins->dreg);
3840                 }
3841                         break;
3842                 case OP_JUMP_TABLE: {
3843                         mono_add_patch_info (cfg, code - cfg->native_code, 
3844                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3845                         S390_LOAD_TEMPLATE (code, ins->dreg);
3846                 }
3847                         break;
3848                 case OP_MOVE:
3849                         if (ins->dreg != ins->sreg1) {
3850                                 s390_lgr (code, ins->dreg, ins->sreg1);
3851                         }
3852                         break;
3853                 case OP_LCONV_TO_I:
3854                 case OP_LCONV_TO_I8:
3855                 case OP_SEXT_I4:
3856                         s390_lgfr (code, ins->dreg, ins->sreg1);
3857                         break;
3858                 case OP_LCONV_TO_I4:
3859                         s390_lgfr (code, ins->dreg, ins->sreg1);
3860                         break;
3861                 case OP_LCONV_TO_U:
3862                 case OP_LCONV_TO_U8:
3863                 case OP_LCONV_TO_U4:
3864                 case OP_ZEXT_I4:
3865                         s390_llgfr (code, ins->dreg, ins->sreg1);
3866                         break;
3867                 case OP_LCONV_TO_OVF_U4:
3868                         S390_SET  (code, s390_r0, 4294967295);
3869                         s390_clgr (code, ins->sreg1, s390_r0);
3870                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3871                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3872                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3873                         s390_llgfr(code, ins->dreg, ins->sreg1);
3874                         break;
3875                 case OP_LCONV_TO_OVF_I4_UN:
3876                         S390_SET  (code, s390_r0, 2147483647);
3877                         s390_cgr  (code, ins->sreg1, s390_r0);
3878                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3879                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3880                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3881                         s390_lgfr (code, ins->dreg, ins->sreg1);
3882                         break;
3883                 case OP_FMOVE:
3884                         if (ins->dreg != ins->sreg1) {
3885                                 s390_ldr   (code, ins->dreg, ins->sreg1);
3886                         }
3887                         break;
3888                 case OP_MOVE_F_TO_I8: 
3889                         s390_lgdr (code, ins->dreg, ins->sreg1);
3890                         break;
3891                 case OP_MOVE_I8_TO_F: 
3892                         s390_ldgr (code, ins->dreg, ins->sreg1);
3893                         break;
3894                 case OP_MOVE_F_TO_I4:
3895                         s390_ledbr (code, s390_f0, ins->sreg1);
3896                         s390_lgdr (code, ins->dreg, s390_f0);
3897                         s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3898                         break;
3899                 case OP_MOVE_I4_TO_F: 
3900                         s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3901                         s390_ldgr (code, ins->dreg, s390_r0);
3902                         s390_ldebr (code, ins->dreg, ins->dreg);
3903                         break;
3904                 case OP_FCONV_TO_R4:
3905                         s390_ledbr (code, ins->dreg, ins->sreg1);
3906                         s390_ldebr (code, ins->dreg, ins->dreg);
3907                         break;
3908                 case OP_S390_SETF4RET:
3909                         s390_ledbr (code, ins->dreg, ins->sreg1);
3910                         break;
3911                 case OP_TLS_GET: {
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_lg  (code, ins->dreg, 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         mono_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         } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5605                 cfg->code_size += 256;
5606
5607         if (method->save_lmf)
5608                 cfg->code_size += 200;
5609
5610         cfg->native_code = code = g_malloc (cfg->code_size);
5611
5612         mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5613         emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5614         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5615         mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5616         mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5617
5618         if (cfg->arch.bkchain_reg != -1)
5619                 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5620
5621         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5622                 cfg->used_int_regs |= 1 << 11;
5623         }
5624
5625         alloc_size = cfg->stack_offset;
5626
5627         cfg->stack_usage = cfa_offset = alloc_size;
5628         mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5629         s390_lgr  (code, s390_r11, STK_BASE);
5630         if (s390_is_imm16 (alloc_size)) {
5631                 s390_aghi (code, STK_BASE, -alloc_size);
5632         } else if (s390_is_imm32 (alloc_size)) { 
5633                 s390_agfi (code, STK_BASE, -alloc_size);
5634         } else {
5635                 int stackSize = alloc_size;
5636                 while (stackSize > INT_MAX) {
5637                         s390_agfi (code, STK_BASE, -INT_MAX);
5638                         stackSize -= INT_MAX;
5639                 }
5640                 s390_agfi (code, STK_BASE, -stackSize);
5641         }
5642         s390_stg  (code, s390_r11, 0, STK_BASE, 0);
5643
5644         if (cfg->frame_reg != STK_BASE)
5645                 s390_lgr (code, s390_r11, STK_BASE);
5646
5647         mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5648
5649         /* store runtime generic context */
5650         if (cfg->rgctx_var) {
5651                 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5652
5653                 s390_stg  (code, MONO_ARCH_RGCTX_REG, 0, 
5654                            cfg->rgctx_var->inst_basereg, 
5655                            cfg->rgctx_var->inst_offset);
5656         }
5657
5658         /* compute max_offset in order to use short forward jumps
5659          * we always do it on s390 because the immediate displacement
5660          * for jumps is too small 
5661          */
5662         max_offset = 0;
5663         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5664                 MonoInst *ins;
5665                 bb->max_offset = max_offset;
5666
5667                 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5668                         max_offset += 6; 
5669
5670                 MONO_BB_FOR_EACH_INS (bb, ins)
5671                         max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5672         }
5673
5674         /* load arguments allocated to register from the stack */
5675         sig = mono_method_signature (method);
5676         pos = 0;
5677
5678         cinfo = get_call_info (cfg, cfg->mempool, sig);
5679
5680         if (cinfo->struct_ret) {
5681                 ArgInfo *ainfo     = &cinfo->ret;
5682                 inst               = cfg->vret_addr;
5683                 inst->backend.size = ainfo->vtsize;
5684                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5685         }
5686
5687         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5688                 ArgInfo *ainfo = cinfo->args + i;
5689                 inst = cfg->args [pos];
5690                 
5691                 if (inst->opcode == OP_VTARG_ADDR)
5692                         inst = inst->inst_left;
5693
5694                 if (inst->opcode == OP_REGVAR) {
5695                         if (ainfo->regtype == RegTypeGeneral)
5696                                 s390_lgr (code, inst->dreg, ainfo->reg);
5697                         else if (ainfo->regtype == RegTypeFP) {
5698                                 if (inst->dreg != ainfo->reg) {
5699                                         if (ainfo->size == 4) {
5700                                                 s390_ledbr (code, inst->dreg, ainfo->reg);
5701                                         } else {
5702                                                 s390_ldr   (code, inst->dreg, ainfo->reg);
5703                                         }
5704                                 }
5705                         }
5706                         else if (ainfo->regtype == RegTypeBase) {
5707                                 s390_lgr  (code, s390_r13, STK_BASE);
5708                                 s390_aghi (code, s390_r13, alloc_size);
5709                                 s390_lg   (code, inst->dreg, 0, s390_r13, ainfo->offset);
5710                         } else
5711                                 g_assert_not_reached ();
5712
5713                         if (cfg->verbose_level > 2)
5714                                 g_print ("Argument %d assigned to register %s\n", 
5715                                          pos, mono_arch_regname (inst->dreg));
5716                 } else {
5717                         if (ainfo->regtype == RegTypeGeneral) {
5718                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5719                                         g_assert_not_reached();
5720                                 switch (ainfo->size) {
5721                                 case 1:
5722                                         s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5723                                         break;
5724                                 case 2:
5725                                         s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5726                                         break;
5727                                 case 4: 
5728                                         s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5729                                         break;
5730                                 case 8:
5731                                         s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5732                                         break;
5733                                 }
5734                         } else if (ainfo->regtype == RegTypeBase) {
5735                         } else if (ainfo->regtype == RegTypeFP) {
5736                                 if (ainfo->size == 8)
5737                                         s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5738                                 else if (ainfo->size == 4)
5739                                         s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5740                                 else
5741                                         g_assert_not_reached ();
5742                         } else if (ainfo->regtype == RegTypeStructByVal) {
5743                                 int doffset = inst->inst_offset;
5744                                 int reg;
5745                                 if (ainfo->reg != STK_BASE)
5746                                         reg = ainfo->reg;
5747                                 else {
5748                                         reg = s390_r0;
5749                                         s390_lgr  (code, s390_r13, STK_BASE);
5750                                         s390_aghi (code, s390_r13, alloc_size);
5751                                 }
5752
5753                                 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE  
5754                                         ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5755                                         : ainfo->size);
5756
5757                                 switch (size) {
5758                                         case 1:
5759                                                 if (ainfo->reg == STK_BASE)
5760                                                         s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5761                                                 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5762                                                 break;
5763                                         case 2:
5764                                                 if (ainfo->reg == STK_BASE)
5765                                                         s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5766                                                 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5767                                                 break;
5768                                         case 4:
5769                                                 if (ainfo->reg == STK_BASE)
5770                                                         s390_l  (code, reg, 0, s390_r13, ainfo->offset+4);
5771                                                 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5772                                                 break;
5773                                         case 8:
5774                                                 if (ainfo->reg == STK_BASE)
5775                                                         s390_lg  (code, reg, 0, s390_r13, ainfo->offset);
5776                                                 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5777                                                 break;
5778                                 }
5779                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5780                                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5781                         } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5782                         } else
5783                                 g_assert_not_reached ();
5784                 }
5785                 pos++;
5786         }
5787
5788         if (method->save_lmf) {
5789                 /*---------------------------------------------------------------*/
5790                 /* build the MonoLMF structure on the stack - see mini-s390x.h   */
5791                 /*---------------------------------------------------------------*/
5792                 lmfOffset = alloc_size - sizeof(MonoLMF);       
5793                                                                                         
5794                 s390_lgr   (code, s390_r13, cfg->frame_reg);            
5795                 s390_aghi  (code, s390_r13, lmfOffset);                                 
5796                                                                                         
5797                 /*---------------------------------------------------------------*/
5798                 /* Preserve the parameter registers while we fix up the lmf      */
5799                 /*---------------------------------------------------------------*/
5800                 s390_stmg  (code, s390_r2, s390_r6, s390_r13,
5801                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5802
5803                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5804                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5805                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5806                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5807                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5808
5809                 /*---------------------------------------------------------------*/
5810                 /* On return from this call r2 have the address of the &lmf      */
5811                 /*---------------------------------------------------------------*/
5812                 if (lmf_addr_tls_offset == -1) {
5813                         mono_add_patch_info (cfg, code - cfg->native_code, 
5814                                              MONO_PATCH_INFO_INTERNAL_METHOD, 
5815                                              (gpointer)"mono_get_lmf_addr");
5816                         S390_CALL_TEMPLATE(code, s390_r1);
5817                 } else {
5818                         /*-------------------------------------------------------*/
5819                         /* Get LMF by getting value from thread level storage    */
5820                         /*-------------------------------------------------------*/
5821                         s390_ear (code, s390_r1, 0);
5822                         s390_sllg(code, s390_r1, s390_r1, 0, 32);
5823                         s390_ear (code, s390_r1, 1);
5824                         s390_lg  (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5825                 }
5826
5827                 /*---------------------------------------------------------------*/     
5828                 /* Set lmf.lmf_addr = jit_tls->lmf                               */     
5829                 /*---------------------------------------------------------------*/     
5830                 s390_stg   (code, s390_r2, 0, s390_r13,                                 
5831                             G_STRUCT_OFFSET(MonoLMF, lmf_addr));                        
5832                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5833                                                                                         
5834                 /*---------------------------------------------------------------*/     
5835                 /* Get current lmf                                               */     
5836                 /*---------------------------------------------------------------*/     
5837                 s390_lg    (code, s390_r0, 0, s390_r2, 0);                              
5838                                                                                         
5839                 /*---------------------------------------------------------------*/     
5840                 /* Set our lmf as the current lmf                                */     
5841                 /*---------------------------------------------------------------*/     
5842                 s390_stg   (code, s390_r13, 0, s390_r2, 0);                             
5843                                                                                         
5844                 /*---------------------------------------------------------------*/     
5845                 /* Have our lmf.previous_lmf point to the last lmf               */     
5846                 /*---------------------------------------------------------------*/     
5847                 s390_stg   (code, s390_r0, 0, s390_r13,                                 
5848                             G_STRUCT_OFFSET(MonoLMF, previous_lmf));                    
5849                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5850                                                                                         
5851                 /*---------------------------------------------------------------*/     
5852                 /* save method info                                              */     
5853                 /*---------------------------------------------------------------*/     
5854                 S390_SET   (code, s390_r1, method);
5855                 s390_stg   (code, s390_r1, 0, s390_r13,                                 
5856                             G_STRUCT_OFFSET(MonoLMF, method));                          
5857                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5858                                                                                 
5859                 /*---------------------------------------------------------------*/     
5860                 /* save the current IP                                           */     
5861                 /*---------------------------------------------------------------*/     
5862                 s390_stg   (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5863                 s390_basr  (code, s390_r1, 0);
5864                 s390_stg   (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); 
5865                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5866                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5867                                                                                         
5868                 /*---------------------------------------------------------------*/     
5869                 /* Save general and floating point registers                     */     
5870                 /*---------------------------------------------------------------*/     
5871                 s390_stmg  (code, s390_r2, s390_r12, s390_r13,                          
5872                             G_STRUCT_OFFSET(MonoLMF, gregs[2]));                        
5873                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5874                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5875                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5876                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5877                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5878                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5879                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5880                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5881                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5882                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5883                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5884
5885                 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5886                 for (i = 0; i < 16; i++) {                                              
5887                         s390_std  (code, i, 0, s390_r13,                                
5888                                    G_STRUCT_OFFSET(MonoLMF, fregs[i]));                 
5889                         mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5890                         fpOffset += sizeof(double);
5891                 }                                                                       
5892
5893                 /*---------------------------------------------------------------*/
5894                 /* Restore the parameter registers now that we've set up the lmf */
5895                 /*---------------------------------------------------------------*/
5896                 s390_lmg   (code, s390_r2, s390_r6, s390_r13,                           
5897                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));                        
5898         }
5899
5900         if (cfg->method->save_lmf)
5901                 argsClobbered = TRUE;
5902
5903         if (tracing) {
5904                 argsClobbered = TRUE;
5905                 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5906         }
5907
5908         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5909                 argsClobbered = TRUE;
5910
5911         /*
5912          * Optimize the common case of the first bblock making a call with the same
5913          * arguments as the method. This works because the arguments are still in their
5914          * original argument registers.
5915          */
5916         if (!argsClobbered) {
5917                 MonoBasicBlock *first_bb = cfg->bb_entry;
5918                 MonoInst *next;
5919                 int filter = FILTER_IL_SEQ_POINT;
5920
5921                 next = mono_bb_first_inst (first_bb, filter);
5922                 if (!next && first_bb->next_bb) {
5923                         first_bb = first_bb->next_bb;
5924                         next = mono_bb_first_inst (first_bb, filter);
5925                 }
5926
5927                 if (first_bb->in_count > 1)
5928                         next = NULL;
5929
5930                 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5931                         ArgInfo *ainfo = cinfo->args + i;
5932                         gboolean match = FALSE;
5933
5934                         inst = cfg->args [i];
5935                         if (inst->opcode != OP_REGVAR) {
5936                                 switch (ainfo->regtype) {
5937                                 case RegTypeGeneral: {
5938                                         if (((next->opcode == OP_LOAD_MEMBASE) || 
5939                                              (next->opcode == OP_LOADI4_MEMBASE)) && 
5940                                              next->inst_basereg == inst->inst_basereg && 
5941                                              next->inst_offset == inst->inst_offset) {
5942                                                 if (next->dreg == ainfo->reg) {
5943                                                         NULLIFY_INS (next);
5944                                                         match = TRUE;
5945                                                 } else {
5946                                                         next->opcode = OP_MOVE;
5947                                                         next->sreg1 = ainfo->reg;
5948                                                         /* Only continue if the instruction doesn't change argument regs */
5949                                                         if (next->dreg == ainfo->reg)
5950                                                                 match = TRUE;
5951                                                 }
5952                                         }
5953                                         break;
5954                                 }
5955                                 default:
5956                                         break;
5957                                 }
5958                         } else {
5959                                 /* Argument allocated to (non-volatile) register */
5960                                 switch (ainfo->regtype) {
5961                                 case RegTypeGeneral:
5962                                         if (next->opcode == OP_MOVE && 
5963                                             next->sreg1 == inst->dreg && 
5964                                             next->dreg == ainfo->reg) {
5965                                                 NULLIFY_INS (next);
5966                                                 match = TRUE;
5967                                         }
5968                                         break;
5969                                 default:
5970                                         break;
5971                                 }
5972                         }
5973
5974                         if (match) {
5975                                 next = mono_inst_next (next, filter);
5976                                 if (!next)
5977                                         break;
5978                         }
5979                 }
5980         }
5981
5982         cfg->code_len = code - cfg->native_code;
5983         g_assert (cfg->code_len < cfg->code_size);
5984
5985         return code;
5986 }
5987
5988 /*========================= End of Function ========================*/
5989
5990 /*------------------------------------------------------------------*/
5991 /*                                                                  */
5992 /* Name         - mono_arch_emit_epilog                             */
5993 /*                                                                  */
5994 /* Function     - Emit the instructions for a function epilog.      */
5995 /*                                                                  */
5996 /*------------------------------------------------------------------*/
5997
5998 void
5999 mono_arch_emit_epilog (MonoCompile *cfg)
6000 {
6001         MonoMethod *method = cfg->method;
6002         int tracing = 0;
6003         guint8 *code;
6004         int max_epilog_size = 96;
6005         
6006         if (cfg->method->save_lmf)
6007                 max_epilog_size += 128;
6008         
6009         if (mono_jit_trace_calls != NULL)
6010                 max_epilog_size += 128;
6011         else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6012                 max_epilog_size += 128;
6013         
6014         while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6015                 cfg->code_size  *= 2;
6016                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6017                 cfg->stat_code_reallocs++;
6018         }
6019
6020         code = cfg->native_code + cfg->code_len;
6021
6022         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6023                 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6024                 tracing = 1;
6025         }
6026         
6027         if (method->save_lmf) 
6028                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6029
6030         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6031                 s390_lg  (code, STK_BASE, 0, STK_BASE, 0);
6032         } else
6033                 code = backUpStackPtr(cfg, code);
6034
6035         s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6036         s390_br  (code, s390_r14);
6037
6038         cfg->code_len = code - cfg->native_code;
6039
6040         g_assert (cfg->code_len < cfg->code_size);
6041
6042 }
6043
6044 /*========================= End of Function ========================*/
6045
6046 /*------------------------------------------------------------------*/
6047 /*                                                                  */
6048 /* Name         - mono_arch_emit_exceptions                         */
6049 /*                                                                  */
6050 /* Function     - Emit the blocks to handle exception conditions.   */
6051 /*                                                                  */
6052 /*------------------------------------------------------------------*/
6053
6054 void
6055 mono_arch_emit_exceptions (MonoCompile *cfg) 
6056 {
6057         MonoJumpInfo    *patch_info;
6058         guint8          *code;
6059         int             nThrows = 0,
6060                         exc_count = 0,
6061                         iExc;
6062         guint32         code_size;
6063         MonoClass       *exc_classes [MAX_EXC];
6064         guint8          *exc_throw_start [MAX_EXC];
6065
6066         for (patch_info = cfg->patch_info; 
6067              patch_info; 
6068              patch_info = patch_info->next) {
6069                 if (patch_info->type == MONO_PATCH_INFO_EXC)
6070                         exc_count++;
6071         }
6072
6073         code_size = exc_count * 48;
6074
6075         while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6076                 cfg->code_size  *= 2;
6077                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6078                 cfg->stat_code_reallocs++; 
6079         }
6080
6081         code = cfg->native_code + cfg->code_len;
6082
6083         /*---------------------------------------------------------------------*/
6084         /* Add code to raise exceptions                                        */
6085         /*---------------------------------------------------------------------*/
6086         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6087                 switch (patch_info->type) {
6088                 case MONO_PATCH_INFO_EXC: {
6089                         guint8 *ip = patch_info->ip.i + cfg->native_code;
6090                         MonoClass *exc_class;
6091                         guint64 throw_ip;
6092
6093                         /*-----------------------------------------------------*/
6094                         /* Patch the branch in epilog to come here             */
6095                         /*-----------------------------------------------------*/
6096                         s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6097
6098                         exc_class = mono_class_load_from_name (mono_defaults.corlib,
6099                                                           "System", 
6100                                                           patch_info->data.name);
6101                         throw_ip = patch_info->ip.i;
6102
6103                         for (iExc = 0; iExc < nThrows; ++iExc)
6104                                 if (exc_classes [iExc] == exc_class)
6105                                         break;
6106                 
6107                         if (iExc < nThrows) {
6108                                 s390_jcl (code, S390_CC_UN, 
6109                                           (guint64) exc_throw_start [iExc]);
6110                                 patch_info->type = MONO_PATCH_INFO_NONE;
6111                         } else {
6112         
6113                                 if (nThrows < MAX_EXC) {
6114                                         exc_classes [nThrows]     = exc_class;
6115                                         exc_throw_start [nThrows] = code;
6116                                 }
6117         
6118                                 /*---------------------------------------------*/
6119                                 /* Patch the parameter passed to the handler   */ 
6120                                 /*---------------------------------------------*/
6121                                 S390_SET  (code, s390_r2, exc_class->type_token);
6122                                 /*---------------------------------------------*/
6123                                 /* Load return address & parameter register    */
6124                                 /*---------------------------------------------*/
6125                                 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6126                                                            cfg->native_code + 8), code));
6127                                 /*---------------------------------------------*/
6128                                 /* Reuse the current patch to set the jump     */
6129                                 /*---------------------------------------------*/
6130                                 patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
6131                                 patch_info->data.name = "mono_arch_throw_corlib_exception";
6132                                 patch_info->ip.i      = code - cfg->native_code;
6133                                 S390_BR_TEMPLATE (code, s390_r1);
6134                         }
6135                         break;
6136                 }
6137                 default:
6138                         /* do nothing */
6139                         break;
6140                 }
6141         }
6142
6143         cfg->code_len = code - cfg->native_code;
6144
6145         g_assert (cfg->code_len < cfg->code_size);
6146
6147 }
6148
6149 /*========================= End of Function ========================*/
6150
6151 /*------------------------------------------------------------------*/
6152 /*                                                                  */
6153 /* Name         - mono_arch_finish_init                                 */
6154 /*                                                                  */
6155 /* Function     - Setup the JIT's Thread Level Specific Data.       */
6156 /*                                                                  */
6157 /*------------------------------------------------------------------*/
6158
6159 void
6160 mono_arch_finish_init (void)
6161 {
6162         appdomain_tls_offset = mono_domain_get_tls_offset();
6163         lmf_tls_offset = mono_get_lmf_tls_offset();
6164         lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6165 }
6166
6167 /*========================= End of Function ========================*/
6168
6169 /*------------------------------------------------------------------*/
6170 /*                                                                  */
6171 /* Name         - mono_arch_free_jit_tls_data                       */
6172 /*                                                                  */
6173 /* Function     - Free tls data.                                    */
6174 /*                                                                  */
6175 /*------------------------------------------------------------------*/
6176
6177 void
6178 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6179 {
6180 }
6181
6182 /*========================= End of Function ========================*/
6183
6184 /*------------------------------------------------------------------*/
6185 /*                                                                  */
6186 /* Name         - mono_arch_emit_inst_for_method                    */
6187 /*                                                                  */
6188 /*------------------------------------------------------------------*/
6189
6190 MonoInst*
6191 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6192 {
6193         return NULL;
6194 }
6195
6196 /*========================= End of Function ========================*/
6197
6198 /*------------------------------------------------------------------*/
6199 /*                                                                  */
6200 /* Name         - mono_arch_decompose_opts                          */
6201 /*                                                                  */
6202 /* Function     - Decompose opcode into a System z opcode.          */
6203 /*                                                                  */
6204 /*------------------------------------------------------------------*/
6205
6206 void
6207 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6208 {
6209         /* 
6210          * Have to rename these to avoid being decomposed normally, since the normal 
6211          * decomposition does not work on S390.
6212          */
6213         switch (ins->opcode) {
6214         case OP_ISUB_OVF:
6215                 ins->opcode = OP_S390_ISUB_OVF;
6216                 break;
6217         case OP_ISUB_OVF_UN:
6218                 ins->opcode = OP_S390_ISUB_OVF_UN;
6219                 break;
6220         case OP_IADD_OVF:
6221                 ins->opcode = OP_S390_IADD_OVF;
6222                 break;
6223         case OP_IADD_OVF_UN:
6224                 ins->opcode = OP_S390_IADD_OVF_UN;
6225                 break;
6226         case OP_LADD_OVF:
6227                 ins->opcode = OP_S390_LADD_OVF;
6228                 break;
6229         case OP_LADD_OVF_UN:
6230                 ins->opcode = OP_S390_LADD_OVF_UN;
6231                 break;
6232         case OP_LSUB_OVF:
6233                 ins->opcode = OP_S390_LSUB_OVF;
6234                 break;
6235         case OP_LSUB_OVF_UN:
6236                 ins->opcode = OP_S390_LSUB_OVF_UN;
6237                 break;
6238         default:
6239                 break;
6240         }
6241 }
6242
6243 /*========================= End of Function ========================*/
6244
6245 /*------------------------------------------------------------------*/
6246 /*                                                                  */
6247 /* Name         - mono_arch_print_tree                              */
6248 /*                                                                  */
6249 /* Function     - Print platform-specific opcode details.           */
6250 /*                                                                  */
6251 /* Returns      - 1 - opcode details have been printed              */
6252 /*                0 - opcode details have not been printed          */
6253 /*                                                                  */
6254 /*------------------------------------------------------------------*/
6255
6256 gboolean
6257 mono_arch_print_tree (MonoInst *tree, int arity)
6258 {
6259         gboolean done;
6260
6261         switch (tree->opcode) {
6262                 case OP_S390_LOADARG:
6263                 case OP_S390_ARGREG:
6264                 case OP_S390_ARGPTR:
6265                         printf ("[0x%lx(%s)]", tree->inst_offset, 
6266                                 mono_arch_regname (tree->inst_basereg));
6267                         done = 1;
6268                         break;
6269                 case OP_S390_STKARG:
6270                         printf ("[0x%lx(previous_frame)]", 
6271                                 tree->inst_offset); 
6272                         done = 1;
6273                         break;
6274                 case OP_S390_MOVE:
6275                         printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6276                                 tree->inst_offset, tree->backend.size,
6277                                 mono_arch_regname(tree->dreg), 
6278                                 tree->inst_imm, 
6279                                 mono_arch_regname(tree->sreg1));
6280                         done = 1;
6281                         break;
6282                 case OP_S390_SETF4RET:
6283                         printf ("[f%s,f%s]", 
6284                                 mono_arch_regname (tree->dreg),
6285                                 mono_arch_regname (tree->sreg1));
6286                         done = 1;
6287                         break;
6288                 case OP_TLS_GET:
6289                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6290                                 tree->inst_imm,
6291                                 mono_arch_regname (tree->sreg1));
6292                         done = 1;
6293                         break;
6294                 case OP_S390_BKCHAIN:
6295                         printf ("[previous_frame(%s)]", 
6296                                 mono_arch_regname (tree->sreg1));
6297                         done = 1;
6298                 default:
6299                         done = 0;
6300         }
6301         return (done);
6302 }
6303
6304 /*========================= End of Function ========================*/
6305
6306 /*------------------------------------------------------------------*/
6307 /*                                                                  */
6308 /* Name         - mono_arch_regalloc_cost                           */
6309 /*                                                                  */
6310 /* Function     - Determine the cost, in the number of memory       */
6311 /*                references, of the action of allocating the var-  */
6312 /*                iable VMV into a register during global register  */
6313 /*                allocation.                                       */
6314 /*                                                                  */
6315 /* Returns      - Cost                                              */
6316 /*                                                                  */
6317 /*------------------------------------------------------------------*/
6318
6319 guint32
6320 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6321 {
6322         /* FIXME: */
6323         return 2;
6324 }
6325
6326 /*========================= End of Function ========================*/
6327
6328 /*------------------------------------------------------------------*/
6329 /*                                                                  */
6330 /* Name         - mono_arch_flush_register_windows                  */
6331 /*                                                                  */
6332 /* Function     -                                                   */
6333 /*                                                                  */
6334 /* Returns      -                                                   */
6335 /*                                                                  */
6336 /*------------------------------------------------------------------*/
6337
6338 void 
6339 mono_arch_flush_register_windows (void)
6340 {
6341 }
6342
6343 /*========================= End of Function ========================*/
6344
6345 /*------------------------------------------------------------------*/
6346 /*                                                                  */
6347 /* Name         - mono_arch_is_inst_imm                             */
6348 /*                                                                  */
6349 /* Function     - Determine if operand qualifies as an immediate    */
6350 /*                value. For s390 this is a value -32768-32768      */
6351 /*                                                                  */
6352 /* Returns      - True|False - is [not] immediate value.            */
6353 /*                                                                  */
6354 /*------------------------------------------------------------------*/
6355
6356 gboolean 
6357 mono_arch_is_inst_imm (gint64 imm)
6358 {
6359         return s390_is_imm32 (imm);
6360 }
6361
6362 /*========================= End of Function ========================*/
6363
6364 /*------------------------------------------------------------------*/
6365 /*                                                                  */
6366 /* Name         - mono_arch_get_patch_offset                        */
6367 /*                                                                  */
6368 /* Function     - Dummy entry point until s390x supports aot.       */
6369 /*                                                                  */
6370 /* Returns      - Offset for patch.                                 */
6371 /*                                                                  */
6372 /*------------------------------------------------------------------*/
6373
6374 guint32
6375 mono_arch_get_patch_offset (guint8 *code)
6376 {
6377         return 0;
6378 }
6379
6380 /*========================= End of Function ========================*/
6381
6382 /*------------------------------------------------------------------*/
6383 /*                                                                  */
6384 /* Name         - mono_arch_context_get_int_reg.                    */
6385 /*                                                                  */
6386 /* Function     -                                                   */
6387 /*                                                                  */
6388 /* Returns      - Return a register from the context.               */
6389 /*                                                                  */
6390 /*------------------------------------------------------------------*/
6391
6392 mgreg_t
6393 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6394 {
6395         return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6396 }
6397
6398 /*========================= End of Function ========================*/
6399
6400 /*------------------------------------------------------------------*/
6401 /*                                                                  */
6402 /* Name         - mono_arch_context_set_int_reg.                    */
6403 /*                                                                  */
6404 /* Function     - Set a value in a specified register.              */
6405 /*                                                                  */
6406 /*------------------------------------------------------------------*/
6407
6408 void
6409 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6410 {
6411         ctx->uc_mcontext.gregs[reg] = val;
6412 }
6413
6414 /*========================= End of Function ========================*/
6415
6416 /*------------------------------------------------------------------*/
6417 /*                                                                  */
6418 /* Name         - mono_arch_get_this_arg_from_call.                 */
6419 /*                                                                  */
6420 /* Function     -                                                   */
6421 /*                                                                  */
6422 /*------------------------------------------------------------------*/
6423
6424 gpointer
6425 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6426 {
6427         return (gpointer) regs [s390_r2];
6428 }
6429
6430 /*========================= End of Function ========================*/
6431  
6432 /*------------------------------------------------------------------*/
6433 /*                                                                  */
6434 /* Name         - mono_arch_install_handler_block_guard             */
6435 /*                                                                  */
6436 /* Function     -                                                   */
6437 /*                                                                  */
6438 /*------------------------------------------------------------------*/
6439
6440 gpointer
6441 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, 
6442                                        MonoContext *ctx, gpointer new_value)
6443 {
6444         int offset;
6445         gpointer *sp, old_value;
6446         char *bp;
6447
6448         offset = clause->exvar_offset;
6449
6450         /*Load the spvar*/
6451         bp = MONO_CONTEXT_GET_BP (ctx);
6452         sp = *(gpointer*)(bp + offset);
6453
6454         old_value = *sp;
6455         if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6456                 return old_value;
6457
6458         *sp = new_value;
6459
6460         return old_value;
6461 }
6462
6463 /*========================= End of Function ========================*/
6464  
6465 /*------------------------------------------------------------------*/
6466 /*                                                                  */
6467 /* Name         - get_delegate_invoke_impl.                         */
6468 /*                                                                  */
6469 /* Function     -                                                   */
6470 /*                                                                  */
6471 /*------------------------------------------------------------------*/
6472
6473 static gpointer
6474 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6475 {
6476         guint8 *code, *start;
6477
6478         if (has_target) {
6479                 int size = 32;
6480
6481                 start = code = mono_global_codeman_reserve (size);
6482
6483                 /* Replace the this argument with the target */
6484                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6485                 s390_lg   (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6486                 s390_br   (code, s390_r1);
6487                 g_assert ((code - start) <= size);
6488
6489                 mono_arch_flush_icache (start, size);
6490         } else {
6491                 int size, i;
6492
6493                 size = 32 + param_count * 8;
6494                 start = code = mono_global_codeman_reserve (size);
6495
6496                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6497                 /* slide down the arguments */
6498                 for (i = 0; i < param_count; ++i) {
6499                         s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6500                 }
6501                 s390_br   (code, s390_r1);
6502
6503                 g_assert ((code - start) <= size);
6504
6505                 mono_arch_flush_icache (start, size);
6506         }
6507
6508         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6509
6510         if (has_target) {
6511                 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6512         } else {
6513                 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6514                 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6515                 g_free (name);
6516         }
6517
6518         return start;
6519 }
6520
6521 /*========================= End of Function ========================*/
6522
6523 /*------------------------------------------------------------------*/
6524 /*                                                                  */
6525 /* Name         - mono_arch_get_delegate_invoke_impls.              */
6526 /*                                                                  */
6527 /* Function     -                                                   */
6528 /*                                                                  */
6529 /*------------------------------------------------------------------*/
6530
6531 GSList*
6532 mono_arch_get_delegate_invoke_impls (void)
6533 {
6534         GSList *res = NULL;
6535         MonoTrampInfo *info;
6536         int i;
6537
6538         get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6539         res = g_slist_prepend (res, info);
6540
6541         for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6542                 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6543                 res = g_slist_prepend (res, info);
6544         }
6545
6546         return res;
6547 }
6548
6549 /*========================= End of Function ========================*/
6550
6551 /*------------------------------------------------------------------*/
6552 /*                                                                  */
6553 /* Name         - mono_arch_get_delegate_invoke_impl.               */
6554 /*                                                                  */
6555 /* Function     -                                                   */
6556 /*                                                                  */
6557 /*------------------------------------------------------------------*/
6558
6559 gpointer
6560 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6561 {
6562         guint8 *code, *start;
6563
6564         /* FIXME: Support more cases */
6565         if (MONO_TYPE_ISSTRUCT (sig->ret))
6566                 return NULL;
6567
6568         if (has_target) {
6569                 static guint8* cached = NULL;
6570
6571                 if (cached)
6572                         return cached;
6573
6574                 if (mono_aot_only) {
6575                         start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6576                 } else {
6577                         MonoTrampInfo *info;
6578                         start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6579                         mono_tramp_info_register (info, NULL);
6580                 }
6581
6582                 mono_memory_barrier ();
6583
6584                 cached = start;
6585         } else {
6586                 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6587                 int i;
6588
6589                 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6590                         return NULL;
6591                 for (i = 0; i < sig->param_count; ++i)
6592                         if (!mono_is_regsize_var (sig->params [i]))
6593                                 return NULL;
6594
6595
6596                 code = cache [sig->param_count];
6597                 if (code)
6598                         return code;
6599
6600                 if (mono_aot_only) {
6601                         char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6602                         start = mono_aot_get_trampoline (name);
6603                         g_free (name);
6604                 } else {
6605                         MonoTrampInfo *info;
6606                         start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6607                         mono_tramp_info_register (info, NULL);
6608                 }
6609
6610                 mono_memory_barrier ();
6611
6612                 cache [sig->param_count] = start;
6613         }
6614         return start;
6615 }
6616
6617 /*========================= End of Function ========================*/
6618
6619 /*------------------------------------------------------------------*/
6620 /*                                                                  */
6621 /* Name         - mono_arch_get_delegate_virtual_invoke_impl.       */
6622 /*                                                                  */
6623 /* Function     -                                                   */
6624 /*                                                                  */
6625 /*------------------------------------------------------------------*/
6626
6627 gpointer
6628 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, 
6629                                             int offset, gboolean load_imt_reg)
6630 {
6631         guint8 *code, *start;
6632         int size = 40;
6633
6634         start = code = mono_global_codeman_reserve (size);
6635
6636         /*
6637         * Replace the "this" argument with the target
6638         */
6639         s390_lgr  (code, s390_r1, s390_r2);
6640         s390_lg   (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));        
6641
6642         /*
6643         * Load the IMT register, if needed
6644         */
6645         if (load_imt_reg) {
6646                 s390_lg  (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6647         }
6648
6649         /*
6650         * Load the vTable
6651         */
6652         s390_lg  (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6653         if (offset != 0) {
6654                 s390_agfi(code, s390_r1, offset);
6655         }
6656         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6657         s390_br  (code, s390_r1);
6658
6659         return(start);
6660 }
6661
6662 /*========================= End of Function ========================*/
6663
6664 /*------------------------------------------------------------------*/
6665 /*                                                                  */
6666 /* Name         - mono_arch_build_imt_trampoline.                       */
6667 /*                                                                  */
6668 /* Function     -                                                   */
6669 /*                                                                  */
6670 /*------------------------------------------------------------------*/
6671
6672 gpointer
6673 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, 
6674                                                                 MonoIMTCheckItem **imt_entries, int count,
6675                                                                 gpointer fail_tramp)
6676 {
6677         int i;
6678         int size = 0;
6679         guchar *code, *start;
6680         char trampName[64];
6681
6682         for (i = 0; i < count; ++i) {
6683                 MonoIMTCheckItem *item = imt_entries [i];
6684                 if (item->is_equals) {
6685                         if (item->check_target_idx) {
6686                                 if (!item->compare_done)
6687                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6688                                 if (item->has_target_code)
6689                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6690                                 else
6691                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE + 
6692                                                             LOAD_SIZE;
6693                         } else {
6694                                 if (fail_tramp) {
6695                                         item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE + 
6696                                                             2 * LOADCON_SIZE;
6697                                         if (!item->has_target_code)
6698                                                 item->chunk_size += LOAD_SIZE;
6699                                 } else {
6700                                         item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6701 #if ENABLE_WRONG_METHOD_CHECK
6702                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6703 #endif
6704                                 }
6705                         }
6706                 } else {
6707                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6708                         imt_entries [item->check_target_idx]->compare_done = TRUE;
6709                 }
6710                 size += item->chunk_size;
6711         }
6712
6713         if (fail_tramp)
6714                 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6715         else
6716                 code = mono_domain_code_reserve (domain, size);
6717
6718         start = code;
6719
6720         for (i = 0; i < count; ++i) {
6721                 MonoIMTCheckItem *item = imt_entries [i];
6722                 item->code_target = (guint8 *) code;
6723                 if (item->is_equals) {
6724                         if (item->check_target_idx) {
6725                                 if (!item->compare_done) {
6726                                         S390_SET  (code, s390_r0, item->key);
6727                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6728                                 }
6729                                 item->jmp_code = (guint8*) code;
6730                                 s390_jcl (code, S390_CC_NE, 0);
6731                                 
6732                                 if (item->has_target_code) {
6733                                         S390_SET (code, s390_r1, item->value.target_code);
6734                                 } else {
6735                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6736                                         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6737                                 }
6738                                 s390_br   (code, s390_r1);
6739                         } else {
6740                                 if (fail_tramp) {
6741                                         gint64  target;
6742
6743                                         S390_SET  (code, s390_r0, item->key);
6744                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6745                                         item->jmp_code = (guint8*) code;
6746                                         s390_jcl  (code, S390_CC_NE, 0);
6747                                         if (item->has_target_code) {
6748                                                 S390_SET (code, s390_r1, item->value.target_code);
6749                                         } else {
6750                                                 g_assert (vtable);
6751                                                 S390_SET  (code, s390_r1, 
6752                                                            (&(vtable->vtable [item->value.vtable_slot])));
6753                                                 s390_lg   (code, s390_r1, 0, s390_r1, 0);
6754                                         }
6755                                         s390_br   (code, s390_r1);
6756                                         target = (gint64) S390_RELATIVE(code, item->jmp_code);
6757                                         s390_patch_rel(item->jmp_code+2, target);
6758                                         S390_SET  (code, s390_r1, fail_tramp);
6759                                         s390_br   (code, s390_r1);
6760                                         item->jmp_code = NULL;
6761                                 } else {
6762                                 /* enable the commented code to assert on wrong method */
6763 #if ENABLE_WRONG_METHOD_CHECK
6764                                         g_assert_not_reached ();
6765 #endif
6766                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6767                                         s390_lg   (code, s390_r1, 0, s390_r1, 0);
6768                                         s390_br   (code, s390_r1);
6769                                 }
6770                         }
6771                 } else {
6772                         S390_SET  (code, s390_r0, item->key);
6773                         s390_cgr  (code, MONO_ARCH_IMT_REG, s390_r0);
6774                         item->jmp_code = (guint8 *) code;
6775                         s390_jcl  (code, S390_CC_GE, 0);
6776                 }
6777         }
6778         /* 
6779          * patch the branches to get to the target items 
6780          */
6781         for (i = 0; i < count; ++i) {
6782                 MonoIMTCheckItem *item = imt_entries [i];
6783                 if (item->jmp_code) {
6784                         if (item->check_target_idx) {
6785                                 gint64 offset;
6786                                 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6787                                                        item->jmp_code);
6788                                 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6789                         }
6790                 }
6791         }
6792
6793         mono_arch_flush_icache ((guint8*)start, (code - start));
6794         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6795
6796         if (!fail_tramp) 
6797                 mono_stats.imt_trampolines_size += (code - start);
6798
6799         g_assert (code - start <= size);
6800
6801         snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6802         mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6803
6804         return (start);
6805 }
6806
6807 /*========================= End of Function ========================*/
6808
6809 /*------------------------------------------------------------------*/
6810 /*                                                                  */
6811 /* Name         - mono_arch_find_imt_method.                        */
6812 /*                                                                  */
6813 /* Function     - Get the method address from MONO_ARCH_IMT_REG     */
6814 /*                found in the save area.                           */
6815 /*                                                                  */
6816 /*------------------------------------------------------------------*/
6817
6818 MonoMethod*
6819 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6820 {
6821         return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6822 }
6823
6824 /*========================= End of Function ========================*/
6825
6826 /*------------------------------------------------------------------*/
6827 /*                                                                  */
6828 /* Name         - mono_arch_find_static_call_vtable                 */
6829 /*                                                                  */
6830 /* Function     - Find the static call vtable.                      */
6831 /*                                                                  */
6832 /*------------------------------------------------------------------*/
6833
6834 MonoVTable*
6835 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6836 {
6837         mgreg_t *r = (mgreg_t*)regs;
6838
6839         return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6840 }
6841
6842 /*========================= End of Function ========================*/
6843
6844 /*------------------------------------------------------------------*/
6845 /*                                                                  */
6846 /* Name         - mono_arch_get_cie_program                         */
6847 /*                                                                  */
6848 /* Function     - Find the static call vtable.                      */
6849 /*                                                                  */
6850 /*------------------------------------------------------------------*/
6851
6852 GSList*
6853 mono_arch_get_cie_program (void)
6854 {
6855         GSList *l = NULL;
6856
6857         mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6858
6859         return(l);
6860 }
6861
6862 /*========================= End of Function ========================*/
6863
6864 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6865
6866 /*------------------------------------------------------------------*/
6867 /*                                                                  */
6868 /* Name         - mono_arch_set_breakpoint.                         */
6869 /*                                                                  */
6870 /* Function     - Set a breakpoint at the native code corresponding */
6871 /*                to JI at NATIVE_OFFSET.  The location should      */
6872 /*                contain code emitted by OP_SEQ_POINT.             */
6873 /*                                                                  */
6874 /*------------------------------------------------------------------*/
6875
6876 void
6877 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6878 {
6879         guint8 *code = ip;
6880
6881         breakpointCode.pTrigger = bp_trigger_page;
6882         memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6883         code += BREAKPOINT_SIZE;
6884 }
6885
6886 /*========================= End of Function ========================*/
6887
6888 /*------------------------------------------------------------------*/
6889 /*                                                                  */
6890 /* Name         - mono_arch_clear_breakpoint.                       */
6891 /*                                                                  */
6892 /* Function     - Clear the breakpoint at IP.                       */
6893 /*                                                                  */
6894 /*------------------------------------------------------------------*/
6895
6896 void
6897 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6898 {
6899         guint8 *code = ip;
6900         int i;
6901
6902         for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6903                 s390_nop(code);
6904 }
6905
6906 /*========================= End of Function ========================*/
6907
6908 /*------------------------------------------------------------------*/
6909 /*                                                                  */
6910 /* Name         - mono_arch_is_breakpoint_event.                    */
6911 /*                                                                  */
6912 /* Function     -                                                   */
6913 /*                                                                  */
6914 /*------------------------------------------------------------------*/
6915
6916 gboolean
6917 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6918 {
6919         siginfo_t* sinfo = (siginfo_t*) info;
6920
6921         /* 
6922          * Sometimes the address is off by 4 
6923          */
6924         if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6925                 return TRUE;
6926         else
6927                 return FALSE;
6928 }
6929
6930 /*========================= End of Function ========================*/
6931
6932 /*------------------------------------------------------------------*/
6933 /*                                                                  */
6934 /* Name         - mono_arch_skip_breakpoint.                        */
6935 /*                                                                  */
6936 /* Function     - Modify the CTX so the IP is placed after the      */
6937 /*                breakpoint instruction, so when we resume, the    */
6938 /*                instruction is not executed again.                */
6939 /*                                                                  */
6940 /*------------------------------------------------------------------*/
6941
6942 void
6943 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6944 {
6945         MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6946 }
6947
6948 /*========================= End of Function ========================*/
6949         
6950 /*------------------------------------------------------------------*/
6951 /*                                                                  */
6952 /* Name         - mono_arch_start_single_stepping.                  */
6953 /*                                                                  */
6954 /* Function     - Start single stepping.                            */
6955 /*                                                                  */
6956 /*------------------------------------------------------------------*/
6957
6958 void
6959 mono_arch_start_single_stepping (void)
6960 {
6961         mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6962 }
6963
6964 /*========================= End of Function ========================*/
6965         
6966 /*------------------------------------------------------------------*/
6967 /*                                                                  */
6968 /* Name         - mono_arch_stop_single_stepping.                   */
6969 /*                                                                  */
6970 /* Function     - Stop single stepping.                             */
6971 /*                                                                  */
6972 /*------------------------------------------------------------------*/
6973
6974 void
6975 mono_arch_stop_single_stepping (void)
6976 {
6977         mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6978 }
6979
6980 /*========================= End of Function ========================*/
6981
6982 /*------------------------------------------------------------------*/
6983 /*                                                                  */
6984 /* Name         - mono_arch_is_single_step_event.                   */
6985 /*                                                                  */
6986 /* Function     - Return whether the machine state in sigctx cor-   */
6987 /*                responds to a single step event.                  */
6988 /*                                                                  */
6989 /*------------------------------------------------------------------*/
6990
6991 gboolean
6992 mono_arch_is_single_step_event (void *info, void *sigctx)
6993 {
6994         siginfo_t* sinfo = (siginfo_t*) info;
6995
6996         /* 
6997          * Sometimes the address is off by 4 
6998          */
6999         if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7000                 return TRUE;
7001         else
7002                 return FALSE;
7003 }
7004
7005 /*========================= End of Function ========================*/
7006
7007 /*------------------------------------------------------------------*/
7008 /*                                                                  */
7009 /* Name         - mono_arch_skip_single_step.                       */
7010 /*                                                                  */
7011 /* Function     - Modify the ctx so the IP is placed after the      */
7012 /*                single step trigger instruction, so that the      */
7013 /*                instruction is not executed again.                */
7014 /*                                                                  */
7015 /*------------------------------------------------------------------*/
7016
7017 void
7018 mono_arch_skip_single_step (MonoContext *ctx)
7019 {
7020         MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7021 }
7022
7023 /*========================= End of Function ========================*/
7024
7025 /*------------------------------------------------------------------*/
7026 /*                                                                  */
7027 /* Name         - mono_arch_create_seq_point_info.                  */
7028 /*                                                                  */
7029 /* Function     - Return a pointer to a data struction which is     */
7030 /*                used by the sequence point implementation in      */
7031 /*                AOTed code.                                       */
7032 /*                                                                  */
7033 /*------------------------------------------------------------------*/
7034
7035 gpointer
7036 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7037 {
7038         NOT_IMPLEMENTED;
7039         return NULL;
7040 }
7041
7042 /*========================= End of Function ========================*/
7043
7044 /*------------------------------------------------------------------*/
7045 /*                                                                  */
7046 /* Name         - mono_arch_init_lmf_ext.                           */
7047 /*                                                                  */
7048 /* Function -                                                       */
7049 /*                                                                  */
7050 /*------------------------------------------------------------------*/
7051
7052 void
7053 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7054 {
7055         ext->lmf.previous_lmf = prev_lmf;
7056         /* Mark that this is a MonoLMFExt */
7057         ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7058         ext->lmf.ebp = (gssize)ext;
7059 }
7060
7061 /*========================= End of Function ========================*/
7062
7063 #endif
7064
7065 /*------------------------------------------------------------------*/
7066 /*                                                                  */
7067 /* Name     - mono_arch_cpu_enumerate_simd_versions.                */
7068 /*                                                                  */
7069 /* Function - If this CPU supports vector operations then it        */
7070 /*            supports the equivalent of SSE1-4.                    */
7071 /*                                                                  */
7072 /*------------------------------------------------------------------*/
7073
7074 guint32
7075 mono_arch_cpu_enumerate_simd_versions (void)
7076 {
7077         guint32 sseOpts = 0;
7078
7079         if (mono_hwcap_s390x_has_vec)
7080                 sseOpts = (SIMD_VERSION_SSE1  | SIMD_VERSION_SSE2 |
7081                            SIMD_VERSION_SSE3  | SIMD_VERSION_SSSE3 |
7082                            SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7083                            SIMD_VERSION_SSE4a);
7084
7085         return (sseOpts);
7086 }
7087
7088 /*========================= End of Function ========================*/
7089
7090 /*------------------------------------------------------------------*/
7091 /*                                                                  */
7092 /* Name     - mono_arch_opcode_supported.                           */
7093 /*                                                                  */
7094 /* Function - Check if a given return code is supported.            */
7095 /*                                                                  */
7096 /*------------------------------------------------------------------*/
7097
7098 gboolean
7099 mono_arch_opcode_supported (int opcode)
7100 {
7101         switch (opcode) {
7102         case OP_ATOMIC_ADD_I4:
7103         case OP_ATOMIC_ADD_I8:
7104         case OP_ATOMIC_EXCHANGE_I4:
7105         case OP_ATOMIC_EXCHANGE_I8:
7106                 return TRUE;
7107         default:
7108                 return FALSE;
7109         }
7110 }
7111
7112 /*========================= End of Function ========================*/