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