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