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