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