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