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