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