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