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