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