a4a7776094c57ab7ee2372e50f8da6d51f4e4d2b
[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         MonoError error;
5391
5392         for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5393                 unsigned char *ip = patch_info->ip.i + code;
5394                 gconstpointer target = NULL;
5395
5396                 target = mono_resolve_patch_target (method, domain, code, 
5397                                                                                         patch_info, run_cctors, &error);
5398                 mono_error_raise_exception (&error); /* FIXME: don't raise here */
5399
5400                 switch (patch_info->type) {
5401                         case MONO_PATCH_INFO_IP:
5402                         case MONO_PATCH_INFO_LDSTR:
5403                         case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
5404                         case MONO_PATCH_INFO_LDTOKEN: 
5405                         case MONO_PATCH_INFO_EXC:
5406                                 s390_patch_addr (ip, (guint64) target);
5407                                 continue;
5408                         case MONO_PATCH_INFO_METHOD:
5409                         case MONO_PATCH_INFO_INTERNAL_METHOD:
5410                         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5411                         case MONO_PATCH_INFO_RGCTX_FETCH:
5412                         case MONO_PATCH_INFO_ABS: {
5413                                 S390_EMIT_CALL (ip, target);
5414                                 continue;
5415                         }
5416                         case MONO_PATCH_INFO_SWITCH: 
5417                                 /*----------------------------------*/
5418                                 /* ip points at the basr r13,0/j +4 */
5419                                 /* instruction the vtable value     */
5420                                 /* follows this (i.e. ip+6)         */
5421                                 /*----------------------------------*/
5422                                 S390_EMIT_LOAD (ip, target);
5423                                 continue;
5424                         case MONO_PATCH_INFO_METHODCONST:
5425                         case MONO_PATCH_INFO_CLASS:
5426                         case MONO_PATCH_INFO_IMAGE:
5427                         case MONO_PATCH_INFO_FIELD:
5428                         case MONO_PATCH_INFO_IID:
5429                         case MONO_PATCH_INFO_EXC_NAME:
5430                                 target = S390_RELATIVE(target, ip);
5431                                 s390_patch_rel (ip, (guint64) target);
5432                                 continue;
5433                         case MONO_PATCH_INFO_R4:
5434                         case MONO_PATCH_INFO_R8:
5435                         case MONO_PATCH_INFO_METHOD_REL:
5436                                 g_assert_not_reached ();
5437                                 continue;
5438                         default:
5439                                 target = S390_RELATIVE(target, ip);
5440                                 ip += 2;
5441                                 s390_patch_rel (ip, (guint64) target);
5442                 }
5443         }
5444 }
5445
5446 /*========================= End of Function ========================*/
5447
5448 /*------------------------------------------------------------------*/
5449 /*                                                                  */
5450 /* Name         - emit_load_volatile_arguments                      */
5451 /*                                                                  */
5452 /* Function     - Emit the instructions to reload parameter regist- */
5453 /*                registers for use with "tail" operations.         */
5454 /*                                                                  */
5455 /*                The register loading operations performed here    */
5456 /*                are the mirror of the store operations performed  */
5457 /*                in mono_arch_emit_prolog and need to be kept in   */
5458 /*                synchronization with it.                          */
5459 /*                                                                  */
5460 /*------------------------------------------------------------------*/
5461
5462 guint8 *
5463 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5464 {
5465         MonoInst *inst;
5466         MonoMethod *method = cfg->method;
5467         MonoMethodSignature *sig = mono_method_signature(method);
5468         int pos = 0, i;
5469         CallInfo *cinfo;
5470
5471         cinfo = get_call_info (NULL, NULL, sig);
5472
5473         if (cinfo->struct_ret) {
5474                 ArgInfo *ainfo = &cinfo->ret;
5475                 inst         = cfg->vret_addr;
5476                 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5477         }
5478
5479         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5480                 ArgInfo *ainfo = cinfo->args + i;
5481                 inst = cfg->args [pos];
5482
5483                 if (inst->opcode == OP_REGVAR) {
5484                         if (ainfo->regtype == RegTypeGeneral)
5485                                 s390_lgr (code, ainfo->reg, inst->dreg);
5486                         else if (ainfo->regtype == RegTypeFP) {
5487                                 if (inst->dreg != ainfo->reg) {
5488                                         if (ainfo->size == 4) {
5489                                                 s390_ldebr (code, ainfo->reg, inst->dreg);
5490                                         } else {
5491                                                 s390_ldr   (code, ainfo->reg, inst->dreg);
5492                                         }
5493                                 }
5494                         }
5495                         else if (ainfo->regtype == RegTypeBase) {
5496                         } else
5497                                 g_assert_not_reached ();
5498                 } else {
5499                         if (ainfo->regtype == RegTypeGeneral) {
5500                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5501                                         g_assert_not_reached();
5502                                 switch (ainfo->size) {
5503                                 case 1:
5504                                         s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5505                                         break;
5506                                 case 2:
5507                                         s390_lgh  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5508                                         break;
5509                                 case 4: 
5510                                         s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5511                                         break;
5512                                 case 8:
5513                                         s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5514                                         break;
5515                                 }
5516                         } else if (ainfo->regtype == RegTypeBase) {
5517                         } else if (ainfo->regtype == RegTypeFP) {
5518                                 if (ainfo->size == 8)
5519                                         s390_ld  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5520                                 else if (ainfo->size == 4)
5521                                         s390_le  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5522                                 else
5523                                         g_assert_not_reached ();
5524                         } else if (ainfo->regtype == RegTypeStructByVal) {
5525                                 if (ainfo->reg != STK_BASE) {
5526                                         switch (ainfo->size) {
5527                                         case 1:
5528                                                 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5529                                                 break;
5530                                         case 2:
5531                                                 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532                                                 break;
5533                                         case 4:
5534                                                 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5535                                                 break;
5536                                         case 8:
5537                                                 s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538                                                 break;
5539                                         }
5540                                 }
5541                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5542                                 if (ainfo->reg != STK_BASE) {
5543                                         s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5544                                 }
5545                         } else
5546                                 g_assert_not_reached ();
5547                 }
5548                 pos++;
5549         }
5550
5551         return code;
5552 }
5553
5554 /*========================= End of Function ========================*/
5555
5556 /*------------------------------------------------------------------*/
5557 /*                                                                  */
5558 /* Name         - mono_arch_emit_prolog                             */
5559 /*                                                                  */
5560 /* Function     - Create the instruction sequence for a function    */
5561 /*                prolog.                                           */
5562 /*                                                                  */
5563 /*------------------------------------------------------------------*/
5564
5565 guint8 *
5566 mono_arch_emit_prolog (MonoCompile *cfg)
5567 {
5568         MonoMethod *method = cfg->method;
5569         MonoBasicBlock *bb;
5570         MonoMethodSignature *sig;
5571         MonoInst *inst;
5572         long alloc_size, pos, max_offset, i, cfa_offset = 0;
5573         guint8 *code;
5574         guint32 size;
5575         CallInfo *cinfo;
5576         int tracing = 0,
5577             argsClobbered = 0,
5578             lmfOffset,
5579             fpOffset;
5580
5581         cfg->code_size   = 512;
5582
5583         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5584                 tracing         = 1;
5585                 cfg->code_size += 256;
5586         } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5587                 cfg->code_size += 256;
5588
5589         if (method->save_lmf)
5590                 cfg->code_size += 200;
5591
5592         cfg->native_code = code = g_malloc (cfg->code_size);
5593
5594         mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5595         emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5596         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5597         mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5598         mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5599
5600         if (cfg->arch.bkchain_reg != -1)
5601                 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5602
5603         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5604                 cfg->used_int_regs |= 1 << 11;
5605         }
5606
5607         alloc_size = cfg->stack_offset;
5608
5609         cfg->stack_usage = cfa_offset = alloc_size;
5610         mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5611         s390_lgr  (code, s390_r11, STK_BASE);
5612         if (s390_is_imm16 (alloc_size)) {
5613                 s390_aghi (code, STK_BASE, -alloc_size);
5614         } else if (s390_is_imm32 (alloc_size)) { 
5615                 s390_agfi (code, STK_BASE, -alloc_size);
5616         } else {
5617                 int stackSize = alloc_size;
5618                 while (stackSize > INT_MAX) {
5619                         s390_agfi (code, STK_BASE, -INT_MAX);
5620                         stackSize -= INT_MAX;
5621                 }
5622                 s390_agfi (code, STK_BASE, -stackSize);
5623         }
5624         s390_stg  (code, s390_r11, 0, STK_BASE, 0);
5625
5626         if (cfg->frame_reg != STK_BASE)
5627                 s390_lgr (code, s390_r11, STK_BASE);
5628
5629         mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5630
5631         /* store runtime generic context */
5632         if (cfg->rgctx_var) {
5633                 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5634
5635                 s390_stg  (code, MONO_ARCH_RGCTX_REG, 0, 
5636                            cfg->rgctx_var->inst_basereg, 
5637                            cfg->rgctx_var->inst_offset);
5638         }
5639
5640         /* compute max_offset in order to use short forward jumps
5641          * we always do it on s390 because the immediate displacement
5642          * for jumps is too small 
5643          */
5644         max_offset = 0;
5645         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5646                 MonoInst *ins;
5647                 bb->max_offset = max_offset;
5648
5649                 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5650                         max_offset += 6; 
5651
5652                 MONO_BB_FOR_EACH_INS (bb, ins)
5653                         max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5654         }
5655
5656         /* load arguments allocated to register from the stack */
5657         sig = mono_method_signature (method);
5658         pos = 0;
5659
5660         cinfo = get_call_info (cfg, cfg->mempool, sig);
5661
5662         if (cinfo->struct_ret) {
5663                 ArgInfo *ainfo     = &cinfo->ret;
5664                 inst               = cfg->vret_addr;
5665                 inst->backend.size = ainfo->vtsize;
5666                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5667         }
5668
5669         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5670                 ArgInfo *ainfo = cinfo->args + i;
5671                 inst = cfg->args [pos];
5672                 
5673                 if (inst->opcode == OP_VTARG_ADDR)
5674                         inst = inst->inst_left;
5675
5676                 if (inst->opcode == OP_REGVAR) {
5677                         if (ainfo->regtype == RegTypeGeneral)
5678                                 s390_lgr (code, inst->dreg, ainfo->reg);
5679                         else if (ainfo->regtype == RegTypeFP) {
5680                                 if (inst->dreg != ainfo->reg) {
5681                                         if (ainfo->size == 4) {
5682                                                 s390_ledbr (code, inst->dreg, ainfo->reg);
5683                                         } else {
5684                                                 s390_ldr   (code, inst->dreg, ainfo->reg);
5685                                         }
5686                                 }
5687                         }
5688                         else if (ainfo->regtype == RegTypeBase) {
5689                                 s390_lgr  (code, s390_r13, STK_BASE);
5690                                 s390_aghi (code, s390_r13, alloc_size);
5691                                 s390_lg   (code, inst->dreg, 0, s390_r13, ainfo->offset);
5692                         } else
5693                                 g_assert_not_reached ();
5694
5695                         if (cfg->verbose_level > 2)
5696                                 g_print ("Argument %d assigned to register %s\n", 
5697                                          pos, mono_arch_regname (inst->dreg));
5698                 } else {
5699                         if (ainfo->regtype == RegTypeGeneral) {
5700                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5701                                         g_assert_not_reached();
5702                                 switch (ainfo->size) {
5703                                 case 1:
5704                                         s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5705                                         break;
5706                                 case 2:
5707                                         s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5708                                         break;
5709                                 case 4: 
5710                                         s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5711                                         break;
5712                                 case 8:
5713                                         s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5714                                         break;
5715                                 }
5716                         } else if (ainfo->regtype == RegTypeBase) {
5717                         } else if (ainfo->regtype == RegTypeFP) {
5718                                 if (ainfo->size == 8)
5719                                         s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5720                                 else if (ainfo->size == 4)
5721                                         s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5722                                 else
5723                                         g_assert_not_reached ();
5724                         } else if (ainfo->regtype == RegTypeStructByVal) {
5725                                 int doffset = inst->inst_offset;
5726                                 int reg;
5727                                 if (ainfo->reg != STK_BASE)
5728                                         reg = ainfo->reg;
5729                                 else {
5730                                         reg = s390_r0;
5731                                         s390_lgr  (code, s390_r13, STK_BASE);
5732                                         s390_aghi (code, s390_r13, alloc_size);
5733                                 }
5734
5735                                 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE  
5736                                         ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5737                                         : ainfo->size);
5738
5739                                 switch (size) {
5740                                         case 1:
5741                                                 if (ainfo->reg == STK_BASE)
5742                                                         s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5743                                                 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5744                                                 break;
5745                                         case 2:
5746                                                 if (ainfo->reg == STK_BASE)
5747                                                         s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5748                                                 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5749                                                 break;
5750                                         case 4:
5751                                                 if (ainfo->reg == STK_BASE)
5752                                                         s390_l  (code, reg, 0, s390_r13, ainfo->offset+4);
5753                                                 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5754                                                 break;
5755                                         case 8:
5756                                                 if (ainfo->reg == STK_BASE)
5757                                                         s390_lg  (code, reg, 0, s390_r13, ainfo->offset);
5758                                                 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5759                                                 break;
5760                                 }
5761                         } else if (ainfo->regtype == RegTypeStructByAddr) {
5762                                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5763                         } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5764                         } else
5765                                 g_assert_not_reached ();
5766                 }
5767                 pos++;
5768         }
5769
5770         if (method->save_lmf) {
5771                 /*---------------------------------------------------------------*/
5772                 /* build the MonoLMF structure on the stack - see mini-s390x.h   */
5773                 /*---------------------------------------------------------------*/
5774                 lmfOffset = alloc_size - sizeof(MonoLMF);       
5775                                                                                         
5776                 s390_lgr   (code, s390_r13, cfg->frame_reg);            
5777                 s390_aghi  (code, s390_r13, lmfOffset);                                 
5778                                                                                         
5779                 /*---------------------------------------------------------------*/
5780                 /* Preserve the parameter registers while we fix up the lmf      */
5781                 /*---------------------------------------------------------------*/
5782                 s390_stmg  (code, s390_r2, s390_r6, s390_r13,
5783                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5784
5785                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5786                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5787                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5788                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5789                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5790
5791                 /*---------------------------------------------------------------*/
5792                 /* On return from this call r2 have the address of the &lmf      */
5793                 /*---------------------------------------------------------------*/
5794                 if (lmf_addr_tls_offset == -1) {
5795                         mono_add_patch_info (cfg, code - cfg->native_code, 
5796                                              MONO_PATCH_INFO_INTERNAL_METHOD, 
5797                                              (gpointer)"mono_get_lmf_addr");
5798                         S390_CALL_TEMPLATE(code, s390_r1);
5799                 } else {
5800                         /*-------------------------------------------------------*/
5801                         /* Get LMF by getting value from thread level storage    */
5802                         /*-------------------------------------------------------*/
5803                         s390_ear (code, s390_r1, 0);
5804                         s390_sllg(code, s390_r1, s390_r1, 0, 32);
5805                         s390_ear (code, s390_r1, 1);
5806                         s390_lg  (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5807                 }
5808
5809                 /*---------------------------------------------------------------*/     
5810                 /* Set lmf.lmf_addr = jit_tls->lmf                               */     
5811                 /*---------------------------------------------------------------*/     
5812                 s390_stg   (code, s390_r2, 0, s390_r13,                                 
5813                             G_STRUCT_OFFSET(MonoLMF, lmf_addr));                        
5814                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5815                                                                                         
5816                 /*---------------------------------------------------------------*/     
5817                 /* Get current lmf                                               */     
5818                 /*---------------------------------------------------------------*/     
5819                 s390_lg    (code, s390_r0, 0, s390_r2, 0);                              
5820                                                                                         
5821                 /*---------------------------------------------------------------*/     
5822                 /* Set our lmf as the current lmf                                */     
5823                 /*---------------------------------------------------------------*/     
5824                 s390_stg   (code, s390_r13, 0, s390_r2, 0);                             
5825                                                                                         
5826                 /*---------------------------------------------------------------*/     
5827                 /* Have our lmf.previous_lmf point to the last lmf               */     
5828                 /*---------------------------------------------------------------*/     
5829                 s390_stg   (code, s390_r0, 0, s390_r13,                                 
5830                             G_STRUCT_OFFSET(MonoLMF, previous_lmf));                    
5831                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5832                                                                                         
5833                 /*---------------------------------------------------------------*/     
5834                 /* save method info                                              */     
5835                 /*---------------------------------------------------------------*/     
5836                 S390_SET   (code, s390_r1, method);
5837                 s390_stg   (code, s390_r1, 0, s390_r13,                                 
5838                             G_STRUCT_OFFSET(MonoLMF, method));                          
5839                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5840                                                                                 
5841                 /*---------------------------------------------------------------*/     
5842                 /* save the current IP                                           */     
5843                 /*---------------------------------------------------------------*/     
5844                 s390_stg   (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5845                 s390_basr  (code, s390_r1, 0);
5846                 s390_stg   (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); 
5847                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5848                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5849                                                                                         
5850                 /*---------------------------------------------------------------*/     
5851                 /* Save general and floating point registers                     */     
5852                 /*---------------------------------------------------------------*/     
5853                 s390_stmg  (code, s390_r2, s390_r12, s390_r13,                          
5854                             G_STRUCT_OFFSET(MonoLMF, gregs[2]));                        
5855                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5856                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5857                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5858                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5859                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5860                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5861                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5862                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5863                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5864                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5865                 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5866
5867                 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5868                 for (i = 0; i < 16; i++) {                                              
5869                         s390_std  (code, i, 0, s390_r13,                                
5870                                    G_STRUCT_OFFSET(MonoLMF, fregs[i]));                 
5871                         mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5872                         fpOffset += sizeof(double);
5873                 }                                                                       
5874
5875                 /*---------------------------------------------------------------*/
5876                 /* Restore the parameter registers now that we've set up the lmf */
5877                 /*---------------------------------------------------------------*/
5878                 s390_lmg   (code, s390_r2, s390_r6, s390_r13,                           
5879                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));                        
5880         }
5881
5882         if (cfg->method->save_lmf)
5883                 argsClobbered = TRUE;
5884
5885         if (tracing) {
5886                 argsClobbered = TRUE;
5887                 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5888         }
5889
5890         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5891                 argsClobbered = TRUE;
5892
5893         /*
5894          * Optimize the common case of the first bblock making a call with the same
5895          * arguments as the method. This works because the arguments are still in their
5896          * original argument registers.
5897          */
5898         if (!argsClobbered) {
5899                 MonoBasicBlock *first_bb = cfg->bb_entry;
5900                 MonoInst *next;
5901                 int filter = FILTER_IL_SEQ_POINT;
5902
5903                 next = mono_bb_first_inst (first_bb, filter);
5904                 if (!next && first_bb->next_bb) {
5905                         first_bb = first_bb->next_bb;
5906                         next = mono_bb_first_inst (first_bb, filter);
5907                 }
5908
5909                 if (first_bb->in_count > 1)
5910                         next = NULL;
5911
5912                 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5913                         ArgInfo *ainfo = cinfo->args + i;
5914                         gboolean match = FALSE;
5915
5916                         inst = cfg->args [i];
5917                         if (inst->opcode != OP_REGVAR) {
5918                                 switch (ainfo->regtype) {
5919                                 case RegTypeGeneral: {
5920                                         if (((next->opcode == OP_LOAD_MEMBASE) || 
5921                                              (next->opcode == OP_LOADI4_MEMBASE)) && 
5922                                              next->inst_basereg == inst->inst_basereg && 
5923                                              next->inst_offset == inst->inst_offset) {
5924                                                 if (next->dreg == ainfo->reg) {
5925                                                         NULLIFY_INS (next);
5926                                                         match = TRUE;
5927                                                 } else {
5928                                                         next->opcode = OP_MOVE;
5929                                                         next->sreg1 = ainfo->reg;
5930                                                         /* Only continue if the instruction doesn't change argument regs */
5931                                                         if (next->dreg == ainfo->reg)
5932                                                                 match = TRUE;
5933                                                 }
5934                                         }
5935                                         break;
5936                                 }
5937                                 default:
5938                                         break;
5939                                 }
5940                         } else {
5941                                 /* Argument allocated to (non-volatile) register */
5942                                 switch (ainfo->regtype) {
5943                                 case RegTypeGeneral:
5944                                         if (next->opcode == OP_MOVE && 
5945                                             next->sreg1 == inst->dreg && 
5946                                             next->dreg == ainfo->reg) {
5947                                                 NULLIFY_INS (next);
5948                                                 match = TRUE;
5949                                         }
5950                                         break;
5951                                 default:
5952                                         break;
5953                                 }
5954                         }
5955
5956                         if (match) {
5957                                 next = mono_inst_next (next, filter);
5958                                 if (!next)
5959                                         break;
5960                         }
5961                 }
5962         }
5963
5964         cfg->code_len = code - cfg->native_code;
5965         g_assert (cfg->code_len < cfg->code_size);
5966
5967         return code;
5968 }
5969
5970 /*========================= End of Function ========================*/
5971
5972 /*------------------------------------------------------------------*/
5973 /*                                                                  */
5974 /* Name         - mono_arch_emit_epilog                             */
5975 /*                                                                  */
5976 /* Function     - Emit the instructions for a function epilog.      */
5977 /*                                                                  */
5978 /*------------------------------------------------------------------*/
5979
5980 void
5981 mono_arch_emit_epilog (MonoCompile *cfg)
5982 {
5983         MonoMethod *method = cfg->method;
5984         int tracing = 0;
5985         guint8 *code;
5986         int max_epilog_size = 96;
5987         
5988         if (cfg->method->save_lmf)
5989                 max_epilog_size += 128;
5990         
5991         if (mono_jit_trace_calls != NULL)
5992                 max_epilog_size += 128;
5993         else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5994                 max_epilog_size += 128;
5995         
5996         while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
5997                 cfg->code_size  *= 2;
5998                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
5999                 cfg->stat_code_reallocs++;
6000         }
6001
6002         code = cfg->native_code + cfg->code_len;
6003
6004         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6005                 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6006                 tracing = 1;
6007         }
6008         
6009         if (method->save_lmf) 
6010                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6011
6012         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6013                 s390_lg  (code, STK_BASE, 0, STK_BASE, 0);
6014         } else
6015                 code = backUpStackPtr(cfg, code);
6016
6017         s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6018         s390_br  (code, s390_r14);
6019
6020         cfg->code_len = code - cfg->native_code;
6021
6022         g_assert (cfg->code_len < cfg->code_size);
6023
6024 }
6025
6026 /*========================= End of Function ========================*/
6027
6028 /*------------------------------------------------------------------*/
6029 /*                                                                  */
6030 /* Name         - mono_arch_emit_exceptions                         */
6031 /*                                                                  */
6032 /* Function     - Emit the blocks to handle exception conditions.   */
6033 /*                                                                  */
6034 /*------------------------------------------------------------------*/
6035
6036 void
6037 mono_arch_emit_exceptions (MonoCompile *cfg) 
6038 {
6039         MonoJumpInfo    *patch_info;
6040         guint8          *code;
6041         int             nThrows = 0,
6042                         exc_count = 0,
6043                         iExc;
6044         guint32         code_size;
6045         MonoClass       *exc_classes [MAX_EXC];
6046         guint8          *exc_throw_start [MAX_EXC];
6047
6048         for (patch_info = cfg->patch_info; 
6049              patch_info; 
6050              patch_info = patch_info->next) {
6051                 if (patch_info->type == MONO_PATCH_INFO_EXC)
6052                         exc_count++;
6053         }
6054
6055         code_size = exc_count * 48;
6056
6057         while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6058                 cfg->code_size  *= 2;
6059                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6060                 cfg->stat_code_reallocs++; 
6061         }
6062
6063         code = cfg->native_code + cfg->code_len;
6064
6065         /*---------------------------------------------------------------------*/
6066         /* Add code to raise exceptions                                        */
6067         /*---------------------------------------------------------------------*/
6068         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6069                 switch (patch_info->type) {
6070                 case MONO_PATCH_INFO_EXC: {
6071                         guint8 *ip = patch_info->ip.i + cfg->native_code;
6072                         MonoClass *exc_class;
6073                         guint64 throw_ip;
6074
6075                         /*-----------------------------------------------------*/
6076                         /* Patch the branch in epilog to come here             */
6077                         /*-----------------------------------------------------*/
6078                         s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6079
6080                         exc_class = mono_class_from_name (mono_defaults.corlib, 
6081                                                           "System", 
6082                                                           patch_info->data.name);
6083                         g_assert (exc_class);
6084                         throw_ip = patch_info->ip.i;
6085
6086                         for (iExc = 0; iExc < nThrows; ++iExc)
6087                                 if (exc_classes [iExc] == exc_class)
6088                                         break;
6089                 
6090                         if (iExc < nThrows) {
6091                                 s390_jcl (code, S390_CC_UN, 
6092                                           (guint64) exc_throw_start [iExc]);
6093                                 patch_info->type = MONO_PATCH_INFO_NONE;
6094                         } else {
6095         
6096                                 if (nThrows < MAX_EXC) {
6097                                         exc_classes [nThrows]     = exc_class;
6098                                         exc_throw_start [nThrows] = code;
6099                                 }
6100         
6101                                 /*---------------------------------------------*/
6102                                 /* Patch the parameter passed to the handler   */ 
6103                                 /*---------------------------------------------*/
6104                                 S390_SET  (code, s390_r2, exc_class->type_token);
6105                                 /*---------------------------------------------*/
6106                                 /* Load return address & parameter register    */
6107                                 /*---------------------------------------------*/
6108                                 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6109                                                            cfg->native_code + 8), code));
6110                                 /*---------------------------------------------*/
6111                                 /* Reuse the current patch to set the jump     */
6112                                 /*---------------------------------------------*/
6113                                 patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
6114                                 patch_info->data.name = "mono_arch_throw_corlib_exception";
6115                                 patch_info->ip.i      = code - cfg->native_code;
6116                                 S390_BR_TEMPLATE (code, s390_r1);
6117                         }
6118                         break;
6119                 }
6120                 default:
6121                         /* do nothing */
6122                         break;
6123                 }
6124         }
6125
6126         cfg->code_len = code - cfg->native_code;
6127
6128         g_assert (cfg->code_len < cfg->code_size);
6129
6130 }
6131
6132 /*========================= End of Function ========================*/
6133
6134 /*------------------------------------------------------------------*/
6135 /*                                                                  */
6136 /* Name         - mono_arch_finish_init                                 */
6137 /*                                                                  */
6138 /* Function     - Setup the JIT's Thread Level Specific Data.       */
6139 /*                                                                  */
6140 /*------------------------------------------------------------------*/
6141
6142 void
6143 mono_arch_finish_init (void)
6144 {
6145         appdomain_tls_offset = mono_domain_get_tls_offset();
6146         lmf_tls_offset = mono_get_lmf_tls_offset();
6147         lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6148 }
6149
6150 /*========================= End of Function ========================*/
6151
6152 /*------------------------------------------------------------------*/
6153 /*                                                                  */
6154 /* Name         - mono_arch_free_jit_tls_data                       */
6155 /*                                                                  */
6156 /* Function     - Free tls data.                                    */
6157 /*                                                                  */
6158 /*------------------------------------------------------------------*/
6159
6160 void
6161 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6162 {
6163 }
6164
6165 /*========================= End of Function ========================*/
6166
6167 /*------------------------------------------------------------------*/
6168 /*                                                                  */
6169 /* Name         - mono_arch_emit_inst_for_method                    */
6170 /*                                                                  */
6171 /*------------------------------------------------------------------*/
6172
6173 MonoInst*
6174 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6175 {
6176         return NULL;
6177 }
6178
6179 /*========================= End of Function ========================*/
6180
6181 /*------------------------------------------------------------------*/
6182 /*                                                                  */
6183 /* Name         - mono_arch_decompose_opts                          */
6184 /*                                                                  */
6185 /* Function     - Decompose opcode into a System z opcode.          */
6186 /*                                                                  */
6187 /*------------------------------------------------------------------*/
6188
6189 void
6190 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6191 {
6192         /* 
6193          * Have to rename these to avoid being decomposed normally, since the normal 
6194          * decomposition does not work on S390.
6195          */
6196         switch (ins->opcode) {
6197         case OP_ISUB_OVF:
6198                 ins->opcode = OP_S390_ISUB_OVF;
6199                 break;
6200         case OP_ISUB_OVF_UN:
6201                 ins->opcode = OP_S390_ISUB_OVF_UN;
6202                 break;
6203         case OP_IADD_OVF:
6204                 ins->opcode = OP_S390_IADD_OVF;
6205                 break;
6206         case OP_IADD_OVF_UN:
6207                 ins->opcode = OP_S390_IADD_OVF_UN;
6208                 break;
6209         case OP_LADD_OVF:
6210                 ins->opcode = OP_S390_LADD_OVF;
6211                 break;
6212         case OP_LADD_OVF_UN:
6213                 ins->opcode = OP_S390_LADD_OVF_UN;
6214                 break;
6215         case OP_LSUB_OVF:
6216                 ins->opcode = OP_S390_LSUB_OVF;
6217                 break;
6218         case OP_LSUB_OVF_UN:
6219                 ins->opcode = OP_S390_LSUB_OVF_UN;
6220                 break;
6221         default:
6222                 break;
6223         }
6224 }
6225
6226 /*========================= End of Function ========================*/
6227
6228 /*------------------------------------------------------------------*/
6229 /*                                                                  */
6230 /* Name         - mono_arch_print_tree                              */
6231 /*                                                                  */
6232 /* Function     - Print platform-specific opcode details.           */
6233 /*                                                                  */
6234 /* Returns      - 1 - opcode details have been printed              */
6235 /*                0 - opcode details have not been printed          */
6236 /*                                                                  */
6237 /*------------------------------------------------------------------*/
6238
6239 gboolean
6240 mono_arch_print_tree (MonoInst *tree, int arity)
6241 {
6242         gboolean done;
6243
6244         switch (tree->opcode) {
6245                 case OP_S390_LOADARG:
6246                 case OP_S390_ARGREG:
6247                 case OP_S390_ARGPTR:
6248                         printf ("[0x%lx(%s)]", tree->inst_offset, 
6249                                 mono_arch_regname (tree->inst_basereg));
6250                         done = 1;
6251                         break;
6252                 case OP_S390_STKARG:
6253                         printf ("[0x%lx(previous_frame)]", 
6254                                 tree->inst_offset); 
6255                         done = 1;
6256                         break;
6257                 case OP_S390_MOVE:
6258                         printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6259                                 tree->inst_offset, tree->backend.size,
6260                                 mono_arch_regname(tree->dreg), 
6261                                 tree->inst_imm, 
6262                                 mono_arch_regname(tree->sreg1));
6263                         done = 1;
6264                         break;
6265                 case OP_S390_SETF4RET:
6266                         printf ("[f%s,f%s]", 
6267                                 mono_arch_regname (tree->dreg),
6268                                 mono_arch_regname (tree->sreg1));
6269                         done = 1;
6270                         break;
6271                 case OP_TLS_GET:
6272                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6273                                 tree->inst_imm,
6274                                 mono_arch_regname (tree->sreg1));
6275                         done = 1;
6276                         break;
6277                 case OP_S390_BKCHAIN:
6278                         printf ("[previous_frame(%s)]", 
6279                                 mono_arch_regname (tree->sreg1));
6280                         done = 1;
6281                 default:
6282                         done = 0;
6283         }
6284         return (done);
6285 }
6286
6287 /*========================= End of Function ========================*/
6288
6289 /*------------------------------------------------------------------*/
6290 /*                                                                  */
6291 /* Name         - mono_arch_regalloc_cost                           */
6292 /*                                                                  */
6293 /* Function     - Determine the cost, in the number of memory       */
6294 /*                references, of the action of allocating the var-  */
6295 /*                iable VMV into a register during global register  */
6296 /*                allocation.                                       */
6297 /*                                                                  */
6298 /* Returns      - Cost                                              */
6299 /*                                                                  */
6300 /*------------------------------------------------------------------*/
6301
6302 guint32
6303 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6304 {
6305         /* FIXME: */
6306         return 2;
6307 }
6308
6309 /*========================= End of Function ========================*/
6310
6311 /*------------------------------------------------------------------*/
6312 /*                                                                  */
6313 /* Name         - mono_arch_flush_register_windows                  */
6314 /*                                                                  */
6315 /* Function     -                                                   */
6316 /*                                                                  */
6317 /* Returns      -                                                   */
6318 /*                                                                  */
6319 /*------------------------------------------------------------------*/
6320
6321 void 
6322 mono_arch_flush_register_windows (void)
6323 {
6324 }
6325
6326 /*========================= End of Function ========================*/
6327
6328 /*------------------------------------------------------------------*/
6329 /*                                                                  */
6330 /* Name         - mono_arch_is_inst_imm                             */
6331 /*                                                                  */
6332 /* Function     - Determine if operand qualifies as an immediate    */
6333 /*                value. For s390 this is a value -32768-32768      */
6334 /*                                                                  */
6335 /* Returns      - True|False - is [not] immediate value.            */
6336 /*                                                                  */
6337 /*------------------------------------------------------------------*/
6338
6339 gboolean 
6340 mono_arch_is_inst_imm (gint64 imm)
6341 {
6342         return s390_is_imm32 (imm);
6343 }
6344
6345 /*========================= End of Function ========================*/
6346
6347 /*------------------------------------------------------------------*/
6348 /*                                                                  */
6349 /* Name         - mono_arch_get_patch_offset                        */
6350 /*                                                                  */
6351 /* Function     - Dummy entry point until s390x supports aot.       */
6352 /*                                                                  */
6353 /* Returns      - Offset for patch.                                 */
6354 /*                                                                  */
6355 /*------------------------------------------------------------------*/
6356
6357 guint32
6358 mono_arch_get_patch_offset (guint8 *code)
6359 {
6360         return 0;
6361 }
6362
6363 /*========================= End of Function ========================*/
6364
6365 /*------------------------------------------------------------------*/
6366 /*                                                                  */
6367 /* Name         - mono_arch_context_get_int_reg.                    */
6368 /*                                                                  */
6369 /* Function     -                                                   */
6370 /*                                                                  */
6371 /* Returns      - Return a register from the context.               */
6372 /*                                                                  */
6373 /*------------------------------------------------------------------*/
6374
6375 mgreg_t
6376 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6377 {
6378         return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6379 }
6380
6381 /*========================= End of Function ========================*/
6382
6383 /*------------------------------------------------------------------*/
6384 /*                                                                  */
6385 /* Name         - mono_arch_context_set_int_reg.                    */
6386 /*                                                                  */
6387 /* Function     - Set a value in a specified register.              */
6388 /*                                                                  */
6389 /*------------------------------------------------------------------*/
6390
6391 void
6392 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6393 {
6394         ctx->uc_mcontext.gregs[reg] = val;
6395 }
6396
6397 /*========================= End of Function ========================*/
6398
6399 /*------------------------------------------------------------------*/
6400 /*                                                                  */
6401 /* Name         - mono_arch_get_this_arg_from_call.                 */
6402 /*                                                                  */
6403 /* Function     -                                                   */
6404 /*                                                                  */
6405 /*------------------------------------------------------------------*/
6406
6407 gpointer
6408 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6409 {
6410         return (gpointer) regs [s390_r2];
6411 }
6412
6413 /*========================= End of Function ========================*/
6414  
6415 /*------------------------------------------------------------------*/
6416 /*                                                                  */
6417 /* Name         - mono_arch_install_handler_block_guard             */
6418 /*                                                                  */
6419 /* Function     -                                                   */
6420 /*                                                                  */
6421 /*------------------------------------------------------------------*/
6422
6423 gpointer
6424 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause, 
6425                                        MonoContext *ctx, gpointer new_value)
6426 {
6427         int offset;
6428         gpointer *sp, old_value;
6429         char *bp;
6430
6431         offset = clause->exvar_offset;
6432
6433         /*Load the spvar*/
6434         bp = MONO_CONTEXT_GET_BP (ctx);
6435         sp = *(gpointer*)(bp + offset);
6436
6437         old_value = *sp;
6438         if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6439                 return old_value;
6440
6441         *sp = new_value;
6442
6443         return old_value;
6444 }
6445
6446 /*========================= End of Function ========================*/
6447  
6448 /*------------------------------------------------------------------*/
6449 /*                                                                  */
6450 /* Name         - get_delegate_invoke_impl.                         */
6451 /*                                                                  */
6452 /* Function     -                                                   */
6453 /*                                                                  */
6454 /*------------------------------------------------------------------*/
6455
6456 static gpointer
6457 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6458 {
6459         guint8 *code, *start;
6460
6461         if (has_target) {
6462                 int size = 32;
6463
6464                 start = code = mono_global_codeman_reserve (size);
6465
6466                 /* Replace the this argument with the target */
6467                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6468                 s390_lg   (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6469                 s390_br   (code, s390_r1);
6470                 g_assert ((code - start) <= size);
6471
6472                 mono_arch_flush_icache (start, size);
6473         } else {
6474                 int size, i;
6475
6476                 size = 32 + param_count * 8;
6477                 start = code = mono_global_codeman_reserve (size);
6478
6479                 s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6480                 /* slide down the arguments */
6481                 for (i = 0; i < param_count; ++i) {
6482                         s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6483                 }
6484                 s390_br   (code, s390_r1);
6485
6486                 g_assert ((code - start) <= size);
6487
6488                 mono_arch_flush_icache (start, size);
6489         }
6490
6491         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6492
6493         if (has_target) {
6494                 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6495         } else {
6496                 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6497                 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6498                 g_free (name);
6499         }
6500
6501         return start;
6502 }
6503
6504 /*========================= End of Function ========================*/
6505
6506 /*------------------------------------------------------------------*/
6507 /*                                                                  */
6508 /* Name         - mono_arch_get_delegate_invoke_impls.              */
6509 /*                                                                  */
6510 /* Function     -                                                   */
6511 /*                                                                  */
6512 /*------------------------------------------------------------------*/
6513
6514 GSList*
6515 mono_arch_get_delegate_invoke_impls (void)
6516 {
6517         GSList *res = NULL;
6518         MonoTrampInfo *info;
6519         int i;
6520
6521         get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6522         res = g_slist_prepend (res, info);
6523
6524         for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6525                 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6526                 res = g_slist_prepend (res, info);
6527         }
6528
6529         return res;
6530 }
6531
6532 /*========================= End of Function ========================*/
6533
6534 /*------------------------------------------------------------------*/
6535 /*                                                                  */
6536 /* Name         - mono_arch_get_delegate_invoke_impl.               */
6537 /*                                                                  */
6538 /* Function     -                                                   */
6539 /*                                                                  */
6540 /*------------------------------------------------------------------*/
6541
6542 gpointer
6543 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6544 {
6545         guint8 *code, *start;
6546
6547         /* FIXME: Support more cases */
6548         if (MONO_TYPE_ISSTRUCT (sig->ret))
6549                 return NULL;
6550
6551         if (has_target) {
6552                 static guint8* cached = NULL;
6553
6554                 if (cached)
6555                         return cached;
6556
6557                 if (mono_aot_only) {
6558                         start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6559                 } else {
6560                         MonoTrampInfo *info;
6561                         start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6562                         mono_tramp_info_register (info, NULL);
6563                 }
6564
6565                 mono_memory_barrier ();
6566
6567                 cached = start;
6568         } else {
6569                 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6570                 int i;
6571
6572                 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6573                         return NULL;
6574                 for (i = 0; i < sig->param_count; ++i)
6575                         if (!mono_is_regsize_var (sig->params [i]))
6576                                 return NULL;
6577
6578
6579                 code = cache [sig->param_count];
6580                 if (code)
6581                         return code;
6582
6583                 if (mono_aot_only) {
6584                         char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6585                         start = mono_aot_get_trampoline (name);
6586                         g_free (name);
6587                 } else {
6588                         MonoTrampInfo *info;
6589                         start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6590                         mono_tramp_info_register (info, NULL);
6591                 }
6592
6593                 mono_memory_barrier ();
6594
6595                 cache [sig->param_count] = start;
6596         }
6597         return start;
6598 }
6599
6600 /*========================= End of Function ========================*/
6601
6602 /*------------------------------------------------------------------*/
6603 /*                                                                  */
6604 /* Name         - mono_arch_get_delegate_virtual_invoke_impl.       */
6605 /*                                                                  */
6606 /* Function     -                                                   */
6607 /*                                                                  */
6608 /*------------------------------------------------------------------*/
6609
6610 gpointer
6611 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, 
6612                                             int offset, gboolean load_imt_reg)
6613 {
6614         guint8 *code, *start;
6615         int size = 40;
6616
6617         start = code = mono_global_codeman_reserve (size);
6618
6619         /*
6620         * Replace the "this" argument with the target
6621         */
6622         s390_lgr  (code, s390_r1, s390_r2);
6623         s390_lg   (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));        
6624
6625         /*
6626         * Load the IMT register, if needed
6627         */
6628         if (load_imt_reg) {
6629                 s390_lg  (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6630         }
6631
6632         /*
6633         * Load the vTable
6634         */
6635         s390_lg  (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6636         if (offset != 0) {
6637                 s390_agfi(code, s390_r1, offset);
6638         }
6639         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6640         s390_br  (code, s390_r1);
6641
6642         return(start);
6643 }
6644
6645 /*========================= End of Function ========================*/
6646
6647 /*------------------------------------------------------------------*/
6648 /*                                                                  */
6649 /* Name         - mono_arch_build_imt_thunk.                        */
6650 /*                                                                  */
6651 /* Function     -                                                   */
6652 /*                                                                  */
6653 /*------------------------------------------------------------------*/
6654
6655 gpointer
6656 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain, 
6657                            MonoIMTCheckItem **imt_entries, int count,
6658                            gpointer fail_tramp)
6659 {
6660         int i;
6661         int size = 0;
6662         guchar *code, *start;
6663         char trampName[64];
6664
6665         for (i = 0; i < count; ++i) {
6666                 MonoIMTCheckItem *item = imt_entries [i];
6667                 if (item->is_equals) {
6668                         if (item->check_target_idx) {
6669                                 if (!item->compare_done)
6670                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6671                                 if (item->has_target_code)
6672                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6673                                 else
6674                                         item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE + 
6675                                                             LOAD_SIZE;
6676                         } else {
6677                                 if (fail_tramp) {
6678                                         item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE + 
6679                                                             2 * LOADCON_SIZE;
6680                                         if (!item->has_target_code)
6681                                                 item->chunk_size += LOAD_SIZE;
6682                                 } else {
6683                                         item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6684 #if ENABLE_WRONG_METHOD_CHECK
6685                                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6686 #endif
6687                                 }
6688                         }
6689                 } else {
6690                         item->chunk_size += CMP_SIZE + JUMP_SIZE;
6691                         imt_entries [item->check_target_idx]->compare_done = TRUE;
6692                 }
6693                 size += item->chunk_size;
6694         }
6695
6696         if (fail_tramp)
6697                 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6698         else
6699                 code = mono_domain_code_reserve (domain, size);
6700
6701         start = code;
6702
6703         for (i = 0; i < count; ++i) {
6704                 MonoIMTCheckItem *item = imt_entries [i];
6705                 item->code_target = (guint8 *) code;
6706                 if (item->is_equals) {
6707                         if (item->check_target_idx) {
6708                                 if (!item->compare_done) {
6709                                         S390_SET  (code, s390_r0, item->key);
6710                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6711                                 }
6712                                 item->jmp_code = (guint8*) code;
6713                                 s390_jcl (code, S390_CC_NE, 0);
6714                                 
6715                                 if (item->has_target_code) {
6716                                         S390_SET (code, s390_r1, item->value.target_code);
6717                                 } else {
6718                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6719                                         s390_lg  (code, s390_r1, 0, s390_r1, 0);
6720                                 }
6721                                 s390_br   (code, s390_r1);
6722                         } else {
6723                                 if (fail_tramp) {
6724                                         gint64  target;
6725
6726                                         S390_SET  (code, s390_r0, item->key);
6727                                         s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
6728                                         item->jmp_code = (guint8*) code;
6729                                         s390_jcl  (code, S390_CC_NE, 0);
6730                                         if (item->has_target_code) {
6731                                                 S390_SET (code, s390_r1, item->value.target_code);
6732                                         } else {
6733                                                 g_assert (vtable);
6734                                                 S390_SET  (code, s390_r1, 
6735                                                            (&(vtable->vtable [item->value.vtable_slot])));
6736                                                 s390_lg   (code, s390_r1, 0, s390_r1, 0);
6737                                         }
6738                                         s390_br   (code, s390_r1);
6739                                         target = (gint64) S390_RELATIVE(code, item->jmp_code);
6740                                         s390_patch_rel(item->jmp_code+2, target);
6741                                         S390_SET  (code, s390_r1, fail_tramp);
6742                                         s390_br   (code, s390_r1);
6743                                         item->jmp_code = NULL;
6744                                 } else {
6745                                 /* enable the commented code to assert on wrong method */
6746 #if ENABLE_WRONG_METHOD_CHECK
6747                                         g_assert_not_reached ();
6748 #endif
6749                                         S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6750                                         s390_lg   (code, s390_r1, 0, s390_r1, 0);
6751                                         s390_br   (code, s390_r1);
6752                                 }
6753                         }
6754                 } else {
6755                         S390_SET  (code, s390_r0, item->key);
6756                         s390_cgr  (code, MONO_ARCH_IMT_REG, s390_r0);
6757                         item->jmp_code = (guint8 *) code;
6758                         s390_jcl  (code, S390_CC_GE, 0);
6759                 }
6760         }
6761         /* 
6762          * patch the branches to get to the target items 
6763          */
6764         for (i = 0; i < count; ++i) {
6765                 MonoIMTCheckItem *item = imt_entries [i];
6766                 if (item->jmp_code) {
6767                         if (item->check_target_idx) {
6768                                 gint64 offset;
6769                                 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6770                                                        item->jmp_code);
6771                                 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6772                         }
6773                 }
6774         }
6775
6776         mono_arch_flush_icache ((guint8*)start, (code - start));
6777         mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6778
6779         if (!fail_tramp) 
6780                 mono_stats.imt_thunks_size += (code - start);
6781
6782         g_assert (code - start <= size);
6783
6784         snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6785         mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6786
6787         return (start);
6788 }
6789
6790 /*========================= End of Function ========================*/
6791
6792 /*------------------------------------------------------------------*/
6793 /*                                                                  */
6794 /* Name         - mono_arch_find_imt_method.                        */
6795 /*                                                                  */
6796 /* Function     - Get the method address from MONO_ARCH_IMT_REG     */
6797 /*                found in the save area.                           */
6798 /*                                                                  */
6799 /*------------------------------------------------------------------*/
6800
6801 MonoMethod*
6802 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6803 {
6804         return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6805 }
6806
6807 /*========================= End of Function ========================*/
6808
6809 /*------------------------------------------------------------------*/
6810 /*                                                                  */
6811 /* Name         - mono_arch_find_static_call_vtable                 */
6812 /*                                                                  */
6813 /* Function     - Find the static call vtable.                      */
6814 /*                                                                  */
6815 /*------------------------------------------------------------------*/
6816
6817 MonoVTable*
6818 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6819 {
6820         mgreg_t *r = (mgreg_t*)regs;
6821
6822         return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6823 }
6824
6825 /*========================= End of Function ========================*/
6826
6827 /*------------------------------------------------------------------*/
6828 /*                                                                  */
6829 /* Name         - mono_arch_get_cie_program                         */
6830 /*                                                                  */
6831 /* Function     - Find the static call vtable.                      */
6832 /*                                                                  */
6833 /*------------------------------------------------------------------*/
6834
6835 GSList*
6836 mono_arch_get_cie_program (void)
6837 {
6838         GSList *l = NULL;
6839
6840         mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6841
6842         return(l);
6843 }
6844
6845 /*========================= End of Function ========================*/
6846
6847 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6848
6849 /*------------------------------------------------------------------*/
6850 /*                                                                  */
6851 /* Name         - mono_arch_set_breakpoint.                         */
6852 /*                                                                  */
6853 /* Function     - Set a breakpoint at the native code corresponding */
6854 /*                to JI at NATIVE_OFFSET.  The location should      */
6855 /*                contain code emitted by OP_SEQ_POINT.             */
6856 /*                                                                  */
6857 /*------------------------------------------------------------------*/
6858
6859 void
6860 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6861 {
6862         guint8 *code = ip;
6863
6864         breakpointCode.pTrigger = bp_trigger_page;
6865         memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6866         code += BREAKPOINT_SIZE;
6867 }
6868
6869 /*========================= End of Function ========================*/
6870
6871 /*------------------------------------------------------------------*/
6872 /*                                                                  */
6873 /* Name         - mono_arch_clear_breakpoint.                       */
6874 /*                                                                  */
6875 /* Function     - Clear the breakpoint at IP.                       */
6876 /*                                                                  */
6877 /*------------------------------------------------------------------*/
6878
6879 void
6880 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6881 {
6882         guint8 *code = ip;
6883         int i;
6884
6885         for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6886                 s390_nop(code);
6887 }
6888
6889 /*========================= End of Function ========================*/
6890
6891 /*------------------------------------------------------------------*/
6892 /*                                                                  */
6893 /* Name         - mono_arch_is_breakpoint_event.                    */
6894 /*                                                                  */
6895 /* Function     -                                                   */
6896 /*                                                                  */
6897 /*------------------------------------------------------------------*/
6898
6899 gboolean
6900 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6901 {
6902         siginfo_t* sinfo = (siginfo_t*) info;
6903
6904         /* 
6905          * Sometimes the address is off by 4 
6906          */
6907         if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6908                 return TRUE;
6909         else
6910                 return FALSE;
6911 }
6912
6913 /*========================= End of Function ========================*/
6914
6915 /*------------------------------------------------------------------*/
6916 /*                                                                  */
6917 /* Name         - mono_arch_skip_breakpoint.                        */
6918 /*                                                                  */
6919 /* Function     - Modify the CTX so the IP is placed after the      */
6920 /*                breakpoint instruction, so when we resume, the    */
6921 /*                instruction is not executed again.                */
6922 /*                                                                  */
6923 /*------------------------------------------------------------------*/
6924
6925 void
6926 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6927 {
6928         MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6929 }
6930
6931 /*========================= End of Function ========================*/
6932         
6933 /*------------------------------------------------------------------*/
6934 /*                                                                  */
6935 /* Name         - mono_arch_start_single_stepping.                  */
6936 /*                                                                  */
6937 /* Function     - Start single stepping.                            */
6938 /*                                                                  */
6939 /*------------------------------------------------------------------*/
6940
6941 void
6942 mono_arch_start_single_stepping (void)
6943 {
6944         mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6945 }
6946
6947 /*========================= End of Function ========================*/
6948         
6949 /*------------------------------------------------------------------*/
6950 /*                                                                  */
6951 /* Name         - mono_arch_stop_single_stepping.                   */
6952 /*                                                                  */
6953 /* Function     - Stop single stepping.                             */
6954 /*                                                                  */
6955 /*------------------------------------------------------------------*/
6956
6957 void
6958 mono_arch_stop_single_stepping (void)
6959 {
6960         mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6961 }
6962
6963 /*========================= End of Function ========================*/
6964
6965 /*------------------------------------------------------------------*/
6966 /*                                                                  */
6967 /* Name         - mono_arch_is_single_step_event.                   */
6968 /*                                                                  */
6969 /* Function     - Return whether the machine state in sigctx cor-   */
6970 /*                responds to a single step event.                  */
6971 /*                                                                  */
6972 /*------------------------------------------------------------------*/
6973
6974 gboolean
6975 mono_arch_is_single_step_event (void *info, void *sigctx)
6976 {
6977         siginfo_t* sinfo = (siginfo_t*) info;
6978
6979         /* 
6980          * Sometimes the address is off by 4 
6981          */
6982         if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6983                 return TRUE;
6984         else
6985                 return FALSE;
6986 }
6987
6988 /*========================= End of Function ========================*/
6989
6990 /*------------------------------------------------------------------*/
6991 /*                                                                  */
6992 /* Name         - mono_arch_skip_single_step.                       */
6993 /*                                                                  */
6994 /* Function     - Modify the ctx so the IP is placed after the      */
6995 /*                single step trigger instruction, so that the      */
6996 /*                instruction is not executed again.                */
6997 /*                                                                  */
6998 /*------------------------------------------------------------------*/
6999
7000 void
7001 mono_arch_skip_single_step (MonoContext *ctx)
7002 {
7003         MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7004 }
7005
7006 /*========================= End of Function ========================*/
7007
7008 /*------------------------------------------------------------------*/
7009 /*                                                                  */
7010 /* Name         - mono_arch_create_seq_point_info.                  */
7011 /*                                                                  */
7012 /* Function     - Return a pointer to a data struction which is     */
7013 /*                used by the sequence point implementation in      */
7014 /*                AOTed code.                                       */
7015 /*                                                                  */
7016 /*------------------------------------------------------------------*/
7017
7018 gpointer
7019 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7020 {
7021         NOT_IMPLEMENTED;
7022         return NULL;
7023 }
7024
7025 /*========================= End of Function ========================*/
7026
7027 /*------------------------------------------------------------------*/
7028 /*                                                                  */
7029 /* Name         - mono_arch_init_lmf_ext.                           */
7030 /*                                                                  */
7031 /* Function -                                                       */
7032 /*                                                                  */
7033 /*------------------------------------------------------------------*/
7034
7035 void
7036 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7037 {
7038         ext->lmf.previous_lmf = prev_lmf;
7039         /* Mark that this is a MonoLMFExt */
7040         ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7041         ext->lmf.ebp = (gssize)ext;
7042 }
7043
7044 /*========================= End of Function ========================*/
7045
7046 #endif
7047
7048 /*------------------------------------------------------------------*/
7049 /*                                                                  */
7050 /* Name     - mono_arch_cpu_enumerate_simd_versions.                */
7051 /*                                                                  */
7052 /* Function - If this CPU supports vector operations then it        */
7053 /*            supports the equivalent of SSE1-4.                    */
7054 /*                                                                  */
7055 /*------------------------------------------------------------------*/
7056
7057 guint32
7058 mono_arch_cpu_enumerate_simd_versions (void)
7059 {
7060         guint32 sseOpts = 0;
7061
7062         if (facs.vec != 0) 
7063                 sseOpts = (SIMD_VERSION_SSE1  | SIMD_VERSION_SSE2 |
7064                            SIMD_VERSION_SSE3  | SIMD_VERSION_SSSE3 |
7065                            SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7066                            SIMD_VERSION_SSE4a);
7067
7068         return (sseOpts);
7069 }
7070
7071 /*========================= End of Function ========================*/
7072
7073 /*------------------------------------------------------------------*/
7074 /*                                                                  */
7075 /* Name     - mono_arch_opcode_supported.                           */
7076 /*                                                                  */
7077 /* Function - Check if a given return code is supported.            */
7078 /*                                                                  */
7079 /*------------------------------------------------------------------*/
7080
7081 gboolean
7082 mono_arch_opcode_supported (int opcode)
7083 {
7084         switch (opcode) {
7085         case OP_ATOMIC_ADD_I4:
7086         case OP_ATOMIC_ADD_I8:
7087         case OP_ATOMIC_EXCHANGE_I4:
7088         case OP_ATOMIC_EXCHANGE_I8:
7089                 return TRUE;
7090         default:
7091                 return FALSE;
7092         }
7093 }
7094
7095 /*========================= End of Function ========================*/