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