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