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