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