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