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