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