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