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