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