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