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