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