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