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