merge 99630:99762
[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                 sz->stack_size += sizeof(gpointer);
1262                 sz->offStruct  += sizeof(gpointer);
1263         } else {
1264                 ainfo->reg      = *gr;
1265         }
1266         (*gr) ++;
1267         ainfo->offset   = sz->stack_size;
1268         ainfo->offparm  = sz->offset;
1269         sz->offset      = S390_ALIGN(sz->offset+size, sizeof(long));
1270         ainfo->size     = size;
1271         ainfo->regtype  = RegTypeStructByAddr; 
1272         ainfo->vtsize   = size;
1273         sz->parm_size  += size;
1274 }
1275
1276 /*========================= End of Function ========================*/
1277
1278 /*------------------------------------------------------------------*/
1279 /*                                                                  */
1280 /* Name         - add_float                                         */
1281 /*                                                                  */
1282 /* Function     - Determine code and stack size incremements for a  */
1283 /*                float parameter.                                  */
1284 /*                                                                  */
1285 /*------------------------------------------------------------------*/
1286
1287 static void inline
1288 add_float (guint *fr,  size_data *sz, ArgInfo *ainfo)
1289 {
1290         if ((*fr) <= S390_LAST_FPARG_REG) {
1291                 ainfo->regtype = RegTypeFP;
1292                 ainfo->reg     = *fr;
1293                 sz->code_size += 4;
1294                 (*fr) += 2;
1295         }
1296         else {
1297                 ainfo->offset   = sz->stack_size;
1298                 ainfo->reg      = STK_BASE;
1299                 ainfo->regtype  = RegTypeBase;
1300                 sz->code_size  += 4;
1301                 sz->stack_size += sizeof(double);
1302                 sz->local_size += sizeof(double);
1303                 sz->offStruct  += sizeof(double);
1304         }
1305 }
1306
1307 /*========================= End of Function ========================*/
1308
1309 /*------------------------------------------------------------------*/
1310 /*                                                                  */
1311 /* Name         - get_call_info                                   */
1312 /*                                                                  */
1313 /* Function     - Determine the amount of space required for code   */
1314 /*                and stack. In addition determine starting points  */
1315 /*                for stack-based parameters, and area for struct-  */
1316 /*                ures being returned on the stack.                 */
1317 /*                                                                  */
1318 /*------------------------------------------------------------------*/
1319
1320 static CallInfo *
1321 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig, gboolean is_pinvoke)
1322 {
1323         guint i, fr, gr, size;
1324         int nParm = sig->hasthis + sig->param_count;
1325         MonoType *ret_type;
1326         guint32 simpletype, align;
1327         CallInfo *cinfo;
1328         size_data *sz;
1329         MonoGenericSharingContext *gsctx = cfg ? cfg->generic_sharing_context : NULL;
1330
1331         if (mp)
1332                 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1333         else
1334                 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1335
1336         fr                = 0;
1337         gr                = s390_r2;
1338         nParm             = 0;
1339         cinfo->struct_ret = 0;
1340         sz                = &cinfo->sz;
1341         sz->retStruct     = 0;
1342         sz->offset        = 0;
1343         sz->offStruct     = S390_MINIMAL_STACK_SIZE;
1344         sz->stack_size    = S390_MINIMAL_STACK_SIZE;
1345         sz->code_size     = 0;
1346         sz->parm_size     = 0;
1347         sz->local_size    = 0;
1348
1349         /*----------------------------------------------------------*/
1350         /* We determine the size of the return code/stack in case we*/
1351         /* need to reserve a register to be used to address a stack */
1352         /* area that the callee will use.                           */
1353         /*----------------------------------------------------------*/
1354
1355         ret_type = mono_type_get_underlying_type (sig->ret);
1356         ret_type = mini_get_basic_type_from_generic (gsctx, ret_type);
1357         simpletype = ret_type->type;
1358 enum_retvalue:
1359         switch (simpletype) {
1360                 case MONO_TYPE_BOOLEAN:
1361                 case MONO_TYPE_I1:
1362                 case MONO_TYPE_U1:
1363                 case MONO_TYPE_I2:
1364                 case MONO_TYPE_U2:
1365                 case MONO_TYPE_CHAR:
1366                 case MONO_TYPE_I4:
1367                 case MONO_TYPE_U4:
1368                 case MONO_TYPE_I:
1369                 case MONO_TYPE_U:
1370                 case MONO_TYPE_CLASS:
1371                 case MONO_TYPE_OBJECT:
1372                 case MONO_TYPE_SZARRAY:
1373                 case MONO_TYPE_ARRAY:
1374                 case MONO_TYPE_PTR:
1375                 case MONO_TYPE_FNPTR:
1376                 case MONO_TYPE_STRING:
1377                         cinfo->ret.reg = s390_r2;
1378                         sz->code_size += 4;
1379                         break;
1380                 case MONO_TYPE_R4:
1381                 case MONO_TYPE_R8:
1382                         cinfo->ret.reg = s390_f0;
1383                         sz->code_size += 4;
1384                         break;
1385                 case MONO_TYPE_I8:
1386                 case MONO_TYPE_U8:
1387                         cinfo->ret.reg = s390_r2;
1388                         sz->code_size += 4;
1389                         break;
1390                 case MONO_TYPE_GENERICINST:
1391                         if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1392                                 cinfo->ret.reg = s390_r2;
1393                                 sz->code_size += 4;
1394                                 break;
1395                         }
1396                         /* Fall through */
1397                 case MONO_TYPE_VALUETYPE: {
1398                         MonoClass *klass = mono_class_from_mono_type (sig->ret);
1399                         if (klass->enumtype) {
1400                                 simpletype = klass->enum_basetype->type;
1401                                 goto enum_retvalue;
1402                         }
1403                         if (sig->pinvoke)
1404                                 size = mono_class_native_size (klass, &align);
1405                         else
1406                                 size = mono_class_value_size (klass, &align);
1407         
1408                         cinfo->ret.reg    = s390_r2;
1409                         cinfo->struct_ret = 1;
1410                         cinfo->ret.size   = size;
1411                         cinfo->ret.vtsize = size;
1412                         gr++;
1413                         break;
1414                 }
1415                 case MONO_TYPE_TYPEDBYREF:
1416                         size = sizeof (MonoTypedRef);
1417                         cinfo->ret.reg    = s390_r2;
1418                         cinfo->struct_ret = 1;
1419                         cinfo->ret.size   = size;
1420                         cinfo->ret.vtsize = size;
1421                         gr++;
1422                         break;
1423                 case MONO_TYPE_VOID:
1424                         break;
1425                 default:
1426                         g_error ("Can't handle as return value 0x%x", sig->ret->type);
1427         }
1428
1429         if (sig->hasthis) {
1430                 cinfo->args[nParm].size = sizeof(gpointer);
1431                 add_general (&gr, sz, cinfo->args+nParm);
1432                 nParm++;
1433         }
1434
1435         /*----------------------------------------------------------*/
1436         /* We determine the size of the parameter code and stack    */
1437         /* requirements by checking the types and sizes of the      */
1438         /* parameters.                                              */
1439         /*----------------------------------------------------------*/
1440
1441         for (i = 0; i < sig->param_count; ++i) {
1442                 MonoType *ptype;
1443
1444                 /*--------------------------------------------------*/
1445                 /* Handle vararg type calls. All args are put on    */
1446                 /* the stack.                                       */
1447                 /*--------------------------------------------------*/
1448                 if ((sig->call_convention == MONO_CALL_VARARG) &&
1449                     (i == sig->sentinelpos)) {
1450                         gr = S390_LAST_ARG_REG + 1;
1451                         add_general (&gr, sz, &cinfo->sigCookie);
1452                 }
1453
1454                 if (sig->params [i]->byref) {
1455                         add_general (&gr, sz, cinfo->args+nParm);
1456                         cinfo->args[nParm].size = sizeof(gpointer);
1457                         nParm++;
1458                         continue;
1459                 }
1460
1461                 ptype = mono_type_get_underlying_type (sig->params [i]);
1462                 ptype = mini_get_basic_type_from_generic (gsctx, ptype);
1463                 simpletype = ptype->type;
1464                 cinfo->args[nParm].type = simpletype;
1465                 switch (simpletype) {
1466                 case MONO_TYPE_BOOLEAN:
1467                 case MONO_TYPE_I1:
1468                 case MONO_TYPE_U1:
1469                         cinfo->args[nParm].size = sizeof(char);
1470                         add_general (&gr, sz, cinfo->args+nParm);
1471                         nParm++;
1472                         break;
1473                 case MONO_TYPE_I2:
1474                 case MONO_TYPE_U2:
1475                 case MONO_TYPE_CHAR:
1476                         cinfo->args[nParm].size = sizeof(short);
1477                         add_general (&gr, sz, cinfo->args+nParm);
1478                         nParm++;
1479                         break;
1480                 case MONO_TYPE_I4:
1481                 case MONO_TYPE_U4:
1482                         cinfo->args[nParm].size = sizeof(int);
1483                         add_general (&gr, sz, cinfo->args+nParm);
1484                         nParm++;
1485                         break;
1486                 case MONO_TYPE_I:
1487                 case MONO_TYPE_U:
1488                 case MONO_TYPE_PTR:
1489                 case MONO_TYPE_FNPTR:
1490                 case MONO_TYPE_CLASS:
1491                 case MONO_TYPE_OBJECT:
1492                 case MONO_TYPE_STRING:
1493                 case MONO_TYPE_SZARRAY:
1494                 case MONO_TYPE_ARRAY:
1495                         cinfo->args[nParm].size = sizeof(gpointer);
1496                         add_general (&gr, sz, cinfo->args+nParm);
1497                         nParm++;
1498                         break;
1499                 case MONO_TYPE_I8:
1500                 case MONO_TYPE_U8:
1501                         cinfo->args[nParm].size = sizeof(long long);
1502                         add_general (&gr, sz, cinfo->args+nParm);
1503                         nParm++;
1504                         break;
1505                 case MONO_TYPE_R4:
1506                         cinfo->args[nParm].size = sizeof(float);
1507                         add_float (&fr, sz, cinfo->args+nParm);
1508                         nParm++;
1509                         break;
1510                 case MONO_TYPE_R8:
1511                         cinfo->args[nParm].size = sizeof(double);
1512                         add_float (&fr, sz, cinfo->args+nParm);
1513                         nParm++;
1514                         break;
1515                 case MONO_TYPE_GENERICINST:
1516                         if (!mono_type_generic_inst_is_valuetype (sig->params [i])) {
1517                                 cinfo->args[nParm].size = sizeof(gpointer);
1518                                 add_general (&gr, sz, cinfo->args+nParm);
1519                                 nParm++;
1520                                 break;
1521                         }
1522                         /* Fall through */
1523                 case MONO_TYPE_VALUETYPE: {
1524                         MonoMarshalType *info;
1525                         MonoClass *klass = mono_class_from_mono_type (sig->params [i]);
1526                         if (sig->pinvoke)
1527                                 size = mono_class_native_size (klass, &align);
1528                         else
1529                                 size = mono_class_value_size (klass, &align);
1530         
1531                         info = mono_marshal_load_type_info (klass);
1532
1533                         if ((info->native_size == sizeof(float)) &&
1534                             (info->num_fields  == 1) &&
1535                             (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1536                                 cinfo->args[nParm].size = sizeof(float);
1537                                 add_float(&fr, sz, cinfo->args+nParm);
1538                                 break;
1539                         }
1540
1541                         if ((info->native_size == sizeof(double)) &&
1542                             (info->num_fields  == 1) &&
1543                             (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1544                                 cinfo->args[nParm].size = sizeof(double);
1545                                 add_float(&fr, sz, cinfo->args+nParm);
1546                                 break;
1547                         }
1548
1549                         cinfo->args[nParm].vtsize  = 0;
1550                         cinfo->args[nParm].size    = 0;
1551
1552                         switch (size) {
1553                                 /*----------------------------------*/
1554                                 /* On S/390, structures of size 1,  */
1555                                 /* 2, 4, and 8 bytes are passed in  */
1556                                 /* (a) register(s).                 */
1557                                 /*----------------------------------*/
1558                                 case 0:
1559                                 case 1:
1560                                 case 2:
1561                                 case 4:
1562                                 case 8:
1563                                         add_general(&gr, sz, cinfo->args+nParm);
1564                                         cinfo->args[nParm].size    = size;
1565                                         cinfo->args[nParm].regtype = RegTypeStructByVal; 
1566                                         nParm++;
1567                                         sz->local_size            += sizeof(long);
1568                                         break;
1569                                 default:
1570                                         add_stackParm(&gr, sz, cinfo->args+nParm, size);
1571                                         nParm++;
1572                         }
1573                 }
1574                         break;
1575                 case MONO_TYPE_TYPEDBYREF: {
1576                         int size = sizeof (MonoTypedRef);
1577
1578                         cinfo->args[nParm].vtsize  = 0;
1579                         cinfo->args[nParm].size    = 0;
1580
1581                         switch (size) {
1582                                 /*----------------------------------*/
1583                                 /* On S/390, structures of size 1,  */
1584                                 /* 2, 4, and 8 bytes are passed in  */
1585                                 /* (a) register(s).                 */
1586                                 /*----------------------------------*/
1587                                 case 0:
1588                                 case 1:
1589                                 case 2:
1590                                 case 4:
1591                                 case 8:
1592                                         add_general(&gr, sz, cinfo->args+nParm);
1593                                         cinfo->args[nParm].size    = size;
1594                                         cinfo->args[nParm].regtype = RegTypeStructByVal; 
1595                                         nParm++;
1596                                         sz->local_size            += sizeof(long);
1597                                         break;
1598                                 default:
1599                                         add_stackParm(&gr, sz, cinfo->args+nParm, size);
1600                                         nParm++;
1601                         }
1602                 }
1603                         break;
1604                 default:
1605                         g_error ("Can't trampoline 0x%x", sig->params [i]->type);
1606                 }
1607         }
1608
1609         /*----------------------------------------------------------*/
1610         /* Handle the case where there are no implicit arguments    */
1611         /*----------------------------------------------------------*/
1612         if ((sig->call_convention == MONO_CALL_VARARG) &&
1613             (sig->param_count == sig->sentinelpos)) {
1614                 gr = S390_LAST_ARG_REG + 1;
1615                 add_general (&gr, sz, &cinfo->sigCookie);
1616         }
1617
1618         /*----------------------------------------------------------*/
1619         /* If we are passing a structure back then if it won't be   */
1620         /* in a register(s) then we make room at the end of the     */
1621         /* parameters that may have been placed on the stack        */
1622         /*----------------------------------------------------------*/
1623         if (cinfo->struct_ret) {
1624                 cinfo->ret.offset = sz->stack_size;
1625                 switch (cinfo->ret.size) {
1626                 case 0:
1627                 case 1:
1628                 case 2:
1629                 case 4:
1630                 case 8:
1631                         break;
1632                 default:
1633                         sz->stack_size   += S390_ALIGN(cinfo->ret.size, align);
1634                 }
1635         }
1636
1637         cinfo->lastgr   = gr;
1638         sz->stack_size  = sz->stack_size + sz->local_size + sz->parm_size + 
1639                           sz->offset;
1640         sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1641
1642         return (cinfo);
1643 }
1644
1645 /*========================= End of Function ========================*/
1646
1647 /*------------------------------------------------------------------*/
1648 /*                                                                  */
1649 /* Name         - mono_arch_allocate_vars                           */
1650 /*                                                                  */
1651 /* Function     - Set var information according to the calling      */
1652 /*                convention for S/390. The local var stuff should  */
1653 /*                most likely be split in another method.           */
1654 /*                                                                  */
1655 /* Parameter    - @m - Compile unit.                                */
1656 /*                                                                  */
1657 /*------------------------------------------------------------------*/
1658
1659 void
1660 mono_arch_allocate_vars (MonoCompile *cfg)
1661 {
1662         MonoMethodSignature *sig;
1663         MonoMethodHeader *header;
1664         MonoInst *inst;
1665         CallInfo *cinfo;
1666         int iParm, iVar, offset, size, align, curinst;
1667         int frame_reg = STK_BASE;
1668         int sArg, eArg;
1669
1670         header  = mono_method_get_header (cfg->method);
1671
1672         cfg->flags |= MONO_CFG_HAS_SPILLUP;
1673
1674         /*---------------------------------------------------------*/    
1675         /* We use the frame register also for any method that has  */ 
1676         /* filter clauses. This way, when the handlers are called, */
1677         /* the code will reference local variables using the frame */
1678         /* reg instead of the stack pointer: if we had to restore  */
1679         /* the stack pointer, we'd corrupt the method frames that  */
1680         /* are already on the stack (since filters get called      */
1681         /* before stack unwinding happens) when the filter code    */
1682         /* would call any method.                                  */
1683         /*---------------------------------------------------------*/    
1684         if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1685                 frame_reg = s390_r11;
1686
1687         cfg->frame_reg = frame_reg;
1688
1689         if (frame_reg != STK_BASE) 
1690                 cfg->used_int_regs |= 1 << frame_reg;           
1691
1692         sig     = mono_method_signature (cfg->method);
1693         
1694         cinfo   = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
1695
1696         if (cinfo->struct_ret) {
1697                 cfg->vret_addr->opcode = OP_REGVAR;
1698                 cfg->vret_addr->inst_c0 = s390_r2;
1699         } else {
1700                 switch (mono_type_get_underlying_type (sig->ret)->type) {
1701                 case MONO_TYPE_VOID:
1702                         break;
1703                 default:
1704                         cfg->ret->opcode = OP_REGVAR;
1705                         cfg->ret->dreg   = s390_r2;
1706                         break;
1707                 }
1708         }
1709
1710         /*--------------------------------------------------------------*/
1711         /* local vars are at a positive offset from the stack pointer   */
1712         /* also note that if the function uses alloca, we use s390_r11  */
1713         /* to point at the local variables.                             */
1714         /* add parameter area size for called functions                 */
1715         /*--------------------------------------------------------------*/
1716         offset          = (cfg->param_area + S390_MINIMAL_STACK_SIZE);
1717         cfg->sig_cookie = 0;
1718
1719         if (cinfo->struct_ret) {
1720                 inst               = cfg->vret_addr;
1721                 offset             = S390_ALIGN(offset, sizeof(gpointer));
1722                 inst->inst_offset  = offset;
1723                 inst->opcode       = OP_REGOFFSET;
1724                 inst->inst_basereg = frame_reg;
1725                 offset            += sizeof(gpointer);
1726                 if ((sig->call_convention == MONO_CALL_VARARG) &&
1727                     (!retFitsInReg (cinfo->ret.size)))
1728                         cfg->sig_cookie += cinfo->ret.size;
1729                 if (G_UNLIKELY (cfg->verbose_level > 1)) {
1730                         printf ("vret_addr =");
1731                         mono_print_ins (cfg->vret_addr);
1732                 }
1733         }
1734
1735         if (sig->hasthis) {
1736                 inst = cfg->args [0];
1737                 if (inst->opcode != OP_REGVAR) {
1738                         inst->opcode       = OP_REGOFFSET;
1739                         inst->inst_basereg = frame_reg;
1740                         offset             = S390_ALIGN(offset, sizeof(gpointer));
1741                         inst->inst_offset  = offset;
1742                         offset            += sizeof (gpointer);
1743                 }
1744                 curinst = sArg = 1;
1745         } else {
1746                 curinst = sArg = 0;
1747         }
1748
1749         eArg = sig->param_count + sArg;
1750
1751         if (sig->call_convention == MONO_CALL_VARARG)
1752                 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
1753
1754         for (iParm = sArg; iParm < eArg; ++iParm) {
1755                 inst = cfg->args [curinst];
1756                 if (inst->opcode != OP_REGVAR) {
1757                         switch (cinfo->args[iParm].regtype) {
1758                                 case RegTypeStructByAddr :
1759                                 if (cinfo->args[iParm].reg == STK_BASE) {
1760                                         inst->opcode       = OP_S390_LOADARG;
1761                                         inst->inst_basereg = frame_reg;
1762                                         offset             = S390_ALIGN(offset, sizeof(long));
1763                                         inst->inst_offset  = offset; 
1764                                         size               = abs(cinfo->args[iParm].vtsize);
1765                                         inst->backend.arg_info     = cinfo->args[iParm].offset;
1766                                 } else {
1767                                         inst->opcode       = OP_S390_ARGREG;
1768                                         inst->inst_basereg = frame_reg;
1769                                         size               = sizeof(gpointer);
1770                                         offset             = S390_ALIGN(offset, size);
1771                                         inst->inst_offset  = offset;
1772                                         inst->backend.arg_info     = cinfo->args[iParm].offset;
1773                                 }
1774                                         break;
1775                                 case RegTypeStructByVal :
1776                                         inst->opcode       = OP_S390_ARGPTR;
1777                                         inst->inst_basereg = frame_reg;
1778                                         size               = cinfo->args[iParm].size;
1779                                         offset             = S390_ALIGN(offset, size);
1780                                         inst->inst_offset  = offset;
1781                                         inst->backend.arg_info     = cinfo->args[iParm].offset;
1782                                         break;
1783                                 default :
1784                                 if (cinfo->args[iParm].reg != STK_BASE) {
1785                                         inst->opcode       = OP_REGOFFSET;
1786                                         inst->inst_basereg = frame_reg;
1787                                         size               = (cinfo->args[iParm].size < 8
1788                                                               ? sizeof(int)
1789                                                               : sizeof(long));
1790                                         offset             = S390_ALIGN(offset, size);
1791                                         inst->inst_offset  = offset;
1792                                 } else {
1793                                         inst->opcode       = OP_S390_STKARG;
1794                                         inst->inst_basereg = frame_reg;
1795                                         size               = ((cinfo->args[iParm].size < 8) 
1796                                                               ? 8 - cinfo->args[iParm].size
1797                                                               : 0);
1798                                         inst->inst_offset  = cinfo->args[iParm].offset + 
1799                                                              size;
1800                                         inst->backend.arg_info       = 0;
1801                                         size               = sizeof(long);
1802                                 } 
1803                         }
1804                         if ((sig->call_convention == MONO_CALL_VARARG) && 
1805                             (cinfo->args[iParm].regtype != RegTypeGeneral) &&
1806                             (iParm < sig->sentinelpos)) 
1807                                 cfg->sig_cookie += size;
1808
1809                         offset += size;
1810                 }
1811                 curinst++;
1812         }
1813
1814         curinst = cfg->locals_start;
1815         for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
1816                 inst = cfg->varinfo [iVar];
1817                 if ((inst->flags & MONO_INST_IS_DEAD) || 
1818                     (inst->opcode == OP_REGVAR))
1819                         continue;
1820
1821                 /*--------------------------------------------------*/
1822                 /* inst->backend.is_pinvoke indicates native sized value types, */
1823                 /* this is used by the pinvoke wrappers when they   */
1824                 /* call functions returning structure               */
1825                 /*--------------------------------------------------*/
1826                 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
1827                         size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype), &align);
1828                 else
1829                         size = mono_type_size (inst->inst_vtype, &align);
1830
1831                 offset             = S390_ALIGN(offset, align);
1832                 inst->inst_offset  = offset;
1833                 inst->opcode       = OP_REGOFFSET;
1834                 inst->inst_basereg = frame_reg;
1835                 offset            += size;
1836                 DEBUG (g_print("allocating local %d to %ld, size: %d\n", 
1837                                 iVar, inst->inst_offset, size));
1838         }
1839
1840         /*------------------------------------------------------*/
1841         /* Allow space for the trace method stack area if needed*/
1842         /*------------------------------------------------------*/
1843         if (mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)) 
1844                 offset += S390_TRACE_STACK_SIZE;
1845
1846         /*------------------------------------------------------*/
1847         /* Reserve space to save LMF and caller saved registers */
1848         /*------------------------------------------------------*/
1849         if (cfg->method->save_lmf)
1850                 offset += sizeof (MonoLMF);
1851
1852         /*------------------------------------------------------*/
1853         /* align the offset                                     */
1854         /*------------------------------------------------------*/
1855         cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
1856
1857 }
1858
1859 /*========================= End of Function ========================*/
1860
1861 /*------------------------------------------------------------------*/
1862 /*                                                                  */
1863 /* Name         - mono_arch_create_vars                                 */
1864 /*------------------------------------------------------------------*/
1865
1866 void
1867 mono_arch_create_vars (MonoCompile *cfg)
1868 {
1869         MonoMethodSignature *sig;
1870         CallInfo *cinfo;
1871
1872         sig = mono_method_signature (cfg->method);
1873
1874         cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
1875
1876         if (cinfo->struct_ret) {
1877                 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
1878                 if (G_UNLIKELY (cfg->verbose_level > 1)) {
1879                         printf ("vret_addr = ");
1880                         mono_print_ins (cfg->vret_addr);
1881                 }
1882         }
1883 }
1884
1885 /*========================= End of Function ========================*/
1886
1887 /*------------------------------------------------------------------*/
1888 /*                                                                  */
1889 /* Name         - mono_arch_call_opcode                             */
1890 /*                                                                  */
1891 /* Function     - Take the arguments and generate the arch-specific */
1892 /*                instructions to properly call the function. This  */
1893 /*                includes pushing, moving argments to the correct  */
1894 /*                etc.                                              */
1895 /*                                                                  */
1896 /*------------------------------------------------------------------*/
1897
1898 MonoCallInst*
1899 mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, 
1900                        MonoCallInst *call, int is_virtual)
1901 {
1902         MonoInst *in;
1903         MonoCallArgParm *arg;
1904         MonoMethodSignature *sig;
1905         int i, n, lParamArea;
1906         CallInfo *cinfo;
1907         ArgInfo *ainfo;
1908
1909         sig = call->signature;
1910         n = sig->param_count + sig->hasthis;
1911         DEBUG (g_print ("Call requires: %d parameters\n",n));
1912         
1913         cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
1914
1915         call->stack_usage = MAX(cinfo->sz.stack_size, call->stack_usage);
1916         lParamArea        = MAX((call->stack_usage - S390_MINIMAL_STACK_SIZE - cinfo->sz.parm_size), 0);
1917         cfg->param_area   = MAX (((signed) cfg->param_area), lParamArea);
1918         cfg->flags       |= MONO_CFG_HAS_CALLS;
1919
1920         if (cinfo->struct_ret)
1921                 call->used_iregs |= 1 << cinfo->ret.reg;
1922
1923         for (i = 0; i < n; ++i) {
1924                 ainfo = cinfo->args + i;
1925
1926                 if (!(sig->pinvoke) &&
1927                     (sig->call_convention == MONO_CALL_VARARG) &&
1928                     (i == sig->sentinelpos)) {
1929                         emit_sig_cookie (cfg, call, cinfo, ainfo->size);
1930                 }
1931
1932                 if (is_virtual && i == 0) {
1933                         /* the argument will be attached to the call instrucion */
1934                         in = call->args [i];
1935                         call->used_iregs |= 1 << ainfo->reg;
1936                 } else {
1937                         MONO_INST_NEW_CALL_ARG (cfg, arg, OP_OUTARG);
1938                         in                  = call->args [i];
1939                         arg->ins.cil_code   = in->cil_code;
1940                         arg->ins.inst_left  = in;
1941                         arg->ins.type       = in->type;
1942                         MONO_INST_LIST_ADD_TAIL (&arg->ins.node, &call->out_args);
1943                         arg->ins.inst_right = (MonoInst *) call;
1944                         if (ainfo->regtype == RegTypeGeneral) {
1945                                 arg->ins.backend.reg3 = ainfo->reg;
1946                                 call->used_iregs |= 1 << ainfo->reg;
1947                         } else if (ainfo->regtype == RegTypeStructByAddr) {
1948                                 call->used_iregs |= 1 << ainfo->reg;
1949                                 arg->ins.sreg1    = ainfo->reg;
1950                                 arg->ins.opcode   = OP_OUTARG_VT;
1951                                 arg->size         = -ainfo->vtsize;
1952                                 arg->offset       = ainfo->offset;
1953                                 arg->offPrm       = ainfo->offparm + cinfo->sz.offStruct;
1954                         } else if (ainfo->regtype == RegTypeStructByVal) {
1955                                 if (ainfo->reg != STK_BASE) 
1956                                         call->used_iregs |= 1 << ainfo->reg;
1957                                 arg->ins.sreg1  = ainfo->reg;
1958                                 arg->ins.opcode = OP_OUTARG_VT;
1959                                 arg->size       = ainfo->size;
1960                                 arg->offset     = ainfo->offset;
1961                                 arg->offPrm     = ainfo->offparm + cinfo->sz.offStruct;
1962                         } else if (ainfo->regtype == RegTypeBase) {
1963                                 arg->ins.opcode   = OP_OUTARG_MEMBASE;
1964                                 arg->ins.sreg1    = ainfo->reg;
1965                                 arg->size         = ainfo->size;
1966                                 arg->offset       = ainfo->offset;
1967                                 call->used_iregs |= 1 << ainfo->reg;
1968                         } else if (ainfo->regtype == RegTypeFP) {
1969                                 arg->ins.backend.reg3 = ainfo->reg;
1970                                 call->used_fregs |= 1 << ainfo->reg;
1971                                 if (ainfo->size == 4)
1972                                         arg->ins.opcode = OP_OUTARG_R4;
1973                                 else
1974                                         arg->ins.opcode = OP_OUTARG_R8;
1975                         } else {
1976                                 g_assert_not_reached ();
1977                         }
1978                 }
1979         }
1980
1981         /*
1982          * Handle the case where there are no implicit arguments 
1983          */
1984         if (!(sig->pinvoke) &&
1985             (sig->call_convention == MONO_CALL_VARARG) &&
1986             (n == sig->sentinelpos)) {
1987                 emit_sig_cookie (cfg, call, cinfo, sizeof(MonoType *));
1988         }
1989
1990         return call;
1991 }
1992
1993 /*========================= End of Function ========================*/
1994
1995 /*------------------------------------------------------------------*/
1996 /*                                                                  */
1997 /* Name         - emit_sig_cookie.                                  */
1998 /*                                                                  */
1999 /* Function     - For variable length parameter lists construct a   */
2000 /*                signature cookie and emit it.                     */
2001 /*                                                                  */
2002 /*------------------------------------------------------------------*/
2003
2004 static void
2005 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, 
2006                  CallInfo *cinfo, int argSize)
2007 {
2008         MonoCallArgParm *arg;
2009         MonoMethodSignature *tmpSig;
2010         MonoInst *sigArg;
2011                         
2012         cfg->disable_aot = TRUE;
2013
2014         /*----------------------------------------------------------*/
2015         /* mono_ArgIterator_Setup assumes the signature cookie is   */
2016         /* passed first and all the arguments which were before it  */
2017         /* passed on the stack after the signature. So compensate   */
2018         /* by passing a different signature.                        */
2019         /*----------------------------------------------------------*/
2020         tmpSig = mono_metadata_signature_dup (call->signature);
2021         tmpSig->param_count -= call->signature->sentinelpos;
2022         tmpSig->sentinelpos  = 0;
2023         if (tmpSig->param_count > 0)
2024                 memcpy (tmpSig->params, 
2025                         call->signature->params + call->signature->sentinelpos, 
2026                         tmpSig->param_count * sizeof(MonoType *));
2027
2028         MONO_INST_NEW (cfg, sigArg, OP_ICONST);
2029         sigArg->inst_p0 = tmpSig;
2030
2031         MONO_INST_NEW_CALL_ARG (cfg, arg, OP_OUTARG_MEMBASE);
2032         arg->ins.inst_left   = sigArg;
2033         arg->ins.inst_right  = (MonoInst *) call;
2034         arg->size            = argSize;
2035         arg->offset          = cinfo->sigCookie.offset;
2036         MONO_INST_LIST_ADD_TAIL (&arg->ins.node, &call->out_args);
2037 }
2038
2039 /*========================= End of Function ========================*/
2040
2041 /*------------------------------------------------------------------*/
2042 /*                                                                  */
2043 /* Name         - mono_arch_instrument_mem_needs                    */
2044 /*                                                                  */
2045 /* Function     - Allow tracing to work with this interface (with   */
2046 /*                an optional argument).                            */
2047 /*                                                                  */
2048 /*------------------------------------------------------------------*/
2049
2050 void
2051 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2052 {
2053         /* no stack room needed now (may be needed for FASTCALL-trace support) */
2054         *stack = 0;
2055         /* split prolog-epilog requirements? */
2056         *code = 50; /* max bytes needed: check this number */
2057 }
2058
2059 /*========================= End of Function ========================*/
2060
2061 /*------------------------------------------------------------------*/
2062 /*                                                                  */
2063 /* Name         - mono_arch_instrument_prolog                       */
2064 /*                                                                  */
2065 /* Function     - Create an "instrumented" prolog.                  */
2066 /*                                                                  */
2067 /*------------------------------------------------------------------*/
2068
2069 void*
2070 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, 
2071                              gboolean enable_arguments)
2072 {
2073         guchar  *code = p;
2074         int     parmOffset, 
2075                 fpOffset,
2076                 baseReg;
2077
2078         parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2079         if (cfg->method->save_lmf)
2080                 parmOffset -= sizeof(MonoLMF);
2081         fpOffset   = parmOffset + (5*sizeof(gpointer));
2082         if ((!has_ld) && (fpOffset > 4096)) {
2083                 s390_lgr (code, s390_r12, STK_BASE);
2084                 baseReg = s390_r12;
2085                 while (fpOffset > 4096) {
2086                         s390_aghi (code, baseReg, 4096);
2087                         fpOffset   -= 4096;
2088                         parmOffset -= 4096;
2089                 }
2090         } else {
2091                 baseReg = STK_BASE;
2092         }       
2093
2094         s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2095         if (has_ld) {
2096                 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2097                 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2098                 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2099                 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2100         } else {
2101                 s390_std  (code, s390_f0, 0, baseReg, fpOffset);
2102                 s390_std  (code, s390_f2, 0, baseReg, fpOffset+sizeof(gdouble));
2103                 s390_std  (code, s390_f4, 0, baseReg, fpOffset+2*sizeof(gdouble));
2104                 s390_std  (code, s390_f6, 0, baseReg, fpOffset+3*sizeof(gdouble));
2105         }
2106         s390_basr (code, s390_r13, 0);
2107         s390_j    (code, 10);
2108         s390_llong(code, cfg->method);
2109         s390_llong(code, func);
2110         s390_lg   (code, s390_r2, 0, s390_r13, 4);
2111         if (has_ld)
2112                 s390_lay  (code, s390_r3, 0, STK_BASE, parmOffset);
2113         else
2114                 s390_la   (code, s390_r3, 0, baseReg, parmOffset);
2115         s390_lgr  (code, s390_r4, STK_BASE);
2116         s390_aghi (code, s390_r4, cfg->stack_usage);
2117         s390_lg   (code, s390_r1, 0, s390_r13, 12);
2118         s390_basr (code, s390_r14, s390_r1);
2119         if (has_ld) {
2120                 s390_ldy  (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2121                 s390_ldy  (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2122                 s390_ldy  (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2123                 s390_ldy  (code, s390_f0, 0, STK_BASE, fpOffset);
2124         } else {
2125                 s390_ld   (code, s390_f6, 0, baseReg, fpOffset+3*sizeof(gdouble));
2126                 s390_ld   (code, s390_f4, 0, baseReg, fpOffset+2*sizeof(gdouble));
2127                 s390_ld   (code, s390_f2, 0, baseReg, fpOffset+sizeof(gdouble));
2128                 s390_ld   (code, s390_f0, 0, baseReg, fpOffset);
2129         }
2130         s390_lmg  (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2131
2132         return code;
2133 }
2134
2135 /*========================= End of Function ========================*/
2136
2137 /*------------------------------------------------------------------*/
2138 /*                                                                  */
2139 /* Name         - mono_arch_instrument_epilog                       */
2140 /*                                                                  */
2141 /* Function     - Create an epilog that will handle the returned    */
2142 /*                values used in instrumentation.                   */
2143 /*                                                                  */
2144 /*------------------------------------------------------------------*/
2145
2146 void*
2147 mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
2148 {
2149         guchar     *code = p;
2150         int        save_mode = SAVE_NONE,
2151                    saveOffset;
2152         MonoMethod *method = cfg->method;
2153         int        rtype = mono_type_get_underlying_type (mono_method_signature (method)->ret)->type;
2154
2155         saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2156         if (method->save_lmf)
2157                 saveOffset -= sizeof(MonoLMF);
2158
2159 handle_enum:
2160         switch (rtype) {
2161         case MONO_TYPE_VOID:
2162                 /* special case string .ctor icall */
2163                 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2164                         save_mode = SAVE_ONE;
2165                 else
2166                         save_mode = SAVE_NONE;
2167                 break;
2168         case MONO_TYPE_I8:
2169         case MONO_TYPE_U8:
2170                 save_mode = SAVE_ONE;
2171                 break;
2172         case MONO_TYPE_R4:
2173                 save_mode = SAVE_R4;
2174                 break;
2175         case MONO_TYPE_R8:
2176                 save_mode = SAVE_R8;
2177                 break;
2178         case MONO_TYPE_VALUETYPE:
2179                 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2180                         rtype = mono_method_signature (method)->ret->data.klass->enum_basetype->type;
2181                         goto handle_enum;
2182                 }
2183                 save_mode = SAVE_STRUCT;
2184                 break;
2185         default:
2186                 save_mode = SAVE_ONE;
2187                 break;
2188         }
2189
2190         switch (save_mode) {
2191         case SAVE_ONE:
2192                 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2193                 if (enable_arguments) {
2194                         s390_lgr (code, s390_r3, s390_r2);
2195                 }
2196                 break;
2197         case SAVE_R4:
2198                 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2199                 if (enable_arguments) {
2200                         s390_ldebr (code, s390_f0, s390_f0);
2201                 }
2202                 break;
2203         case SAVE_R8:
2204                 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2205                 break;
2206         case SAVE_STRUCT:
2207                 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2208                 if (enable_arguments) {
2209                         s390_lg (code, s390_r3, 0, cfg->frame_reg, 
2210                                  S390_MINIMAL_STACK_SIZE+cfg->param_area);
2211                 }
2212                 break;
2213         case SAVE_NONE:
2214         default:
2215                 break;
2216         }
2217
2218         s390_basr (code, s390_r13, 0);
2219         s390_j    (code, 10);
2220         s390_llong(code, cfg->method);
2221         s390_llong(code, func);
2222         s390_lg   (code, s390_r2, 0, s390_r13, 4);
2223         s390_lg   (code, s390_r1, 0, s390_r13, 12);
2224         s390_basr (code, s390_r14, s390_r1);
2225
2226         switch (save_mode) {
2227         case SAVE_ONE:
2228                 s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2229                 break;
2230         case SAVE_R4:
2231         case SAVE_R8:
2232                 s390_ld  (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2233                 break;
2234         case SAVE_STRUCT:
2235                 s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2236                 break;
2237         case SAVE_NONE:
2238         default:
2239                 break;
2240         }
2241
2242         return code;
2243 }
2244
2245 /*========================= End of Function ========================*/
2246
2247 void
2248 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2249 {
2250 }
2251
2252 /*------------------------------------------------------------------*/
2253 /*                                                                  */
2254 /* Name         - mono_arch_peephole_pass                                     */
2255 /*                                                                  */
2256 /* Function     - Form a peephole pass at the code looking for      */
2257 /*                simple optimizations.                             */
2258 /*                                                                  */
2259 /*------------------------------------------------------------------*/
2260
2261 void
2262 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2263 {
2264         MonoInst *ins, *n;
2265
2266         MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2267                 mono_peephole_ins (bb, ins);
2268         }
2269 }
2270
2271 /*========================= End of Function ========================*/
2272
2273 void
2274 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2275 {
2276         MonoInst *ins, *next;
2277
2278         if (bb->max_vreg > cfg->rs->next_vreg)
2279                 cfg->rs->next_vreg = bb->max_vreg;
2280
2281         MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2282                 switch (ins->opcode) {
2283                 case OP_DIV_IMM:
2284                 case OP_REM_IMM:
2285                 case OP_IDIV_IMM:
2286                 case OP_IREM_IMM:
2287                 case OP_IDIV_UN_IMM:
2288                 case OP_IREM_UN_IMM:
2289                         mono_decompose_op_imm (cfg, ins);
2290                         break;
2291                 default:
2292                         break;
2293                 }
2294         }
2295
2296         bb->max_vreg = cfg->rs->next_vreg;
2297 }
2298
2299 /*========================= End of Function ========================*/
2300
2301 /*------------------------------------------------------------------*/
2302 /*                                                                  */
2303 /* Name         - emit_float_to_int                                 */
2304 /*                                                                  */
2305 /* Function     - Create instructions which will convert a floating */
2306 /*                point value to integer.                           */
2307 /*                                                                  */
2308 /*------------------------------------------------------------------*/
2309
2310 static guchar*
2311 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2312 {
2313         /* sreg is a float, dreg is an integer reg. */
2314         if (is_signed) {
2315                 s390_cfdbr (code, dreg, 5, sreg);
2316                 switch (size) {
2317                         case 1:
2318                                 s390_lghi (code, s390_r0, 0);
2319                                 s390_lghi (code, s390_r13, 0xff);
2320                                 s390_ltgr (code, dreg, dreg);
2321                                 s390_jnl  (code, 4);
2322                                 s390_lghi (code, s390_r0, 0x80);
2323                                 s390_ngr  (code, dreg, s390_r13);
2324                                 s390_ogr  (code, dreg, s390_r0);
2325                                 break;
2326                 }
2327         } else {
2328                 short *o[1];
2329                 s390_basr   (code, s390_r13, 0);
2330                 s390_j      (code, 10);
2331                 s390_llong  (code, 0x41e0000000000000);
2332                 s390_llong  (code, 0x41f0000000000000);
2333                 s390_ldr    (code, s390_f15, sreg);
2334                 s390_cdb    (code, s390_f15, 0, s390_r13, 4);
2335                 s390_jl     (code, 0); CODEPTR (code, o[0]);
2336                 s390_sdb    (code, s390_f15, 0, s390_r13, 12);
2337                 s390_cfdbr  (code, dreg, 7, s390_f15);
2338                 s390_j      (code, 4);
2339                 PTRSLOT (code, o[0]);
2340                 s390_cfdbr  (code, dreg, 5, sreg);
2341                 switch (size) {
2342                         case 1: 
2343                                 s390_lghi (code, s390_r0, 0xff);
2344                                 s390_ngr  (code, dreg, s390_r0);
2345                                 break;
2346                         case 2:
2347                                 s390_lghi (code, s390_r0, -1);
2348                                 s390_srlg (code, s390_r0, s390_r0, 0, 16);
2349                                 s390_ngr  (code, dreg, s390_r0);
2350                                 break;
2351                 }
2352         }
2353         return code;
2354 }
2355
2356 /*========================= End of Function ========================*/
2357
2358 /*------------------------------------------------------------------*/
2359 /*                                                                  */
2360 /* Name         - mono_arch_output_basic_block                      */
2361 /*                                                                  */
2362 /* Function     - Perform the "real" work of emitting instructions  */
2363 /*                that will do the work of in the basic block.      */
2364 /*                                                                  */
2365 /*------------------------------------------------------------------*/
2366
2367 void
2368 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2369 {
2370         MonoInst *ins, *next;
2371         MonoCallInst *call;
2372         guint offset;
2373         guint8 *code = cfg->native_code + cfg->code_len;
2374         guint last_offset = 0;
2375         int max_len, cpos, src2;
2376
2377         /* we don't align basic blocks of loops on s390 */
2378
2379         if (cfg->verbose_level > 2)
2380                 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2381
2382         cpos = bb->max_offset;
2383
2384         if (cfg->prof_options & MONO_PROFILE_COVERAGE) {
2385                 //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
2386                 //g_assert (!mono_compile_aot);
2387                 //cpos += 6;
2388                 //if (bb->cil_code)
2389                 //      cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
2390                 /* this is not thread save, but good enough */
2391                 /* fixme: howto handle overflows? */
2392                 //x86_inc_mem (code, &cov->data [bb->dfn].count); 
2393         }
2394
2395         MONO_BB_FOR_EACH_INS (bb, ins) {
2396                 offset = code - cfg->native_code;
2397
2398                 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2399
2400                 if (offset > (cfg->code_size - max_len - 16)) {
2401                         cfg->code_size *= 2;
2402                         cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2403                         code = cfg->native_code + offset;
2404                 }
2405
2406                 mono_debug_record_line_number (cfg, ins, offset);
2407
2408                 switch (ins->opcode) {
2409                 case OP_STOREI1_MEMBASE_IMM: {
2410                         s390_lghi (code, s390_r0, ins->inst_imm);
2411                         S390_LONG (code, stcy, stc, s390_r0, 0, 
2412                                    ins->inst_destbasereg, ins->inst_offset);
2413                 }
2414                         break;
2415                 case OP_STOREI2_MEMBASE_IMM: {
2416                         s390_lghi (code, s390_r0, ins->inst_imm);
2417                         S390_LONG (code, sthy, sth, s390_r0, 0, 
2418                                    ins->inst_destbasereg, ins->inst_offset);
2419                 }
2420                         break;
2421                 case OP_STOREI4_MEMBASE_IMM: {
2422                         if (s390_is_imm16(ins->inst_imm)) {
2423                                 s390_lghi (code, s390_r0, ins->inst_imm);
2424                         } else {
2425                                 s390_basr (code, s390_r13, 0);
2426                                 s390_j    (code, 6);
2427                                 s390_llong(code, ins->inst_imm);
2428                                 s390_lg   (code, s390_r0, 0, s390_r13, 4);
2429                         }
2430                         S390_LONG (code, sty, st, s390_r0, 0, 
2431                                    ins->inst_destbasereg, ins->inst_offset);
2432                 }
2433                         break;
2434                 case OP_STORE_MEMBASE_IMM:
2435                 case OP_STOREI8_MEMBASE_IMM: {
2436                         if (s390_is_imm16(ins->inst_imm)) {
2437                                 s390_lghi (code, s390_r0, ins->inst_imm);
2438                         } else {
2439                                 s390_basr (code, s390_r13, 0);
2440                                 s390_j    (code, 6);
2441                                 s390_llong(code, ins->inst_imm);
2442                                 s390_lg   (code, s390_r0, 0, s390_r13, 4);
2443                         }
2444                         S390_LONG (code, stg, stg, s390_r0, 0, 
2445                                    ins->inst_destbasereg, ins->inst_offset);
2446                 }
2447                         break;
2448                 case OP_STOREI1_MEMBASE_REG: {
2449                         S390_LONG (code, stcy, stc, ins->sreg1, 0, 
2450                                    ins->inst_destbasereg, ins->inst_offset);
2451                 }
2452                         break;
2453                 case OP_STOREI2_MEMBASE_REG: {
2454                         S390_LONG (code, sthy, sth, ins->sreg1, 0, 
2455                                    ins->inst_destbasereg, ins->inst_offset);
2456                 }
2457                         break;
2458                 case OP_STOREI4_MEMBASE_REG: {
2459                         S390_LONG (code, sty, st, ins->sreg1, 0, 
2460                                    ins->inst_destbasereg, ins->inst_offset);
2461                 }
2462                         break;
2463                 case OP_STORE_MEMBASE_REG:
2464                 case OP_STOREI8_MEMBASE_REG: {
2465                         S390_LONG (code, stg, stg, ins->sreg1, 0, 
2466                                    ins->inst_destbasereg, ins->inst_offset);
2467                 }
2468                         break;
2469                 case OP_LOADU4_MEM:
2470                         g_assert_not_reached ();
2471                         break;
2472                 case OP_LOAD_MEMBASE:
2473                 case OP_LOADI8_MEMBASE: {
2474                         S390_LONG (code, lg, lg, ins->dreg, 0, 
2475                                    ins->inst_basereg, ins->inst_offset);
2476                 }
2477                         break;
2478                 case OP_LOADI4_MEMBASE: {
2479                         S390_LONG (code, lgf, lgf, ins->dreg, 0, 
2480                                    ins->inst_basereg, ins->inst_offset);
2481                 }
2482                         break;
2483                 case OP_LOADU4_MEMBASE: {
2484                         S390_LONG (code, llgf, llgf, ins->dreg, 0, 
2485                                    ins->inst_basereg, ins->inst_offset);
2486                 }
2487                         break;
2488                 case OP_LOADU1_MEMBASE: {
2489                         S390_LONG (code, llgc, llgc, ins->dreg, 0, 
2490                                    ins->inst_basereg, ins->inst_offset);
2491                 }
2492                         break;
2493                 case OP_LOADI1_MEMBASE: {
2494                         S390_LONG (code, lgb, lgb, ins->dreg, 0, 
2495                                    ins->inst_basereg, ins->inst_offset);
2496                 }
2497                         break;
2498                 case OP_LOADU2_MEMBASE: {
2499                         S390_LONG (code, llgh, llgh, ins->dreg, 0, 
2500                                    ins->inst_basereg, ins->inst_offset);
2501                 }
2502                         break;
2503                 case OP_LOADI2_MEMBASE: {
2504                         S390_LONG (code, lgh, lgh, ins->dreg, 0, 
2505                                    ins->inst_basereg, ins->inst_offset);
2506                 }
2507                         break;
2508                 case OP_LCONV_TO_I1: {
2509                         s390_lghi  (code, s390_r0, 0x80);
2510                         if (ins->dreg != ins->sreg1) {
2511                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2512                         }
2513                         s390_ngr  (code, s390_r0, ins->sreg1);
2514                         s390_jz   (code, 9);
2515                         s390_lghi (code, s390_r13, -1);
2516                         s390_sllg (code, s390_r13, s390_r13, 0, 8);
2517                         s390_ogr  (code, ins->dreg, s390_r13);
2518                 }
2519                         break;
2520                 case OP_LCONV_TO_I2: {
2521                         s390_lghi (code, s390_r0, 0x80);
2522                         s390_sllg (code, s390_r0, s390_r0, 0, 8);
2523                         if (ins->dreg != ins->sreg1) {
2524                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2525                         }
2526                         s390_ngr  (code, s390_r0, ins->sreg1);
2527                         s390_jz   (code, 9);
2528                         s390_lghi (code, s390_r13, -1);
2529                         s390_sllg (code, s390_r13, s390_r13, 0, 16);
2530                         s390_ogr  (code, ins->dreg, s390_r13);
2531                 }
2532                         break;
2533                 case OP_LCONV_TO_U1: {
2534                         s390_lghi (code, s390_r0, 0xff);
2535                         if (ins->dreg != ins->sreg1) {
2536                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2537                         }
2538                         s390_ngr  (code, ins->dreg, s390_r0);
2539                 }
2540                         break;
2541                 case OP_LCONV_TO_U2: {
2542                         s390_lghi (code, s390_r0, -1);
2543                         s390_sllg (code, s390_r0, s390_r0, 0, 16);
2544                         s390_srlg (code, s390_r0, s390_r0, 0, 16);
2545                         if (ins->dreg != ins->sreg1) {
2546                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2547                         }
2548                         s390_ngr  (code, ins->dreg, s390_r0);
2549                 }
2550                         break;
2551                 case OP_COMPARE: 
2552                 case OP_LCOMPARE: {
2553                         next = mono_inst_list_next (&ins->node, &bb->ins_list);
2554                         if ((next) && (mono_opcode_to_cond(next->opcode) >= CMP_LE_UN))
2555                                 s390_clgr (code, ins->sreg1, ins->sreg2);
2556                         else
2557                                 s390_cgr  (code, ins->sreg1, ins->sreg2);
2558                 }
2559                         break;
2560                 case OP_COMPARE_IMM: {
2561                         next = mono_inst_list_next (&ins->node, &bb->ins_list);
2562                         if (s390_is_imm16 (ins->inst_imm)) {
2563                                 s390_lghi (code, s390_r0, ins->inst_imm);
2564                                 if ((next) && 
2565                                     (mono_opcode_to_cond(next->opcode) >= CMP_LE_UN))
2566                                         s390_clgr (code, ins->sreg1, s390_r0);
2567                                 else
2568                                         s390_cgr  (code, ins->sreg1, s390_r0);
2569                         } else {
2570                                 s390_basr (code, s390_r13, 0);
2571                                 s390_j    (code, 6);
2572                                 s390_llong(code, ins->inst_imm);
2573                                 if ((next) && 
2574                                     (mono_opcode_to_cond(next->opcode) >= CMP_LE_UN))
2575                                         s390_clg  (code, ins->sreg1, 0, s390_r13, 4);
2576                                 else
2577                                         s390_cg   (code, ins->sreg1, 0, s390_r13, 4);
2578                         }
2579                 }
2580                         break;
2581                 case OP_ICOMPARE: {
2582                         next = mono_inst_list_next (&ins->node, &bb->ins_list);
2583                         if ((next) && (mono_opcode_to_cond(next->opcode) >= CMP_LE_UN))
2584                                 s390_clr  (code, ins->sreg1, ins->sreg2);
2585                         else
2586                                 s390_cr   (code, ins->sreg1, ins->sreg2);
2587                 }
2588                         break;
2589                 case OP_ICOMPARE_IMM: {
2590                         next = mono_inst_list_next (&ins->node, &bb->ins_list);
2591                         if (s390_is_imm16 (ins->inst_imm)) {
2592                                 s390_lghi (code, s390_r0, ins->inst_imm);
2593                                 if ((next) && 
2594                                     (mono_opcode_to_cond(next->opcode) >= CMP_LE_UN))
2595                                         s390_clr  (code, ins->sreg1, s390_r0);
2596                                 else
2597                                         s390_cr   (code, ins->sreg1, s390_r0);
2598                         }
2599                         else {
2600                                 s390_basr (code, s390_r13, 0);
2601                                 s390_j    (code, 4);
2602                                 s390_word (code, ins->inst_imm);
2603                                 if ((next) && 
2604                                     (mono_opcode_to_cond(next->opcode) >= CMP_LE_UN))
2605                                         s390_cl  (code, ins->sreg1, 0, s390_r13, 4);
2606                                 else
2607                                         s390_c   (code, ins->sreg1, 0, s390_r13, 4);
2608                         }
2609                 }
2610                         break;
2611                 case OP_BREAK: {
2612                         s390_basr  (code, s390_r13, 0);
2613                         s390_j     (code, 6);
2614                         mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS, 
2615                                              mono_break);
2616                         s390_llong (code, mono_break);
2617                         s390_lg    (code, s390_r14, 0, s390_r13, 4);
2618                         s390_basr  (code, s390_r14, s390_r14);
2619                 }
2620                         break;
2621                 case OP_ADDCC: {
2622                         CHECK_SRCDST_COM;
2623                         s390_algr  (code, ins->dreg, src2);
2624                 }
2625                         break;
2626                 case OP_LADD: {
2627                         CHECK_SRCDST_COM;
2628                         s390_agr   (code, ins->dreg, src2);
2629                 }
2630                         break;
2631                 case OP_ADC: {
2632                         CHECK_SRCDST_COM;
2633                         s390_alcgr (code, ins->dreg, src2);
2634                 }
2635                         break;
2636                 case OP_ADD_IMM: {
2637                         if (ins->dreg != ins->sreg1) {
2638                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2639                         }
2640                         if (s390_is_imm16 (ins->inst_imm)) {
2641                                 s390_aghi (code, ins->dreg, ins->inst_imm);
2642                         } else {
2643                                 s390_basr (code, s390_r13, 0);
2644                                 s390_j    (code, 6);
2645                                 s390_llong(code, ins->inst_imm);
2646                                 s390_ag   (code, ins->dreg, 0, s390_r13, 4);
2647                         }
2648                 }
2649                         break;
2650                 case OP_ADC_IMM: {
2651                         if (ins->dreg != ins->sreg1) {
2652                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2653                         }
2654                         if (s390_is_imm16 (ins->inst_imm)) {
2655                                 s390_lghi  (code, s390_r0, ins->inst_imm);
2656                                 s390_alcgr (code, ins->dreg, s390_r0);
2657                         } else {
2658                                 s390_basr  (code, s390_r13, 0);
2659                                 s390_j     (code, 6);
2660                                 s390_llong (code, ins->inst_imm);
2661                                 s390_lg    (code, s390_r13, 0, s390_r13, 4);
2662                                 s390_alcgr (code, ins->dreg, s390_r13);
2663                         }
2664                 }
2665                         break;
2666                 case OP_IADD_OVF: {
2667                         CHECK_SRCDST_COM;
2668                         s390_ar    (code, ins->dreg, src2);
2669                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
2670                         s390_lgfr  (code, ins->dreg, ins->dreg);
2671                 }
2672                         break;
2673                 case OP_IADD_OVF_UN: {
2674                         CHECK_SRCDST_COM;
2675                         s390_algr  (code, ins->dreg, src2);
2676                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
2677                         s390_llgfr (code, ins->dreg, ins->dreg);
2678                 }
2679                         break;
2680                 case OP_ADD_OVF_CARRY: {
2681                         CHECK_SRCDST_COM;
2682                         s390_lghi  (code, s390_r0, 0);
2683                         s390_lgr   (code, s390_r1, s390_r0);
2684                         s390_alcgr (code, s390_r0, s390_r1);
2685                         s390_agr   (code, ins->dreg, src2);
2686                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
2687                         s390_agr   (code, ins->dreg, s390_r0);
2688                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
2689                 }
2690                         break;
2691                 case OP_ADD_OVF_UN_CARRY: {
2692                         CHECK_SRCDST_COM;
2693                         s390_alcgr (code, ins->dreg, src2);
2694                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
2695                 }
2696                         break;
2697                 case OP_SUBCC: {
2698                         CHECK_SRCDST_NCOM;
2699                         s390_slgr (code, ins->dreg, src2);
2700                 }
2701                         break;
2702                 case OP_LSUB: {
2703                         CHECK_SRCDST_NCOM;
2704                         s390_sgr  (code, ins->dreg, src2);
2705                 }
2706                         break;
2707                 case OP_SBB: {
2708                         CHECK_SRCDST_NCOM;
2709                         s390_slbgr(code, ins->dreg, src2);
2710                 }
2711                         break;
2712                 case OP_SUB_IMM: {
2713                         if (ins->dreg != ins->sreg1) {
2714                                 s390_lgr   (code, ins->dreg, ins->sreg1);
2715                         }
2716                         if (s390_is_imm16 (-ins->inst_imm)) {
2717                                 s390_lghi  (code, s390_r0, ins->inst_imm);
2718                                 s390_slgr  (code, ins->dreg, s390_r0);
2719                         } else {
2720                                 s390_basr (code, s390_r13, 0);
2721                                 s390_j    (code, 6);
2722                                 s390_llong(code, ins->inst_imm);
2723                                 s390_slg  (code, ins->dreg, 0, s390_r13, 4);
2724                         }
2725                 }
2726                         break;
2727                 case OP_SBB_IMM: {
2728                         if (ins->dreg != ins->sreg1) {
2729                                 s390_lgr   (code, ins->dreg, ins->sreg1);
2730                         }
2731                         if (s390_is_imm16 (-ins->inst_imm)) {
2732                                 s390_lghi  (code, s390_r0, ins->inst_imm);
2733                                 s390_slbgr (code, ins->dreg, s390_r0);
2734                         } else {
2735                                 s390_basr (code, s390_r13, 0);
2736                                 s390_j    (code, 6);
2737                                 s390_llong(code, ins->inst_imm);
2738                                 s390_slbg (code, ins->dreg, 0, s390_r13, 4);
2739                         }
2740                 }
2741                         break;
2742                 case OP_SUB_OVF_CARRY: {
2743                         CHECK_SRCDST_NCOM;
2744                         s390_lghi  (code, s390_r0, 0);
2745                         s390_lgr   (code, s390_r1, s390_r0);
2746                         s390_slbgr (code, s390_r0, s390_r1);
2747                         s390_sgr   (code, ins->dreg, src2);
2748                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
2749                         s390_agr   (code, ins->dreg, s390_r0);
2750                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
2751                 }
2752                         break;
2753                 case OP_SUB_OVF_UN_CARRY: {
2754                         CHECK_SRCDST_NCOM;
2755                         s390_slbgr (code, ins->dreg, src2);
2756                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
2757                 }
2758                         break;
2759                 case OP_LAND: {
2760                         if (ins->sreg1 == ins->dreg) {
2761                                 s390_ngr  (code, ins->dreg, ins->sreg2);
2762                         } 
2763                         else { 
2764                                 if (ins->sreg2 == ins->dreg) { 
2765                                         s390_ngr (code, ins->dreg, ins->sreg1);
2766                                 }
2767                                 else { 
2768                                         s390_lgr (code, ins->dreg, ins->sreg1);
2769                                         s390_ngr (code, ins->dreg, ins->sreg2);
2770                                 }
2771                         }
2772                 }
2773                         break;
2774                 case OP_AND_IMM: {
2775                         if (ins->dreg != ins->sreg1) {
2776                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2777                         }
2778                         if (s390_is_imm16 (ins->inst_imm)) {
2779                                 s390_lghi  (code, s390_r0, ins->inst_imm);
2780                                 s390_ngr  (code, ins->dreg, s390_r0);
2781                         } else {
2782                                 s390_basr (code, s390_r13, 0);
2783                                 s390_j    (code, 6);
2784                                 s390_llong(code, ins->inst_imm);
2785                                 s390_ng   (code, ins->dreg, 0, s390_r13, 4);
2786                         }
2787                 }
2788                         break;
2789                 case OP_LDIV: {
2790                         s390_lgr  (code, s390_r1, ins->sreg1);
2791                         s390_dsgr (code, s390_r0, ins->sreg2);
2792                         s390_lgr  (code, ins->dreg, s390_r1);
2793                 }
2794                         break;
2795                 case OP_LDIV_UN: {
2796                         s390_lgr   (code, s390_r1, ins->sreg1);
2797                         s390_lghi  (code, s390_r0, 0);
2798                         s390_dlgr  (code, s390_r0, ins->sreg2);
2799                         s390_lgr   (code, ins->dreg, s390_r1);
2800                 }
2801                         break;
2802                 case OP_LREM: {
2803                         s390_lgr  (code, s390_r1, ins->sreg1);
2804                         s390_dsgr (code, s390_r0, ins->sreg2);
2805                         s390_lgr  (code, ins->dreg, s390_r0);
2806                         break;
2807                 }
2808                 case OP_LREM_UN: {
2809                         s390_lgr   (code, s390_r1, ins->sreg1);
2810                         s390_lghi  (code, s390_r0, 0);
2811                         s390_dlgr  (code, s390_r0, ins->sreg2);
2812                         s390_lgr   (code, ins->dreg, s390_r0);
2813                 }
2814                         break;
2815                 case OP_LOR: {
2816                         if (ins->sreg1 == ins->dreg) {
2817                                 s390_ogr  (code, ins->dreg, ins->sreg2);
2818                         } 
2819                         else { 
2820                                 if (ins->sreg2 == ins->dreg) { 
2821                                         s390_ogr (code, ins->dreg, ins->sreg1);
2822                                 }
2823                                 else { 
2824                                         s390_lgr (code, ins->dreg, ins->sreg1);
2825                                         s390_ogr (code, ins->dreg, ins->sreg2);
2826                                 }
2827                         }
2828                 }
2829                         break;
2830                 case OP_OR_IMM: {
2831                         if (ins->dreg != ins->sreg1) {
2832                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2833                         }
2834                         if (s390_is_imm16 (ins->inst_imm)) {
2835                                 s390_lghi (code, s390_r0, ins->inst_imm);
2836                                 s390_ogr  (code, ins->dreg, s390_r0);
2837                         } else {
2838                                 s390_basr (code, s390_r13, 0);
2839                                 s390_j    (code, 6);
2840                                 s390_llong(code, ins->inst_imm);
2841                                 s390_og   (code, ins->dreg, 0, s390_r13, 4);
2842                         }
2843                 }
2844                         break;
2845                 case OP_LXOR: {
2846                         if (ins->sreg1 == ins->dreg) {
2847                                 s390_xgr  (code, ins->dreg, ins->sreg2);
2848                         } 
2849                         else { 
2850                                 if (ins->sreg2 == ins->dreg) { 
2851                                         s390_xgr (code, ins->dreg, ins->sreg1);
2852                                 }
2853                                 else { 
2854                                         s390_lgr (code, ins->dreg, ins->sreg1);
2855                                         s390_xgr (code, ins->dreg, ins->sreg2);
2856                                 }
2857                         }
2858                 }
2859                         break;
2860                 case OP_XOR_IMM: {
2861                         if (ins->dreg != ins->sreg1) {
2862                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2863                         }
2864                         if (s390_is_imm16 (ins->inst_imm)) {
2865                                 s390_lghi  (code, s390_r0, ins->inst_imm);
2866                                 s390_xgr  (code, ins->dreg, s390_r0);
2867                         } else {
2868                                 s390_basr (code, s390_r13, 0);
2869                                 s390_j    (code, 6);
2870                                 s390_llong(code, ins->inst_imm);
2871                                 s390_xg   (code, ins->dreg, 0, s390_r13, 4);
2872                         }
2873                 }
2874                         break;
2875                 case OP_LSHL: {
2876                         CHECK_SRCDST_NCOM;
2877                         s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
2878                 }
2879                         break;
2880                 case OP_SHL_IMM: 
2881                 case OP_LSHL_IMM: {
2882                         if (ins->sreg1 != ins->dreg) {
2883                                 s390_lgr   (code, ins->dreg, ins->sreg1);
2884                         }
2885                         s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
2886                 }
2887                         break;
2888                 case OP_LSHR: {
2889                         CHECK_SRCDST_NCOM;
2890                         s390_srag  (code, ins->dreg, ins->dreg, src2, 0);
2891                 }
2892                         break;
2893                 case OP_SHR_IMM:
2894                 case OP_LSHR_IMM: {
2895                         if (ins->sreg1 != ins->dreg) {
2896                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2897                         }
2898                         s390_srag  (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
2899                 }
2900                         break;
2901                 case OP_SHR_UN_IMM: 
2902                 case OP_LSHR_UN_IMM: {
2903                         if (ins->sreg1 != ins->dreg) {
2904                                 s390_lgr   (code, ins->dreg, ins->sreg1);
2905                         }
2906                         s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
2907                 }
2908                         break;
2909                 case OP_LSHR_UN: {
2910                         CHECK_SRCDST_NCOM;
2911                         s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
2912                 }
2913                         break;
2914                 case OP_LNOT: {
2915                         if (ins->sreg1 != ins->dreg) {
2916                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2917                         }
2918                         s390_lghi (code, s390_r0, -1);
2919                         s390_xgr  (code, ins->dreg, s390_r0);
2920                 }
2921                         break;
2922                 case OP_LNEG: {
2923                         s390_lcgr (code, ins->dreg, ins->sreg1);
2924                 }
2925                         break;
2926                 case OP_LMUL: {
2927                         CHECK_SRCDST_COM;
2928                         s390_msgr (code, ins->dreg, src2);
2929                 }
2930                         break;
2931                 case OP_MUL_IMM: 
2932                 case OP_LMUL_IMM: {
2933                         if (ins->dreg != ins->sreg1) {
2934                                 s390_lgr  (code, ins->dreg, ins->sreg1);
2935                         }
2936                         if (s390_is_imm16 (ins->inst_imm)) {
2937                                 s390_lghi (code, s390_r13, ins->inst_imm);
2938                         } else {
2939                                 s390_basr (code, s390_r13, 0);
2940                                 s390_j    (code, 6);
2941                                 s390_llong(code, ins->inst_imm);
2942                                 s390_lg   (code, s390_r13, 0, s390_r13, 4);
2943                         }
2944                         s390_msgr (code, ins->dreg, s390_r13);
2945                 }
2946                         break;
2947                 case OP_LMUL_OVF: {
2948                         short int *o[2];
2949                         s390_ltgr (code, s390_r1, ins->sreg1);
2950                         s390_jz   (code, 0); CODEPTR(code, o[0]);
2951                         s390_ltgr (code, s390_r0, ins->sreg2);
2952                         s390_jnz  (code, 6);
2953                         s390_lghi (code, s390_r1, 0);
2954                         s390_j    (code, 0); CODEPTR(code, o[1]);
2955                         s390_xgr  (code, s390_r0, s390_r1);
2956                         s390_msgr (code, s390_r1, ins->sreg2);
2957                         s390_xgr  (code, s390_r0, s390_r1);
2958                         s390_srlg (code, s390_r0, s390_r0, 0, 63);
2959                         s390_ltgr (code, s390_r0, s390_r0);
2960                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
2961                         PTRSLOT   (code, o[0]); 
2962                         PTRSLOT   (code, o[1]);
2963                         s390_lgr  (code, ins->dreg, s390_r1);
2964                 }
2965                         break;
2966                 case OP_LMUL_OVF_UN: {
2967                         s390_lghi  (code, s390_r0, 0);
2968                         s390_lgr   (code, s390_r1, ins->sreg1);
2969                         s390_mlgr  (code, s390_r0, ins->sreg2);
2970                         s390_ltgr  (code, s390_r0, s390_r0);
2971                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
2972                         s390_lgr   (code, ins->dreg, s390_r1);
2973                 }
2974                         break;
2975                 case OP_IADDCC: {
2976                         g_assert_not_reached ();
2977                         CHECK_SRCDST_COM_I;
2978                         s390_algr (code, ins->dreg, src2);
2979                 }
2980                         break;
2981                 case OP_IADD: {
2982                         CHECK_SRCDST_COM_I;
2983                         s390_agr  (code, ins->dreg, src2);
2984                 }
2985                         break;
2986                 case OP_IADC: {
2987                         g_assert_not_reached ();
2988                         CHECK_SRCDST_COM_I;
2989                         s390_alcgr (code, ins->dreg, src2);
2990                 }
2991                         break;
2992                 case OP_IADD_IMM: {
2993                         if (ins->dreg != ins->sreg1) {
2994                                 s390_lgfr (code, ins->dreg, ins->sreg1);
2995                         }
2996                         if (s390_is_imm16 (ins->inst_imm)) {
2997                                 s390_aghi(code, ins->dreg, ins->inst_imm);
2998                         } else {
2999                                 s390_basr (code, s390_r13, 0);
3000                                 s390_j    (code, 4);
3001                                 s390_word (code, ins->inst_imm);
3002                                 s390_agf  (code, ins->dreg, 0, s390_r13, 4);
3003                         }
3004                 }
3005                         break;
3006                 case OP_IADC_IMM: {
3007                         if (ins->dreg != ins->sreg1) {
3008                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3009                         } 
3010                         if (s390_is_imm16 (ins->inst_imm)) {
3011                                 s390_lghi  (code, s390_r0, ins->inst_imm);
3012                                 s390_alcgr (code, ins->dreg, s390_r0);
3013                         } else {
3014                                 s390_basr  (code, s390_r13, 0);
3015                                 s390_j     (code, 4);
3016                                 s390_word  (code, ins->inst_imm);
3017                                 s390_lgf   (code, s390_r13, 0, s390_r13, 4);
3018                                 s390_alcgr (code, ins->dreg, s390_r13);
3019                         }
3020                 }
3021                         break;
3022                 case OP_LADD_OVF: {
3023                         CHECK_SRCDST_COM;
3024                         s390_agr    (code, ins->dreg, src2);
3025                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3026                 }
3027                         break;
3028                 case OP_LADD_OVF_UN: {
3029                         CHECK_SRCDST_COM;
3030                         s390_algr  (code, ins->dreg, src2);
3031                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3032                 }
3033                         break;
3034                 case OP_ISUBCC: {
3035                         CHECK_SRCDST_NCOM_I;
3036                         s390_slgr (code, ins->dreg, src2);
3037                 }
3038                         break;
3039                 case OP_ISUB: {
3040                         CHECK_SRCDST_NCOM_I;
3041                         s390_sgr  (code, ins->dreg, src2);
3042                 }
3043                         break;
3044                 case OP_ISBB: {
3045                         CHECK_SRCDST_NCOM_I;
3046                         s390_slbgr (code, ins->dreg, src2);
3047                 }
3048                         break;
3049                 case OP_ISUB_IMM: {
3050                         if (ins->dreg != ins->sreg1) {
3051                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3052                         }
3053                         if (s390_is_imm16 (-ins->inst_imm)) {
3054                                 s390_aghi (code, ins->dreg, -ins->inst_imm);
3055                         } else {
3056                                 s390_basr (code, s390_r13, 0);
3057                                 s390_j    (code, 4);
3058                                 s390_word (code, ins->inst_imm);
3059                                 s390_sgf  (code, ins->dreg, 0, s390_r13, 4);
3060                         }
3061                 }
3062                         break;
3063                 case OP_ISBB_IMM: {
3064                         s390_basr (code, s390_r13, 0);
3065                         s390_j    (code, 4);
3066                         s390_word (code, ins->inst_imm);
3067                         s390_slgf (code, ins->dreg, 0, s390_r13, 4);
3068                 }
3069                         break;
3070                 case OP_ISUB_OVF: {
3071                         CHECK_SRCDST_NCOM;
3072                         s390_sr   (code, ins->dreg, src2);
3073                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3074                         s390_lgfr (code, ins->dreg, ins->dreg);
3075                 }
3076                         break;
3077                 case OP_ISUB_OVF_UN: {
3078                         CHECK_SRCDST_NCOM;
3079                         s390_slr  (code, ins->dreg, src2);
3080                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3081                         s390_llgfr(code, ins->dreg, ins->dreg);
3082                 }
3083                         break;
3084                 case OP_LSUB_OVF: {
3085                         CHECK_SRCDST_NCOM;
3086                         s390_sgr   (code, ins->dreg, src2);
3087                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3088                 }
3089                         break;
3090                 case OP_LSUB_OVF_UN: {
3091                         CHECK_SRCDST_NCOM;
3092                         s390_slgr  (code, ins->dreg, src2);
3093                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3094                 }
3095                         break;
3096                 case OP_IAND: {
3097                         CHECK_SRCDST_NCOM_I;
3098                         s390_ngr (code, ins->dreg, src2);
3099                 }
3100                         break;
3101                 case OP_IAND_IMM: {
3102                         if (ins->dreg != ins->sreg1) {
3103                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3104                         }
3105                         if (s390_is_imm16 (ins->inst_imm)) {
3106                                 s390_lghi (code, s390_r0, ins->inst_imm);
3107                                 s390_ngr  (code, ins->dreg, s390_r0);
3108                         } else {
3109                                 s390_basr (code, s390_r13, 0);
3110                                 s390_j    (code, 6);
3111                                 s390_llong(code, ins->inst_imm);
3112                                 s390_ng   (code, ins->dreg, 0, s390_r13, 4);
3113                         }
3114                 }
3115                         break;
3116                 case OP_IDIV: {
3117                         s390_lgfr (code, s390_r0, ins->sreg1);
3118                         s390_srda (code, s390_r0, 0, 32);
3119                         s390_dr   (code, s390_r0, ins->sreg2);
3120                         s390_lgfr (code, ins->dreg, s390_r1);
3121                 }
3122                         break;
3123                 case OP_IDIV_UN: {
3124                         s390_lgfr (code, s390_r0, ins->sreg1);
3125                         s390_srdl (code, s390_r0, 0, 32);
3126                         s390_dlr  (code, s390_r0, ins->sreg2);
3127                         s390_lgfr (code, ins->dreg, s390_r1);
3128                 }
3129                         break;
3130                 case OP_IDIV_IMM: {
3131                         if (s390_is_imm16 (ins->inst_imm)) {
3132                                 s390_lghi (code, s390_r13, ins->inst_imm);
3133                                 s390_lgfr (code, s390_r0, ins->sreg1);
3134                         } else {
3135                                 s390_basr (code, s390_r13, 0);
3136                                 s390_j    (code, 4);
3137                                 s390_word (code, ins->inst_imm);
3138                                 s390_lgfr (code, s390_r0, ins->sreg1);
3139                                 s390_lgf  (code, s390_r13, 0, s390_r13, 4);
3140                         }
3141                         s390_srda (code, s390_r0, 0, 32);
3142                         s390_dr   (code, s390_r0, ins->sreg2);
3143                         s390_lgfr (code, ins->dreg, s390_r1);
3144                 }
3145                         break;
3146                 case OP_IREM: {
3147                         s390_lgfr (code, s390_r0, ins->sreg1);
3148                         s390_srda (code, s390_r0, 0, 32);
3149                         s390_dr   (code, s390_r0, ins->sreg2);
3150                         s390_lgfr (code, ins->dreg, s390_r0);
3151                         break;
3152                 case OP_IREM_UN:
3153                         s390_lgfr (code, s390_r0, ins->sreg1);
3154                         s390_srdl (code, s390_r0, 0, 32);
3155                         s390_dlr  (code, s390_r0, ins->sreg2);
3156                         s390_lgfr (code, ins->dreg, s390_r0);
3157                 }
3158                         break;
3159                 case OP_IREM_IMM: {
3160                         if (s390_is_imm16 (ins->inst_imm)) {
3161                                 s390_lghi (code, s390_r13, ins->inst_imm);
3162                                 s390_lgfr (code, s390_r0, ins->sreg1);
3163                         } else {
3164                                 s390_basr (code, s390_r13, 0);
3165                                 s390_j    (code, 4);
3166                                 s390_word (code, ins->inst_imm);
3167                                 s390_lgfr (code, s390_r0, ins->sreg1);
3168                                 s390_lgf  (code, s390_r13, 0, s390_r13, 4);
3169                         }
3170                         s390_srda (code, s390_r0, 0, 32);
3171                         s390_dr   (code, s390_r0, ins->sreg2);
3172                         s390_lgfr (code, ins->dreg, s390_r0);
3173                 }
3174                         break;
3175                 case OP_IOR: {
3176                         CHECK_SRCDST_COM_I;
3177                         s390_ogr (code, ins->dreg, src2);
3178                 }
3179                         break;
3180                 case OP_IOR_IMM: {
3181                         if (ins->dreg != ins->sreg1) {
3182                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3183                         }
3184                         if (s390_is_imm16 (ins->inst_imm)) {
3185                                 s390_lghi (code, s390_r0, ins->inst_imm);
3186                                 s390_ogr  (code, ins->dreg, s390_r0);
3187                         } else {
3188                                 s390_basr (code, s390_r13, 0);
3189                                 s390_j    (code, 6);
3190                                 s390_llong(code, ins->inst_imm);
3191                                 s390_og   (code, ins->dreg, 0, s390_r13, 4);
3192                         }
3193                 }
3194                         break;
3195                 case OP_IXOR: {
3196                         CHECK_SRCDST_COM_I;
3197                         s390_xgr (code, ins->dreg, src2);
3198                 }
3199                         break;
3200                 case OP_IXOR_IMM: {
3201                         if (ins->dreg != ins->sreg1) {
3202                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3203                         }
3204                         if (s390_is_imm16 (ins->inst_imm)) {
3205                                 s390_lghi (code, s390_r0, ins->inst_imm);
3206                                 s390_xgr  (code, ins->dreg, s390_r0);
3207                         } else {
3208                                 s390_basr (code, s390_r13, 0);
3209                                 s390_j    (code, 6);
3210                                 s390_llong(code, ins->inst_imm);
3211                                 s390_xg   (code, ins->dreg, 0, s390_r13, 4);
3212                         }
3213                 }
3214                         break;
3215                 case OP_ISHL: {
3216                         if (ins->sreg1 != ins->dreg) {
3217                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3218                         }
3219                         s390_sll  (code, ins->dreg, ins->sreg2, 0);
3220                 }
3221                         break;
3222                 case OP_ISHL_IMM: {
3223                         if (ins->sreg1 != ins->dreg) {
3224                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3225                         }
3226                         s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3227                 }
3228                         break;
3229                 case OP_ISHR: {
3230                         if (ins->sreg1 != ins->dreg) {
3231                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3232                         }
3233                         s390_sra (code, ins->dreg, ins->sreg2, 0);
3234                 }
3235                         break;
3236                 case OP_ISHR_IMM: {
3237                         if (ins->sreg1 != ins->dreg) {
3238                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3239                         }
3240                         s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3241                 }
3242                         break;
3243                 case OP_ISHR_UN_IMM: {
3244                         if (ins->sreg1 != ins->dreg) {
3245                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3246                         }
3247                         s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3248                 }
3249                         break;
3250                 case OP_ISHR_UN: {
3251                         if (ins->sreg1 != ins->dreg) {
3252                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3253                         }
3254                         s390_srl  (code, ins->dreg, ins->sreg2, 0);
3255                 }
3256                         break;
3257                 case OP_INOT: {
3258                         if (ins->sreg1 != ins->dreg) {
3259                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3260                         }
3261                         s390_lghi (code, s390_r0, -1);
3262                         s390_xgr  (code, ins->dreg, s390_r0);
3263                 }
3264                         break;
3265                 case OP_INEG: {
3266                         s390_lcgr (code, ins->dreg, ins->sreg1);
3267                 }
3268                         break;
3269                 case OP_IMUL: {
3270                         CHECK_SRCDST_COM_I;
3271                         s390_msr (code, ins->dreg, src2);
3272                 }
3273                         break;
3274                 case OP_IMUL_IMM: {
3275                         if (ins->dreg != ins->sreg1) {
3276                                 s390_lgfr (code, ins->dreg, ins->sreg1);
3277                         }
3278                         if (s390_is_imm16 (ins->inst_imm)) {
3279                                 s390_lghi (code, s390_r13, ins->inst_imm);
3280                         } else {
3281                                 s390_basr (code, s390_r13, 0);
3282                                 s390_j    (code, 4);
3283                                 s390_word (code, ins->inst_imm);
3284                                 s390_lgf  (code, s390_r13, 0, s390_r13, 4);
3285                         }
3286                         s390_msr  (code, ins->dreg, s390_r13);
3287                 }
3288                         break;
3289                 case OP_IMUL_OVF: {
3290                         short int *o[2];
3291                         s390_ltr  (code, s390_r1, ins->sreg1);
3292                         s390_jz   (code, 0); CODEPTR(code, o[0]);
3293                         s390_ltr  (code, s390_r0, ins->sreg2);
3294                         s390_jnz  (code, 6);
3295                         s390_lhi  (code, s390_r1, 0);
3296                         s390_j    (code, 0); CODEPTR(code, o[1]);
3297                         s390_xr   (code, s390_r0, s390_r1);
3298                         s390_msr  (code, s390_r1, ins->sreg2);
3299                         s390_xr   (code, s390_r0, s390_r1);
3300                         s390_srl  (code, s390_r0, 0, 31);
3301                         s390_ltr  (code, s390_r0, s390_r0);
3302                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3303                         PTRSLOT   (code, o[0]); 
3304                         PTRSLOT   (code, o[1]);
3305                         s390_lgfr (code, ins->dreg, s390_r1);
3306                 }
3307                         break;
3308                 case OP_IMUL_OVF_UN: {
3309                         s390_lhi  (code, s390_r0, 0);
3310                         s390_lr   (code, s390_r1, ins->sreg1);
3311                         s390_mlr  (code, s390_r0, ins->sreg2);
3312                         s390_ltr  (code, s390_r0, s390_r0);
3313                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3314                         s390_lgfr (code, ins->dreg, s390_r1);
3315                 }
3316                         break;
3317                 case OP_ICONST: 
3318                 case OP_I8CONST: {
3319                         if (s390_is_imm16(ins->inst_c0)) {
3320                                 s390_lghi (code, ins->dreg, ins->inst_c0);
3321                         } else {
3322                                 s390_basr (code, s390_r13, 0);
3323                                 s390_j    (code, 6);
3324                                 s390_llong(code, ins->inst_c0);
3325                                 s390_lg   (code, ins->dreg, 0, s390_r13, 4);
3326                         }
3327                 }
3328                         break;
3329                 case OP_AOTCONST: {
3330                         s390_basr (code, s390_r13, 0);
3331                         s390_j    (code, 6);
3332                         mono_add_patch_info (cfg, code - cfg->native_code, 
3333                                 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3334                         s390_llong(code, 0);
3335                         s390_lg   (code,ins->dreg, 0, s390_r13, 4);
3336                 }
3337                         break;
3338                 case OP_MOVE:
3339                         if (ins->dreg != ins->sreg1) {
3340                                 s390_lgr (code, ins->dreg, ins->sreg1);
3341                         }
3342                         break;
3343                 case OP_LCONV_TO_I:
3344                 case OP_LCONV_TO_I8:
3345                 case OP_SEXT_I4:
3346                         s390_lgfr (code, ins->dreg, ins->sreg1);
3347                         break;
3348                 case OP_LCONV_TO_I4:
3349                         s390_lgfr (code, ins->dreg, ins->sreg1);
3350                         break;
3351                 case OP_LCONV_TO_U:
3352                 case OP_LCONV_TO_U8:
3353                 case OP_LCONV_TO_U4:
3354                 case OP_ZEXT_I4:
3355                         s390_llgfr (code, ins->dreg, ins->sreg1);
3356                         break;
3357                 case OP_LCONV_TO_OVF_U4:
3358                         s390_basr (code, s390_r13, 0);
3359                         s390_j    (code, 6);
3360                         s390_llong(code, 4294967295);
3361                         s390_clg  (code, ins->sreg1, 0, s390_r13, 4);   
3362                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3363                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3364                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3365                         s390_llgfr(code, ins->dreg, ins->sreg1);
3366                         break;
3367                 case OP_LCONV_TO_OVF_I4_UN:
3368                         s390_basr (code, s390_r13, 0);
3369                         s390_j    (code, 6);
3370                         s390_llong(code, 2147483647);
3371                         s390_cg   (code, ins->sreg1, 0, s390_r13, 4);
3372                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3373                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3374                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3375                         s390_lgfr (code, ins->dreg, ins->sreg1);
3376                         break;
3377                 case OP_FMOVE: {
3378                         if (ins->dreg != ins->sreg1) {
3379                                 s390_ldr   (code, ins->dreg, ins->sreg1);
3380                         }
3381                 }
3382                         break;
3383                 case OP_S390_SETF4RET: {
3384                         s390_ledbr (code, ins->dreg, ins->sreg1);
3385                 }
3386                         break;
3387                 case OP_FCONV_TO_R4: {
3388                         g_error ("Shouldn't be reached");
3389                         next = mono_inst_list_next (&ins->node, &bb->ins_list);
3390                         if ((next) &&
3391                             (next->opcode != OP_FMOVE) &&
3392                             (next->opcode != OP_STORER4_MEMBASE_REG))
3393                                 s390_ledbr (code, ins->dreg, ins->sreg1);
3394                 }
3395                         break;
3396                 case OP_JMP: {
3397                         if (cfg->method->save_lmf)
3398                                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3399
3400                         if (cfg->flags & MONO_CFG_HAS_TAIL) {
3401                                 code =  emit_load_volatile_registers(code, cfg);
3402                         }
3403
3404                         code = backUpStackPtr(cfg, code);
3405                         s390_lg  (code, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET);
3406                         mono_add_patch_info (cfg, code - cfg->native_code,
3407                                              MONO_PATCH_INFO_METHOD_JUMP,
3408                                              ins->inst_p0);
3409                         s390_jcl (code, S390_CC_UN, 0);
3410                 }
3411                         break;
3412                 case OP_CHECK_THIS: {
3413                         /* ensure ins->sreg1 is not NULL */
3414                         s390_lg   (code, s390_r0, 0, ins->sreg1, 0);
3415                         s390_ltgr (code, s390_r0, s390_r0);
3416                 }
3417                         break;
3418                 case OP_ARGLIST: {
3419                         int offset = cfg->sig_cookie + cfg->stack_usage;
3420
3421                         if (s390_is_imm16 (offset))
3422                                 s390_lghi (code, s390_r0, offset);
3423                         else {
3424                                 s390_basr (code, s390_r13, 0);
3425                                 s390_j    (code, 6);
3426                                 s390_llong(code, offset);
3427                                 s390_lg   (code, s390_r0, 0, s390_r13, 0);
3428                         }
3429                         s390_agr  (code, s390_r0, cfg->frame_reg);
3430                         s390_stg  (code, s390_r0, 0, ins->sreg1, 0);
3431                 }
3432                         break;
3433                 case OP_FCALL: {
3434                         s390_basr (code, s390_r13, 0);
3435                         s390_j    (code, 6);
3436                         call = (MonoCallInst*)ins;
3437                         if (ins->flags & MONO_INST_HAS_METHOD)
3438                                 mono_add_patch_info (cfg, code-cfg->native_code,
3439                                                      MONO_PATCH_INFO_METHOD, 
3440                                                      call->method);
3441                         else
3442                                 mono_add_patch_info (cfg, code-cfg->native_code,
3443                                                      MONO_PATCH_INFO_ABS, 
3444                                                      call->fptr);
3445                         s390_llong(code, 0);
3446                         s390_lg   (code, s390_r14, 0, s390_r13, 4);
3447                         s390_basr (code, s390_r14, s390_r14);
3448                         if (call->signature->ret->type == MONO_TYPE_R4)
3449                                 s390_ldebr (code, s390_f0, s390_f0);
3450                 }
3451                         break;
3452                 case OP_LCALL:
3453                 case OP_VCALL:
3454                 case OP_VOIDCALL:
3455                 case OP_CALL: {
3456                         s390_basr (code, s390_r13, 0);
3457                         s390_j    (code, 6);
3458                         call = (MonoCallInst*)ins;
3459                         if (ins->flags & MONO_INST_HAS_METHOD)
3460                                 mono_add_patch_info (cfg, code-cfg->native_code,
3461                                                      MONO_PATCH_INFO_METHOD, 
3462                                                      call->method);
3463                         else
3464                                 mono_add_patch_info (cfg, code-cfg->native_code,
3465                                                      MONO_PATCH_INFO_ABS, 
3466                                                      call->fptr);
3467                         s390_llong(code, 0);
3468                         s390_lg   (code, s390_r14, 0, s390_r13, 4);
3469                         s390_basr (code, s390_r14, s390_r14);
3470                 }
3471                         break;
3472                 case OP_FCALL_REG: {
3473                         call = (MonoCallInst*)ins;
3474                         s390_lgr  (code, s390_r1, ins->sreg1);
3475                         s390_basr (code, s390_r14, s390_r1);
3476                         if (call->signature->ret->type == MONO_TYPE_R4)
3477                                 s390_ldebr (code, s390_f0, s390_f0);
3478                 }
3479                         break;
3480                 case OP_LCALL_REG:
3481                 case OP_VCALL_REG:
3482                 case OP_VOIDCALL_REG:
3483                 case OP_CALL_REG: {
3484                         s390_lgr  (code, s390_r1, ins->sreg1);
3485                         s390_basr (code, s390_r14, s390_r1);
3486                 }
3487                         break;
3488                 case OP_FCALL_MEMBASE: {
3489                         call = (MonoCallInst*)ins;
3490                         s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
3491                         s390_basr (code, s390_r14, s390_r1);
3492                         if (call->signature->ret->type == MONO_TYPE_R4)
3493                                 s390_ldebr (code, s390_f0, s390_f0);
3494                 }
3495                         break;
3496                 case OP_LCALL_MEMBASE:
3497                 case OP_VCALL_MEMBASE:
3498                 case OP_VOIDCALL_MEMBASE:
3499                 case OP_CALL_MEMBASE: {
3500                         s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
3501                         s390_basr (code, s390_r14, s390_r1);
3502                 }
3503                         break;
3504                 case OP_OUTARG: 
3505                         g_assert_not_reached ();
3506                         break;
3507                 case OP_LOCALLOC: {
3508                         int alloca_skip = S390_MINIMAL_STACK_SIZE + cfg->param_area;
3509                         int area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
3510                         s390_lgr  (code, s390_r1, ins->sreg1);
3511                         if (ins->flags & MONO_INST_INIT)
3512                                 s390_lgr  (code, s390_r0, ins->sreg1);
3513                         s390_aghi (code, s390_r1, 14);
3514                         s390_srlg (code, s390_r1, s390_r1, 0, 3);
3515                         s390_sllg (code, s390_r1, s390_r1, 0, 3);
3516                         if (cfg->method->save_lmf) {
3517                                 /*----------------------------------*/
3518                                 /* we have to adjust lmf ebp value  */
3519                                 /*----------------------------------*/
3520                                 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
3521
3522                                 s390_lgr (code, s390_r13, cfg->frame_reg);
3523                                 if (s390_is_imm16(lmfOffset))
3524                                         s390_aghi (code, s390_r13, lmfOffset);
3525                                 else {
3526                                         s390_basr (code, s390_r14, 0);
3527                                         s390_j    (code, 4);
3528                                         s390_word (code, lmfOffset);
3529                                         s390_agf  (code, s390_r13, 0, s390_r14, 4);
3530                                 }
3531                                 s390_lgr (code, s390_r14, STK_BASE);
3532                                 s390_sgr (code, s390_r14, s390_r1);
3533                                 s390_stg (code, s390_r14, 0, s390_r13,
3534                                           G_STRUCT_OFFSET(MonoLMF, ebp));
3535                         }
3536                         s390_lg   (code, s390_r13, 0, STK_BASE, 0);
3537                         s390_sgr  (code, STK_BASE, s390_r1);
3538                         s390_stg  (code, s390_r13, 0, STK_BASE, 0);
3539                         s390_la   (code, ins->dreg, 0, STK_BASE, area_offset);
3540                         s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
3541                         s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
3542                         if (ins->flags & MONO_INST_INIT) {
3543                                 s390_lgr  (code, s390_r1, s390_r0);
3544                                 s390_lgr  (code, s390_r0, ins->dreg);
3545                                 s390_lgr  (code, s390_r14, s390_r12);
3546                                 s390_lghi (code, s390_r13, 0);
3547                                 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
3548                                 s390_jo   (code, -2);
3549                                 s390_lgr  (code, s390_r12, s390_r14);
3550                         }
3551                 }
3552                         break;
3553                 case OP_THROW: {
3554                         s390_lgr  (code, s390_r2, ins->sreg1);
3555                         s390_basr (code, s390_r13, 0);
3556                         s390_j    (code, 6);
3557                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
3558                                              (gpointer) "mono_arch_throw_exception");
3559                         s390_llong(code, 0);
3560                         s390_lg   (code, s390_r14, 0, s390_r13, 4);
3561                         s390_basr (code, s390_r14, s390_r14);
3562                 }
3563                         break;
3564                 case OP_RETHROW: {
3565                         s390_lgr  (code, s390_r2, ins->sreg1);
3566                         s390_basr (code, s390_r13, 0);
3567                         s390_j    (code, 6);
3568                         mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD, 
3569                                              (gpointer) "mono_arch_rethrow_exception");
3570                         s390_llong(code, 0);
3571                         s390_lg   (code, s390_r14, 0, s390_r13, 4);
3572                         s390_basr (code, s390_r14, s390_r14);
3573                 }
3574                         break;
3575                 case OP_START_HANDLER: {
3576                         S390_LONG (code, stg, stg, s390_r14, 0, 
3577                                    ins->inst_left->inst_basereg, 
3578                                    ins->inst_left->inst_offset);
3579                 }
3580                         break;
3581                 case OP_ENDFILTER: {
3582                         if (ins->sreg1 != s390_r2)
3583                                 s390_lgr(code, s390_r2, ins->sreg1);
3584                         S390_LONG (code, lg, lg, s390_r14, 0, 
3585                                    ins->inst_left->inst_basereg, 
3586                                    ins->inst_left->inst_offset);
3587                         s390_br  (code, s390_r14);
3588                 }
3589                         break;
3590                 case OP_ENDFINALLY: {
3591                         S390_LONG (code, lg, lg, s390_r14, 0, 
3592                                    ins->inst_left->inst_basereg, 
3593                                    ins->inst_left->inst_offset);
3594                         s390_br  (code, s390_r14);
3595                 }
3596                         break;
3597                 case OP_CALL_HANDLER: {
3598                         mono_add_patch_info (cfg, code-cfg->native_code, 
3599                                              MONO_PATCH_INFO_BB, ins->inst_target_bb);
3600                         s390_brasl (code, s390_r14, 0);
3601                 }
3602                         break;
3603                 case OP_LABEL: {
3604                         ins->inst_c0 = code - cfg->native_code;
3605                 }
3606                         break;
3607                 case OP_BR: 
3608                         EMIT_UNCOND_BRANCH(ins);
3609                         break;
3610                 case OP_BR_REG: {
3611                         s390_br  (code, ins->sreg1);
3612                 }
3613                         break;
3614                 case OP_CEQ: 
3615                 case OP_ICEQ: {
3616                         s390_lghi(code, ins->dreg, 1);
3617                         s390_jz  (code, 4);
3618                         s390_lghi(code, ins->dreg, 0);
3619                 }
3620                         break;
3621                 case OP_CLT: 
3622                 case OP_ICLT: {
3623                         s390_lghi(code, ins->dreg, 1);
3624                         s390_jl  (code, 4);
3625                         s390_lghi(code, ins->dreg, 0);
3626                 }
3627                         break;
3628                 case OP_CLT_UN:
3629                 case OP_ICLT_UN: {
3630                         s390_lghi(code, ins->dreg, 1);
3631                         s390_jlo (code, 4);
3632                         s390_lghi(code, ins->dreg, 0);
3633                 }
3634                         break;
3635                 case OP_CGT: 
3636                 case OP_ICGT: {
3637                         s390_lghi(code, ins->dreg, 1);
3638                         s390_jh  (code, 4);
3639                         s390_lghi(code, ins->dreg, 0);
3640                 }
3641                         break;
3642                 case OP_CGT_UN:
3643                 case OP_ICGT_UN: {
3644                         s390_lghi(code, ins->dreg, 1);
3645                         s390_jho (code, 4);
3646                         s390_lghi(code, ins->dreg, 0);
3647                 }
3648                         break;
3649                 case OP_COND_EXC_EQ:
3650                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
3651                         break;
3652                 case OP_COND_EXC_NE_UN:
3653                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
3654                         break;
3655                 case OP_COND_EXC_LT:
3656                 case OP_COND_EXC_LT_UN:
3657                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
3658                         break;
3659                 case OP_COND_EXC_GT:
3660                 case OP_COND_EXC_GT_UN:
3661                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
3662                         break;
3663                 case OP_COND_EXC_GE:
3664                 case OP_COND_EXC_GE_UN:
3665                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
3666                         break;
3667                 case OP_COND_EXC_LE:
3668                 case OP_COND_EXC_LE_UN:
3669                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
3670                         break;
3671                 case OP_COND_EXC_OV:
3672                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
3673                         break;
3674                 case OP_COND_EXC_NO:
3675                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
3676                         break;
3677                 case OP_COND_EXC_C:
3678                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
3679                         break;
3680                 case OP_COND_EXC_NC:
3681                         EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
3682                         break;
3683                 case OP_LBEQ:
3684                 case OP_IBEQ:
3685                         EMIT_COND_BRANCH (ins, S390_CC_EQ);
3686                         break;  
3687                 case OP_LBNE_UN:
3688                 case OP_IBNE_UN:
3689                         EMIT_COND_BRANCH (ins, S390_CC_NE);
3690                         break;  
3691                 case OP_LBLT:
3692                 case OP_LBLT_UN:
3693                 case OP_IBLT:
3694                 case OP_IBLT_UN:
3695                         EMIT_COND_BRANCH (ins, S390_CC_LT);
3696                         break;  
3697                 case OP_LBGT:
3698                 case OP_LBGT_UN:
3699                 case OP_IBGT:
3700                 case OP_IBGT_UN:
3701                         EMIT_COND_BRANCH (ins, S390_CC_GT);
3702                         break;  
3703                 case OP_LBGE:
3704                 case OP_LBGE_UN:
3705                 case OP_IBGE:
3706                 case OP_IBGE_UN:
3707                         EMIT_COND_BRANCH (ins, S390_CC_GE);
3708                         break;  
3709                 case OP_LBLE:
3710                 case OP_LBLE_UN:
3711                 case OP_IBLE:
3712                 case OP_IBLE_UN:
3713                         EMIT_COND_BRANCH (ins, S390_CC_LE);
3714                         break;
3715
3716                 /* floating point opcodes */
3717                 case OP_R8CONST: {
3718                         if (*((float *) ins->inst_p0) == 0) {
3719                                 s390_lzdr (code, ins->dreg);
3720                         } else {
3721                                 s390_basr  (code, s390_r13, 0);
3722                                 s390_j     (code, 6);
3723                                 s390_llong (code, ins->inst_p0);
3724                                 s390_lg    (code, s390_r13, 0, s390_r13, 4);
3725                                 s390_ld    (code, ins->dreg, 0, s390_r13, 0);
3726                         }
3727                 }
3728                         break;
3729                 case OP_R4CONST: {
3730                         if (*((float *) ins->inst_p0) == 0) {
3731                                 s390_lzdr (code, ins->dreg);
3732                         } else {
3733                                 s390_basr (code, s390_r13, 0);
3734                                 s390_j    (code, 6);
3735                                 s390_llong(code, ins->inst_p0);
3736                                 s390_lg   (code, s390_r13, 0, s390_r13, 4);
3737                                 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
3738                         }
3739                 }
3740                         break;
3741                 case OP_STORER8_MEMBASE_REG: {
3742                         S390_LONG (code, stdy, std, ins->sreg1, 0, 
3743                                    ins->inst_destbasereg, ins->inst_offset);
3744                 }
3745                         break;
3746                 case OP_LOADR8_MEMBASE: {
3747                         S390_LONG (code, ldy, ld, ins->dreg, 0, 
3748                                    ins->inst_basereg, ins->inst_offset);
3749                 }
3750                         break;
3751                 case OP_STORER4_MEMBASE_REG: {
3752                         s390_ledbr (code, s390_f15, ins->sreg1);
3753                         S390_LONG (code, stey, ste, s390_f15, 0, 
3754                                    ins->inst_destbasereg, ins->inst_offset);
3755                 }
3756                         break;
3757                 case OP_LOADR4_MEMBASE: {
3758                         S390_LONG (code, ldy, ld, s390_f15, 0, 
3759                                    ins->inst_basereg, ins->inst_offset);
3760                         s390_ldebr (code, ins->dreg, s390_f15);
3761                 }
3762                         break;
3763                 case OP_LCONV_TO_R_UN: {
3764                         s390_cdgbr (code, ins->dreg, ins->sreg1);
3765                         s390_ltgr  (code, ins->sreg1, ins->sreg1);
3766                         s390_jnl   (code, 12);
3767                         s390_basr  (code, s390_r13, 0);
3768                         s390_j     (code, 6);
3769                         s390_word  (code, 0x41f00000);
3770                         s390_word  (code, 0);
3771                         s390_adb   (code, ins->dreg, 0, s390_r13, 4);
3772                 }
3773                         break;
3774                 case OP_LCONV_TO_R4:
3775                 case OP_ICONV_TO_R4: {
3776                         s390_cdgbr (code, ins->dreg, ins->sreg1);
3777                 }
3778                         break;
3779                 case OP_LCONV_TO_R8:
3780                 case OP_ICONV_TO_R8: {
3781                         s390_cdgbr (code, ins->dreg, ins->sreg1);
3782                 }
3783                         break;
3784                 case OP_FCONV_TO_I1:
3785                         code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, TRUE);
3786                         break;
3787                 case OP_FCONV_TO_U1:
3788                         code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
3789                         break;
3790                 case OP_FCONV_TO_I2:
3791                         code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, TRUE);
3792                         break;
3793                 case OP_FCONV_TO_U2:
3794                         code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
3795                         break;
3796                 case OP_FCONV_TO_I4:
3797                 case OP_FCONV_TO_I:
3798                         code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, TRUE);
3799                         break;
3800                 case OP_FCONV_TO_U4:
3801                 case OP_FCONV_TO_U:
3802                         code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
3803                         break;
3804                 case OP_FCONV_TO_I8:
3805                         s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
3806                         break;
3807                 case OP_LCONV_TO_OVF_I: {
3808                         /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
3809                         short int *o[5];
3810                         s390_ltgr (code, ins->sreg2, ins->sreg2);
3811                         s390_jnl  (code, 0); CODEPTR(code, o[0]);
3812                         s390_ltgr (code, ins->sreg1, ins->sreg1);
3813                         s390_jnl  (code, 0); CODEPTR(code, o[1]);
3814                         s390_lhi  (code, s390_r13, -1);
3815                         s390_cgr  (code, ins->sreg1, s390_r13);
3816                         s390_jnz  (code, 0); CODEPTR(code, o[2]);
3817                         if (ins->dreg != ins->sreg2)
3818                                 s390_lgr  (code, ins->dreg, ins->sreg2);
3819                         s390_j    (code, 0); CODEPTR(code, o[3]);
3820                         PTRSLOT(code, o[0]);
3821                         s390_jz   (code, 0); CODEPTR(code, o[4]);
3822                         PTRSLOT(code, o[1]);
3823                         PTRSLOT(code, o[2]);
3824                         mono_add_patch_info (cfg, code - cfg->native_code, 
3825                                              MONO_PATCH_INFO_EXC, "OverflowException");
3826                         s390_brasl (code, s390_r14, 0);
3827                         PTRSLOT(code, o[3]);
3828                         PTRSLOT(code, o[4]);
3829                 }
3830                         break;
3831                 case OP_ABS: {
3832                         s390_lpdbr (code, ins->dreg, ins->sreg1);
3833                 }
3834                         break;
3835                 case OP_SQRT: {
3836                         s390_sqdbr (code, ins->dreg, ins->sreg1);
3837                 }
3838                         break;
3839                 case OP_FADD: {
3840                         CHECK_SRCDST_COM_F;
3841                         s390_adbr (code, ins->dreg, src2);
3842                 }
3843                         break;
3844                 case OP_FSUB: {
3845                         CHECK_SRCDST_NCOM_F;
3846                         s390_sdbr (code, ins->dreg, src2);
3847                 }
3848                         break;          
3849                 case OP_FMUL: {
3850                         CHECK_SRCDST_COM_F;
3851                         s390_mdbr (code, ins->dreg, src2);
3852                 }
3853                         break;          
3854                 case OP_FDIV: {
3855                         CHECK_SRCDST_NCOM_F;
3856                         s390_ddbr (code, ins->dreg, src2);
3857                 }
3858                         break;          
3859                 case OP_FNEG: {
3860                         s390_lcdbr (code, ins->dreg, ins->sreg1);
3861                 }
3862                         break;          
3863                 case OP_FREM: {
3864                         CHECK_SRCDST_NCOM_F;
3865                         s390_didbr (code, ins->dreg, src2, 5, s390_f15);
3866                 }
3867                         break;
3868                 case OP_FCOMPARE: {
3869                         s390_cdbr (code, ins->sreg1, ins->sreg2);
3870                 }
3871                         break;
3872                 case OP_FCEQ: {
3873                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
3874                         s390_lghi  (code, ins->dreg, 1);
3875                         s390_je    (code, 4);
3876                         s390_lghi  (code, ins->dreg, 0);
3877                 }
3878                         break;
3879                 case OP_FCLT: {
3880                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
3881                         s390_lghi  (code, ins->dreg, 1);
3882                         s390_jl    (code, 4);
3883                         s390_lghi  (code, ins->dreg, 0);
3884                 }
3885                         break;
3886                 case OP_FCLT_UN: {
3887                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
3888                         s390_lghi  (code, ins->dreg, 1);
3889                         s390_jlo   (code, 4);
3890                         s390_lghi  (code, ins->dreg, 0);
3891                 }
3892                         break;
3893                 case OP_FCGT: {
3894                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
3895                         s390_lghi  (code, ins->dreg, 1);
3896                         s390_jh    (code, 4);
3897                         s390_lghi  (code, ins->dreg, 0);
3898                 }
3899                         break;
3900                 case OP_FCGT_UN: {
3901                         s390_cdbr  (code, ins->sreg1, ins->sreg2);
3902                         s390_lghi  (code, ins->dreg, 1);
3903                         s390_jho   (code, 4);
3904                         s390_lghi  (code, ins->dreg, 0);
3905                 }
3906                         break;
3907                 case OP_FBEQ: {
3908                         short *o;
3909                         s390_jo (code, 0); CODEPTR(code, o);
3910                         EMIT_COND_BRANCH (ins, S390_CC_EQ);
3911                         PTRSLOT (code, o);
3912                 }
3913                         break;
3914                 case OP_FBNE_UN:
3915                         EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
3916                         break;
3917                 case OP_FBLT: {
3918                         short *o;
3919                         s390_jo (code, 0); CODEPTR(code, o);
3920                         EMIT_COND_BRANCH (ins, S390_CC_LT);
3921                         PTRSLOT (code, o);
3922                 }
3923                         break;
3924                 case OP_FBLT_UN:
3925                         EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
3926                         break;
3927                 case OP_FBGT: {
3928                         short *o;
3929                         s390_jo (code, 0); CODEPTR(code, o);
3930                         EMIT_COND_BRANCH (ins, S390_CC_GT);
3931                         PTRSLOT (code, o);
3932                 }
3933                         break;
3934                 case OP_FBGT_UN:
3935                         EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
3936                         break;
3937                 case OP_FBGE: {
3938                         short *o;
3939                         s390_jo (code, 0); CODEPTR(code, o);
3940                         EMIT_COND_BRANCH (ins, S390_CC_GE);
3941                         PTRSLOT (code, o);
3942                 }
3943                         break;
3944                 case OP_FBGE_UN:
3945                         EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
3946                         break;
3947                 case OP_FBLE: {
3948                         short *o;
3949                         s390_jo (code, 0); CODEPTR(code, o);
3950                         EMIT_COND_BRANCH (ins, S390_CC_LE);
3951                         PTRSLOT (code, o);
3952                 }
3953                         break;
3954                 case OP_FBLE_UN:
3955                         EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
3956                         break;
3957                 case OP_CKFINITE: {
3958                         short *o;
3959                         s390_lhi  (code, s390_r13, 0x7f);
3960                         s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
3961                         s390_jz   (code, 0); CODEPTR(code, o);
3962                         mono_add_patch_info (cfg, code - cfg->native_code, 
3963                                              MONO_PATCH_INFO_EXC, "ArithmeticException");
3964                         s390_brasl (code, s390_r14,0);
3965                         PTRSLOT(code, o);
3966                 }
3967                         break;
3968                 case OP_S390_MOVE: {
3969                         if (ins->backend.size > 0) {
3970                                 if (ins->backend.size <= 256) {
3971                                         s390_mvc  (code, ins->backend.size, ins->dreg, 
3972                                                    ins->inst_offset, ins->sreg1, ins->inst_imm);
3973                                 } else {
3974                                         s390_lgr  (code, s390_r0, ins->dreg);
3975                                         if (s390_is_imm16 (ins->inst_offset)) {
3976                                                 s390_aghi (code, s390_r0, ins->inst_offset);
3977                                         } else {
3978                                                 s390_basr (code, s390_r13, 0);
3979                                                 s390_j    (code, 6);
3980                                                 s390_llong(code, ins->inst_offset);
3981                                                 s390_a    (code, s390_r0, 0, s390_r13, 4);
3982                                         }
3983                                         s390_lgr  (code, s390_r12, ins->sreg1);
3984                                         if (s390_is_imm16 (ins->inst_imm)) {
3985                                                 s390_aghi (code, s390_r12, ins->inst_imm);
3986                                         } else {
3987                                                 s390_basr (code, s390_r13, 0);
3988                                                 s390_j    (code, 6);
3989                                                 s390_llong(code, ins->inst_imm);
3990                                                 s390_ag   (code, s390_r12, 0, s390_r13, 4);
3991                                         }
3992                                         s390_lgr  (code, s390_r1, ins->sreg1);
3993                                         s390_lgr  (code, s390_r13, s390_r1);
3994                                         s390_mvcle(code, s390_r0, s390_r12, 0, 0);
3995                                         s390_jo   (code, -2);
3996                                 }
3997                         }
3998                 }
3999                         break;
4000                 case OP_ATOMIC_ADD_I8: {
4001                         s390_lgr (code, s390_r1, ins->sreg2);
4002                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4003                         s390_agr (code, s390_r1, s390_r0);
4004                         s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4005                         s390_jnz (code, -10);
4006                         s390_lgr (code, ins->dreg, s390_r1);
4007                 }
4008                         break;  
4009                 case OP_ATOMIC_ADD_NEW_I8: {
4010                         s390_lgr (code, s390_r1, ins->sreg2);
4011                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4012                         s390_agr (code, s390_r1, s390_r0);
4013                         s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4014                         s390_jnz (code, -10);
4015                         s390_lgr (code, ins->dreg, s390_r1);
4016                 }
4017                         break;  
4018                 case OP_ATOMIC_EXCHANGE_I8: {
4019                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4020                         s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4021                         s390_jnz (code, -6);
4022                         s390_lgr (code, ins->dreg, s390_r0);
4023                 }
4024                         break;  
4025                 case OP_ATOMIC_ADD_I4: {
4026                         s390_lgfr(code, s390_r1, ins->sreg2);
4027                         s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4028                         s390_agr (code, s390_r1, s390_r0);
4029                         s390_cs  (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4030                         s390_jnz (code, -9);
4031                         s390_lgfr(code, ins->dreg, s390_r1);
4032                 }
4033                         break;  
4034                 case OP_ATOMIC_ADD_NEW_I4: {
4035                         s390_lgfr(code, s390_r1, ins->sreg2);
4036                         s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4037                         s390_agr (code, s390_r1, s390_r0);
4038                         s390_cs  (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4039                         s390_jnz (code, -9);
4040                         s390_lgfr(code, ins->dreg, s390_r1);
4041                 }
4042                         break;  
4043                 case OP_ATOMIC_EXCHANGE_I4: {
4044                         s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4045                         s390_cs  (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4046                         s390_jnz (code, -4);
4047                         s390_lgfr(code, ins->dreg, s390_r0);
4048                 }
4049                         break;  
4050                 case OP_S390_BKCHAIN: {
4051                         s390_lgr  (code, ins->dreg, ins->sreg1);
4052                         if (s390_is_imm16 (cfg->stack_offset)) {
4053                                 s390_aghi (code, ins->dreg, cfg->stack_offset);
4054                         } else {
4055                                 s390_basr (code, s390_r13, 0);
4056                                 s390_j    (code, 6);
4057                                 s390_llong(code, cfg->stack_offset);
4058                                 s390_ag   (code, ins->dreg, 0, s390_r13, 4);
4059                         }
4060                 }
4061                         break;  
4062                 case OP_MEMORY_BARRIER: {
4063                 }
4064                         break;
4065                 default:
4066                         g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
4067                         g_assert_not_reached ();
4068                 }
4069
4070                 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
4071                         g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
4072                                    mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
4073                         g_assert_not_reached ();
4074                 }
4075                
4076                 cpos += max_len;
4077
4078                 last_offset = offset;
4079         }
4080
4081         cfg->code_len = code - cfg->native_code;
4082 }
4083
4084 /*========================= End of Function ========================*/
4085
4086 /*------------------------------------------------------------------*/
4087 /*                                                                  */
4088 /* Name         - mono_arch_register_lowlevel_calls                 */
4089 /*                                                                  */
4090 /* Function     - Register routines to help with --trace operation. */
4091 /*                                                                  */
4092 /*------------------------------------------------------------------*/
4093
4094 void
4095 mono_arch_register_lowlevel_calls (void)
4096 {
4097         mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr", NULL, TRUE);
4098 }
4099
4100 /*========================= End of Function ========================*/
4101
4102 /*------------------------------------------------------------------*/
4103 /*                                                                  */
4104 /* Name         - mono_arch_patch_code                              */
4105 /*                                                                  */
4106 /* Function     - Process the patch data created during the         */
4107 /*                instruction build process. This resolves jumps,   */
4108 /*                calls, variables etc.                             */
4109 /*                                                                  */
4110 /*------------------------------------------------------------------*/
4111
4112 void
4113 mono_arch_patch_code (MonoMethod *method, MonoDomain *domain, 
4114                       guint8 *code, MonoJumpInfo *ji, gboolean run_cctors)
4115 {
4116         MonoJumpInfo *patch_info;
4117
4118         for (patch_info = ji; patch_info; patch_info = patch_info->next) {
4119                 unsigned char *ip = patch_info->ip.i + code;
4120                 gconstpointer target = NULL;
4121
4122                 target = mono_resolve_patch_target (method, domain, code, 
4123                                                     patch_info, run_cctors);
4124
4125                 switch (patch_info->type) {
4126                         case MONO_PATCH_INFO_IP:
4127                         case MONO_PATCH_INFO_EXC_NAME:
4128                         case MONO_PATCH_INFO_LDSTR:
4129                         case MONO_PATCH_INFO_TYPE_FROM_HANDLE: 
4130                         case MONO_PATCH_INFO_LDTOKEN: 
4131                         case MONO_PATCH_INFO_EXC:
4132                         case MONO_PATCH_INFO_ABS:
4133                         case MONO_PATCH_INFO_METHOD:
4134                         case MONO_PATCH_INFO_INTERNAL_METHOD:
4135                         case MONO_PATCH_INFO_CLASS_INIT:
4136                                 s390_patch_addr (ip, (guint64) target);
4137                                 continue;
4138                         case MONO_PATCH_INFO_SWITCH: 
4139                                 /*----------------------------------*/
4140                                 /* ip points at the basr r13,0/j +4 */
4141                                 /* instruction the vtable value     */
4142                                 /* follows this (i.e. ip+6)         */
4143                                 /*----------------------------------*/
4144                                 *((gconstpointer *)(ip+6)) = target;
4145                                 continue;
4146                         case MONO_PATCH_INFO_METHODCONST:
4147                         case MONO_PATCH_INFO_CLASS:
4148                         case MONO_PATCH_INFO_IMAGE:
4149                         case MONO_PATCH_INFO_FIELD:
4150                         case MONO_PATCH_INFO_IID:
4151                                 target = S390_RELATIVE(target, ip);
4152                                 s390_patch_rel (ip, (guint64) target);
4153                                 continue;
4154                         case MONO_PATCH_INFO_R4:
4155                         case MONO_PATCH_INFO_R8:
4156                         case MONO_PATCH_INFO_METHOD_REL:
4157                                 g_assert_not_reached ();
4158                                 continue;
4159                         default:
4160                                 target = S390_RELATIVE(target, ip);
4161                                 ip += 2;
4162                                 s390_patch_rel (ip, (guint64) target);
4163                 }
4164         }
4165 }
4166
4167 /*========================= End of Function ========================*/
4168
4169 /*------------------------------------------------------------------*/
4170 /*                                                                  */
4171 /* Name         - emit_load_volatile_registers                      */
4172 /*                                                                  */
4173 /* Function     - Emit the instructions to reload parameter regist- */
4174 /*                registers for use with "tail" operations.         */
4175 /*                                                                  */
4176 /*                The register loading operations performed here    */
4177 /*                are the mirror of the store operations performed  */
4178 /*                in mono_arch_emit_prolog and need to be kept in   */
4179 /*                synchronization with it.                          */
4180 /*                                                                  */
4181 /*------------------------------------------------------------------*/
4182
4183 guint8 *
4184 emit_load_volatile_registers (guint8 *code, MonoCompile *cfg)
4185 {
4186         MonoInst *inst;
4187         MonoMethod *method = cfg->method;
4188         MonoMethodSignature *sig = mono_method_signature(method);
4189         int pos = 0, i;
4190         CallInfo *cinfo;
4191
4192         cinfo = get_call_info (NULL, NULL, sig, sig->pinvoke);
4193
4194         if (cinfo->struct_ret) {
4195                 ArgInfo *ainfo = &cinfo->ret;
4196                 inst         = cfg->vret_addr;
4197                 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4198         }
4199
4200         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
4201                 ArgInfo *ainfo = cinfo->args + i;
4202                 inst = cfg->args [pos];
4203
4204                 if (inst->opcode == OP_REGVAR) {
4205                         if (ainfo->regtype == RegTypeGeneral)
4206                                 s390_lgr (code, ainfo->reg, inst->dreg);
4207                         else if (ainfo->regtype == RegTypeFP) {
4208                                 if (inst->dreg != ainfo->reg) {
4209                                         if (ainfo->size == 4) {
4210                                                 s390_ldebr (code, ainfo->reg, inst->dreg);
4211                                         } else {
4212                                                 s390_ldr   (code, ainfo->reg, inst->dreg);
4213                                         }
4214                                 }
4215                         }
4216                         else if (ainfo->regtype == RegTypeBase) {
4217                         } else
4218                                 g_assert_not_reached ();
4219                 } else {
4220                         if (ainfo->regtype == RegTypeGeneral) {
4221                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
4222                                         g_assert_not_reached();
4223                                 switch (ainfo->size) {
4224                                 case 1:
4225                                         s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4226                                         break;
4227                                 case 2:
4228                                         s390_lgh  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4229                                         break;
4230                                 case 4: 
4231                                         s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4232                                         break;
4233                                 case 8:
4234                                         s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4235                                         break;
4236                                 }
4237                         } else if (ainfo->regtype == RegTypeBase) {
4238                         } else if (ainfo->regtype == RegTypeFP) {
4239                                 if (ainfo->size == 8)
4240                                         s390_ld  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4241                                 else if (ainfo->size == 4)
4242                                         s390_le  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4243                                 else
4244                                         g_assert_not_reached ();
4245                         } else if (ainfo->regtype == RegTypeStructByVal) {
4246                                 if (ainfo->reg != STK_BASE) {
4247                                         switch (ainfo->size) {
4248                                         case 1:
4249                                                 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4250                                                 break;
4251                                         case 2:
4252                                                 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4253                                                 break;
4254                                         case 4:
4255                                                 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4256                                                 break;
4257                                         case 8:
4258                                                 s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4259                                                 break;
4260                                         }
4261                                 }
4262                         } else if (ainfo->regtype == RegTypeStructByAddr) {
4263                                 if (ainfo->reg != STK_BASE) {
4264                                         s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4265                                 }
4266                         } else
4267                                 g_assert_not_reached ();
4268                 }
4269                 pos++;
4270         }
4271
4272         return code;
4273 }
4274
4275 /*========================= End of Function ========================*/
4276
4277 /*------------------------------------------------------------------*/
4278 /*                                                                  */
4279 /* Name         - mono_arch_emit_prolog                             */
4280 /*                                                                  */
4281 /* Function     - Create the instruction sequence for a function    */
4282 /*                prolog.                                           */
4283 /*                                                                  */
4284 /*------------------------------------------------------------------*/
4285
4286 guint8 *
4287 mono_arch_emit_prolog (MonoCompile *cfg)
4288 {
4289         MonoMethod *method = cfg->method;
4290         MonoBasicBlock *bb;
4291         MonoMethodSignature *sig;
4292         MonoInst *inst;
4293         int alloc_size, pos, max_offset, i;
4294         guint8 *code;
4295         CallInfo *cinfo;
4296         int tracing = 0;
4297         int lmfOffset;
4298
4299         cfg->code_size   = 512;
4300
4301         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
4302                 tracing         = 1;
4303                 cfg->code_size += 256;
4304         }
4305
4306         if (method->save_lmf)
4307                 cfg->code_size += 200;
4308
4309         cfg->native_code = code = g_malloc (cfg->code_size);
4310
4311         s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
4312
4313         if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
4314                 cfg->used_int_regs |= 1 << 11;
4315         }
4316
4317         alloc_size = cfg->stack_offset;
4318
4319         cfg->stack_usage = alloc_size;
4320         s390_lgr  (code, s390_r11, STK_BASE);
4321         if (s390_is_imm16 (alloc_size)) {
4322                 s390_aghi (code, STK_BASE, -alloc_size);
4323         } else { 
4324                 int stackSize = alloc_size;
4325                 while (stackSize > 32767) {
4326                         s390_aghi (code, STK_BASE, -32767);
4327                         stackSize -= 32767;
4328                 }
4329                 s390_aghi (code, STK_BASE, -stackSize);
4330         }
4331         s390_stg  (code, s390_r11, 0, STK_BASE, 0);
4332
4333         if (cfg->frame_reg != STK_BASE)
4334                 s390_lgr (code, s390_r11, STK_BASE);
4335
4336         /* compute max_offset in order to use short forward jumps
4337          * we always do it on s390 because the immediate displacement
4338          * for jumps is too small 
4339          */
4340         max_offset = 0;
4341         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
4342                 MonoInst *ins;
4343                 bb->max_offset = max_offset;
4344
4345                 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
4346                         max_offset += 6; 
4347
4348                 MONO_BB_FOR_EACH_INS (bb, ins)
4349                         max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
4350         }
4351
4352         /* load arguments allocated to register from the stack */
4353         sig = mono_method_signature (method);
4354         pos = 0;
4355
4356         cinfo = get_call_info (cfg, cfg->mempool, sig, sig->pinvoke);
4357
4358         if (cinfo->struct_ret) {
4359                 ArgInfo *ainfo = &cinfo->ret;
4360                 inst         = cfg->vret_addr;
4361                 inst->backend.size = ainfo->vtsize;
4362                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4363         }
4364
4365         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
4366                 ArgInfo *ainfo = cinfo->args + i;
4367                 inst = cfg->args [pos];
4368
4369                 if (inst->opcode == OP_REGVAR) {
4370                         if (ainfo->regtype == RegTypeGeneral)
4371                                 s390_lgr (code, inst->dreg, ainfo->reg);
4372                         else if (ainfo->regtype == RegTypeFP) {
4373                                 if (inst->dreg != ainfo->reg) {
4374                                         if (ainfo->size == 4) {
4375                                                 s390_ledbr (code, inst->dreg, ainfo->reg);
4376                                         } else {
4377                                                 s390_ldr   (code, inst->dreg, ainfo->reg);
4378                                         }
4379                                 }
4380                         }
4381                         else if (ainfo->regtype == RegTypeBase) {
4382                                 s390_lgr  (code, s390_r13, STK_BASE);
4383                                 s390_aghi (code, s390_r13, alloc_size);
4384                                 s390_lg   (code, inst->dreg, 0, s390_r13, ainfo->offset);
4385                         } else
4386                                 g_assert_not_reached ();
4387
4388                         if (cfg->verbose_level > 2)
4389                                 g_print ("Argument %d assigned to register %s\n", 
4390                                          pos, mono_arch_regname (inst->dreg));
4391                 } else {
4392                         if (ainfo->regtype == RegTypeGeneral) {
4393                                 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
4394                                         g_assert_not_reached();
4395                                 switch (ainfo->size) {
4396                                 case 1:
4397                                         s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4398                                         break;
4399                                 case 2:
4400                                         s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4401                                         break;
4402                                 case 4: 
4403                                         s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4404                                         break;
4405                                 case 8:
4406                                         s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4407                                         break;
4408                                 }
4409                         } else if (ainfo->regtype == RegTypeBase) {
4410                         } else if (ainfo->regtype == RegTypeFP) {
4411                                 if (ainfo->size == 8)
4412                                         s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4413                                 else if (ainfo->size == 4)
4414                                         s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4415                                 else
4416                                         g_assert_not_reached ();
4417                         } else if (ainfo->regtype == RegTypeStructByVal) {
4418                                 int doffset = inst->inst_offset;
4419                                 int reg;
4420                                 if (ainfo->reg != STK_BASE)
4421                                         reg = ainfo->reg;
4422                                 else {
4423                                         reg = s390_r0;
4424                                         s390_lgr  (code, s390_r13, STK_BASE);
4425                                         s390_aghi (code, s390_r13, alloc_size);
4426                                 }
4427                                 switch (ainfo->size) {
4428                                         case 1:
4429                                                 if (ainfo->reg == STK_BASE)
4430                                                         s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
4431                                                 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
4432                                                 break;
4433                                         case 2:
4434                                                 if (ainfo->reg == STK_BASE)
4435                                                         s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
4436                                                 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
4437                                                 break;
4438                                         case 4:
4439                                                 if (ainfo->reg == STK_BASE)
4440                                                         s390_l  (code, reg, 0, s390_r13, ainfo->offset+4);
4441                                                 s390_st (code, reg, 0, inst->inst_basereg, doffset);
4442                                                 break;
4443                                         case 8:
4444                                                 if (ainfo->reg == STK_BASE)
4445                                                         s390_lg  (code, reg, 0, s390_r13, ainfo->offset);
4446                                                 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
4447                                                 break;
4448                                 }
4449                         } else if (ainfo->regtype == RegTypeStructByAddr) {
4450                                 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
4451                         } else
4452                                 g_assert_not_reached ();
4453                 }
4454                 pos++;
4455         }
4456
4457         if (method->save_lmf) {
4458                 /*---------------------------------------------------------------*/
4459                 /* we build the MonoLMF structure on the stack - see mini-s390.h */
4460                 /*---------------------------------------------------------------*/
4461                 lmfOffset = alloc_size - sizeof(MonoLMF);       
4462                                                                                         
4463                 s390_lgr   (code, s390_r13, cfg->frame_reg);            
4464                 s390_aghi  (code, s390_r13, lmfOffset);                                 
4465                                                                                         
4466                 /*---------------------------------------------------------------*/
4467                 /* Preserve the parameter registers while we fix up the lmf      */
4468                 /*---------------------------------------------------------------*/
4469                 s390_stmg  (code, s390_r2, s390_r6, s390_r13,
4470                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));
4471
4472                 /*---------------------------------------------------------------*/
4473                 /* On return from this call r2 have the address of the &lmf      */
4474                 /*---------------------------------------------------------------*/
4475                 s390_basr(code, s390_r10, 0);
4476                 s390_j   (code, 6);
4477                 mono_add_patch_info (cfg, code - cfg->native_code, 
4478                                      MONO_PATCH_INFO_INTERNAL_METHOD, 
4479                                      (gpointer)"mono_get_lmf_addr");
4480                 s390_llong(code, 0);
4481                 s390_lg   (code, s390_r1, 0, s390_r10, 4);
4482                 s390_basr (code, s390_r14, s390_r1);
4483
4484                 /*---------------------------------------------------------------*/     
4485                 /* Set lmf.lmf_addr = jit_tls->lmf                               */     
4486                 /*---------------------------------------------------------------*/     
4487                 s390_stg   (code, s390_r2, 0, s390_r13,                                 
4488                             G_STRUCT_OFFSET(MonoLMF, lmf_addr));                        
4489                                                                                         
4490                 /*---------------------------------------------------------------*/     
4491                 /* Get current lmf                                               */     
4492                 /*---------------------------------------------------------------*/     
4493                 s390_lg    (code, s390_r0, 0, s390_r2, 0);                              
4494                                                                                         
4495                 /*---------------------------------------------------------------*/     
4496                 /* Set our lmf as the current lmf                                */     
4497                 /*---------------------------------------------------------------*/     
4498                 s390_stg   (code, s390_r13, 0, s390_r2, 0);                             
4499                                                                                         
4500                 /*---------------------------------------------------------------*/     
4501                 /* Have our lmf.previous_lmf point to the last lmf               */     
4502                 /*---------------------------------------------------------------*/     
4503                 s390_stg   (code, s390_r0, 0, s390_r13,                                 
4504                             G_STRUCT_OFFSET(MonoLMF, previous_lmf));                    
4505                                                                                         
4506                 /*---------------------------------------------------------------*/     
4507                 /* save method info                                              */     
4508                 /*---------------------------------------------------------------*/     
4509                 s390_basr  (code, s390_r1, 0);                                          
4510                 s390_j     (code, 6);
4511                 s390_llong (code, method);                                              
4512                 s390_lg    (code, s390_r1, 0, s390_r1, 4);                      
4513                 s390_stg   (code, s390_r1, 0, s390_r13,                                 
4514                             G_STRUCT_OFFSET(MonoLMF, method));                          
4515                                                                                 
4516                 /*---------------------------------------------------------------*/     
4517                 /* save the current IP                                           */     
4518                 /*---------------------------------------------------------------*/     
4519                 s390_stg   (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
4520                 s390_basr  (code, s390_r1, 0);
4521                 s390_stg   (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); 
4522                                                                                         
4523                 /*---------------------------------------------------------------*/     
4524                 /* Save general and floating point registers                     */     
4525                 /*---------------------------------------------------------------*/     
4526                 s390_stmg  (code, s390_r2, s390_r12, s390_r13,                          
4527                             G_STRUCT_OFFSET(MonoLMF, gregs[2]));                        
4528                 for (i = 0; i < 16; i++) {                                              
4529                         s390_std  (code, i, 0, s390_r13,                                
4530                                    G_STRUCT_OFFSET(MonoLMF, fregs[i]));                 
4531                 }                                                                       
4532
4533                 /*---------------------------------------------------------------*/
4534                 /* Restore the parameter registers now that we've set up the lmf */
4535                 /*---------------------------------------------------------------*/
4536                 s390_lmg   (code, s390_r2, s390_r6, s390_r13,                           
4537                             G_STRUCT_OFFSET(MonoLMF, pregs[0]));                        
4538         }
4539
4540         if (tracing)
4541                 code = mono_arch_instrument_prolog(cfg, enter_method, code, TRUE);
4542
4543         cfg->code_len = code - cfg->native_code;
4544         g_assert (cfg->code_len < cfg->code_size);
4545
4546         return code;
4547 }
4548
4549 /*========================= End of Function ========================*/
4550
4551 /*------------------------------------------------------------------*/
4552 /*                                                                  */
4553 /* Name         - mono_arch_emit_epilog                             */
4554 /*                                                                  */
4555 /* Function     - Emit the instructions for a function epilog.      */
4556 /*                                                                  */
4557 /*------------------------------------------------------------------*/
4558
4559 void
4560 mono_arch_emit_epilog (MonoCompile *cfg)
4561 {
4562         MonoMethod *method = cfg->method;
4563         int tracing = 0;
4564         guint8 *code;
4565         int max_epilog_size = 96;
4566         
4567         if (cfg->method->save_lmf)
4568                 max_epilog_size += 128;
4569         
4570         if (mono_jit_trace_calls != NULL)
4571                 max_epilog_size += 128;
4572
4573         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
4574                 max_epilog_size += 128;
4575         
4576         while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
4577                 cfg->code_size  *= 2;
4578                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
4579                 mono_jit_stats.code_reallocs++;
4580         }
4581
4582         code = cfg->native_code + cfg->code_len;
4583
4584         if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
4585                 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
4586                 tracing = 1;
4587         }
4588         
4589         if (method->save_lmf) 
4590                 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4591
4592         if (cfg->flags & MONO_CFG_HAS_ALLOCA) 
4593                 s390_lg  (code, STK_BASE, 0, STK_BASE, 0);
4594         else
4595                 code = backUpStackPtr(cfg, code);
4596
4597         s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
4598         s390_br  (code, s390_r14);
4599
4600         cfg->code_len = code - cfg->native_code;
4601
4602         g_assert (cfg->code_len < cfg->code_size);
4603
4604 }
4605
4606 /*========================= End of Function ========================*/
4607
4608 /*------------------------------------------------------------------*/
4609 /*                                                                  */
4610 /* Name         - mono_arch_emit_exceptions                         */
4611 /*                                                                  */
4612 /* Function     - Emit the blocks to handle exception conditions.   */
4613 /*                                                                  */
4614 /*------------------------------------------------------------------*/
4615
4616 void
4617 mono_arch_emit_exceptions (MonoCompile *cfg) 
4618 {
4619         MonoJumpInfo    *patch_info;
4620         guint8          *code;
4621         int             nThrows = 0,
4622                         exc_count = 0,
4623                         iExc;
4624         guint32         code_size;
4625         MonoClass       *exc_classes [MAX_EXC];
4626         guint8          *exc_throw_start [MAX_EXC];
4627
4628         for (patch_info = cfg->patch_info; 
4629              patch_info; 
4630              patch_info = patch_info->next) {
4631                 if (patch_info->type == MONO_PATCH_INFO_EXC)
4632                         exc_count++;
4633         }
4634
4635         code_size = exc_count * 48;
4636
4637         while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
4638                 cfg->code_size  *= 2;
4639                 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
4640                 mono_jit_stats.code_reallocs++; 
4641         }
4642
4643         code = cfg->native_code + cfg->code_len;
4644
4645         /*---------------------------------------------------------------------*/
4646         /* Add code to raise exceptions                                        */
4647         /*---------------------------------------------------------------------*/
4648         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
4649                 switch (patch_info->type) {
4650                 case MONO_PATCH_INFO_EXC: {
4651                         guint8 *ip = patch_info->ip.i + cfg->native_code;
4652                         MonoClass *exc_class;
4653                         guint64 throw_ip;
4654
4655                         /*-----------------------------------------------------*/
4656                         /* Patch the branch in epilog to come here             */
4657                         /*-----------------------------------------------------*/
4658                         s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
4659
4660                         exc_class = mono_class_from_name (mono_defaults.corlib, 
4661                                                           "System", 
4662                                                           patch_info->data.name);
4663                         g_assert (exc_class);
4664                         throw_ip = patch_info->ip.i;
4665
4666                         for (iExc = 0; iExc < nThrows; ++iExc)
4667                                 if (exc_classes [iExc] == exc_class)
4668                                         break;
4669                 
4670                         if (iExc < nThrows) {
4671                                 s390_jcl (code, S390_CC_UN, 
4672                                           (guint64) exc_throw_start [iExc]);
4673                                 patch_info->type = MONO_PATCH_INFO_NONE;
4674                         } else {
4675         
4676                                 if (nThrows < MAX_EXC) {
4677                                         exc_classes [nThrows]     = exc_class;
4678                                         exc_throw_start [nThrows] = code;
4679                                 }
4680         
4681                                 /*---------------------------------------------*/
4682                                 /* Patch the parameter passed to the handler   */ 
4683                                 /*---------------------------------------------*/
4684                                 s390_basr (code, s390_r13, 0);
4685                                 s390_j    (code, 6);
4686                                 s390_llong(code, patch_info->data.target);
4687                                 /*---------------------------------------------*/
4688                                 /* Load return address & parameter register    */
4689                                 /*---------------------------------------------*/
4690                                 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
4691                                                            cfg->native_code + 8), code));
4692                                 s390_lg   (code, s390_r2, 0, s390_r13, 4);
4693                                 /*---------------------------------------------*/
4694                                 /* Reuse the current patch to set the jump     */
4695                                 /*---------------------------------------------*/
4696                                 s390_basr (code, s390_r13, 0);
4697                                 s390_j    (code, 6);
4698                                 patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
4699                                 patch_info->data.name = "mono_arch_throw_exception_by_name";
4700                                 patch_info->ip.i      = code - cfg->native_code;
4701                                 s390_llong(code, 0);
4702                                 s390_lg   (code, s390_r1, 0, s390_r13, 4);
4703                                 s390_br   (code, s390_r1);
4704                         }
4705                         break;
4706                 }
4707                 default:
4708                         /* do nothing */
4709                         break;
4710                 }
4711         }
4712
4713         cfg->code_len = code - cfg->native_code;
4714
4715         g_assert (cfg->code_len < cfg->code_size);
4716
4717 }
4718
4719 /*========================= End of Function ========================*/
4720
4721 /*------------------------------------------------------------------*/
4722 /*                                                                  */
4723 /* Name         - mono_arch_setup_jit_tls_data                      */
4724 /*                                                                  */
4725 /* Function     - Setup the JIT's Thread Level Specific Data.       */
4726 /*                                                                  */
4727 /*------------------------------------------------------------------*/
4728
4729 void
4730 mono_arch_setup_jit_tls_data (MonoJitTlsData *tls)
4731 {
4732         if (!tls_offset_inited) {
4733                 tls_offset_inited = TRUE;
4734
4735 #if HAVE_KW_THREAD
4736 # if 0
4737         __asm__ ("\tear\t%r1,0\n"
4738                  "\tlr\t%0,%3\n"
4739                  "\tsr\t%0,%r1\n"
4740                  "\tlr\t%1,%4\n"
4741                  "\tsr\t%1,%r1\n"
4742                  "\tlr\t%2,%5\n"
4743                  "\tsr\t%2,%r1\n"
4744                  : "=r" (appdomain_tls_offset),
4745                    "=r" (thread_tls_offset),
4746                    "=r" (lmf_tls_offset)
4747                  : "r" (&tls_appdomain),
4748                    "r" (&tls_current_object),
4749                    "r" (&mono_lmf_addr)
4750                  : "1", "cc");
4751 # endif
4752 #endif
4753         }               
4754
4755         if (!lmf_addr_key_inited) {
4756                 lmf_addr_key_inited = TRUE;
4757                 pthread_key_create (&lmf_addr_key, NULL);
4758         }
4759         pthread_setspecific (lmf_addr_key, &tls->lmf);
4760
4761 }
4762
4763 /*========================= End of Function ========================*/
4764
4765 /*------------------------------------------------------------------*/
4766 /*                                                                  */
4767 /* Name         - mono_arch_free_jit_tls_data                       */
4768 /*                                                                  */
4769 /* Function     - Free tls data.                                    */
4770 /*                                                                  */
4771 /*------------------------------------------------------------------*/
4772
4773 void
4774 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
4775 {
4776
4777 }
4778
4779 /*========================= End of Function ========================*/
4780
4781 /*------------------------------------------------------------------*/
4782 /*                                                                  */
4783 /* Name         - mono_arch_emit_this_vret_args                     */
4784 /*                                                                  */
4785 /* Function     -                                                   */
4786 /*                                                                  */
4787 /*------------------------------------------------------------------*/
4788
4789 void
4790 mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_reg, int this_type, int vt_reg)
4791 {
4792         int this_dreg = s390_r2;
4793         
4794         if (vt_reg != -1)
4795                 this_dreg = s390_r3;
4796
4797         /* add the this argument */
4798         if (this_reg != -1) {
4799                 MonoInst *this;
4800                 MONO_INST_NEW (cfg, this, OP_MOVE);
4801                 this->type  = this_type;
4802                 this->sreg1 = this_reg;
4803                 this->dreg  = mono_regstate_next_int (cfg->rs);
4804                 mono_bblock_add_inst (cfg->cbb, this);
4805                 mono_call_inst_add_outarg_reg (cfg, inst, this->dreg, this_dreg, FALSE);
4806         }
4807
4808         if (vt_reg != -1) {
4809                 MonoInst *vtarg;
4810                 MONO_INST_NEW (cfg, vtarg, OP_MOVE);
4811                 vtarg->type  = STACK_MP;
4812                 vtarg->sreg1 = vt_reg;
4813                 vtarg->dreg  = mono_regstate_next_int (cfg->rs);
4814                 mono_bblock_add_inst (cfg->cbb, vtarg);
4815                 mono_call_inst_add_outarg_reg (cfg, inst, vtarg->dreg, s390_r2, FALSE);
4816         }
4817 }
4818
4819 /*========================= End of Function ========================*/
4820
4821 /*------------------------------------------------------------------*/
4822 /*                                                                  */
4823 /* Name         - mono_arch_get_inst_for_method                   */
4824 /*                                                                  */
4825 /* Function     - Check for opcodes we can handle directly in       */
4826 /*                hardware.                                         */
4827 /*                                                                  */
4828 /*------------------------------------------------------------------*/
4829
4830 MonoInst*
4831 mono_arch_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, 
4832                                MonoMethodSignature *fsig, MonoInst **args)
4833 {
4834         MonoInst *ins = NULL;
4835
4836         if (cmethod->klass == mono_defaults.math_class) {
4837                 if (strcmp (cmethod->name, "Sqrt") == 0) {
4838                         MONO_INST_NEW (cfg, ins, OP_SQRT);
4839                         ins->inst_i0 = args [0];
4840                 }
4841 //              if (strcmp (cmethod->name, "Abs") == 0) {
4842 //                      MONO_INST_NEW (cfg, ins, OP_ABS);
4843 //                      ins->inst_i0 = args [0];
4844 //              }
4845         }
4846
4847         return ins;
4848 }
4849
4850 /*========================= End of Function ========================*/
4851
4852 /*------------------------------------------------------------------*/
4853 /*                                                                  */
4854 /* Name         - mono_arch_print_tree                              */
4855 /*                                                                  */
4856 /* Function     - Print platform-specific opcode details.           */
4857 /*                                                                  */
4858 /* Returns      - 1 - opcode details have been printed              */
4859 /*                0 - opcode details have not been printed          */
4860 /*                                                                  */
4861 /*------------------------------------------------------------------*/
4862
4863 gboolean
4864 mono_arch_print_tree (MonoInst *tree, int arity)
4865 {
4866         gboolean done;
4867
4868         switch (tree->opcode) {
4869                 case OP_S390_LOADARG:
4870                 case OP_S390_ARGREG:
4871                 case OP_S390_ARGPTR:
4872                         printf ("[0x%lx(%s)]", tree->inst_offset, 
4873                                 mono_arch_regname (tree->inst_basereg));
4874                         done = 1;
4875                         break;
4876                 case OP_S390_STKARG:
4877                         printf ("[0x%lx(previous_frame)]", 
4878                                 tree->inst_offset); 
4879                         done = 1;
4880                         break;
4881                 case OP_S390_MOVE:
4882                         printf ("[0x%lx(%d,%s),0x%lx(%s)]",
4883                                 tree->inst_offset, tree->backend.size,
4884                                 mono_arch_regname(tree->dreg), 
4885                                 tree->inst_imm, 
4886                                 mono_arch_regname(tree->sreg1));
4887                         done = 1;
4888                         break;
4889                 case OP_S390_SETF4RET:
4890                         printf ("[f%s,f%s]", 
4891                                 mono_arch_regname (tree->dreg),
4892                                 mono_arch_regname (tree->sreg1));
4893                         done = 1;
4894                         break;
4895                 case OP_TLS_GET:
4896                         printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
4897                                 tree->inst_imm,
4898                                 mono_arch_regname (tree->sreg1));
4899                         done = 1;
4900                         break;
4901                 case OP_S390_BKCHAIN:
4902                         printf ("[previous_frame(%s)]", 
4903                                 mono_arch_regname (tree->sreg1));
4904                         done = 1;
4905                 default:
4906                         done = 0;
4907         }
4908         return (done);
4909 }
4910
4911 /*========================= End of Function ========================*/
4912
4913 /*------------------------------------------------------------------*/
4914 /*                                                                  */
4915 /* Name         - mono_arch_regalloc_cost                           */
4916 /*                                                                  */
4917 /* Function     - Determine the cost, in the number of memory       */
4918 /*                references, of the action of allocating the var-  */
4919 /*                iable VMV into a register during global register  */
4920 /*                allocation.                                       */
4921 /*                                                                  */
4922 /* Returns      - Cost                                              */
4923 /*                                                                  */
4924 /*------------------------------------------------------------------*/
4925
4926 guint32
4927 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
4928 {
4929         /* FIXME: */
4930         return 2;
4931 }
4932
4933 /*========================= End of Function ========================*/
4934
4935 /*------------------------------------------------------------------*/
4936 /*                                                                  */
4937 /* Name         - mono_arch_get_domain_intrinsic                    */
4938 /*                                                                  */
4939 /* Function     -                                                   */
4940 /*                                                                  */
4941 /* Returns      -                                                   */
4942 /*                                                                  */
4943 /*------------------------------------------------------------------*/
4944
4945 MonoInst * 
4946 mono_arch_get_domain_intrinsic (MonoCompile* cfg)
4947 {
4948         MonoInst *ins;
4949
4950         if (appdomain_tls_offset == -1)
4951                 return NULL;
4952         
4953         MONO_INST_NEW (cfg, ins, OP_TLS_GET);
4954         ins->inst_offset = appdomain_tls_offset;
4955         return (ins);
4956 }
4957
4958 /*========================= End of Function ========================*/
4959
4960 /*------------------------------------------------------------------*/
4961 /*                                                                  */
4962 /* Name         - mono_arch_get_thread_intrinsic                    */
4963 /*                                                                  */
4964 /* Function     -                                                   */
4965 /*                                                                  */
4966 /* Returns      -                                                   */
4967 /*                                                                  */
4968 /*------------------------------------------------------------------*/
4969
4970 MonoInst * 
4971 mono_arch_get_thread_intrinsic (MonoCompile* cfg)
4972 {
4973         MonoInst *ins;
4974
4975         if (thread_tls_offset == -1)
4976                 return NULL;
4977         
4978         MONO_INST_NEW (cfg, ins, OP_TLS_GET);
4979         ins->inst_offset = thread_tls_offset;
4980         return (ins);
4981 }
4982
4983 /*========================= End of Function ========================*/
4984
4985 /*------------------------------------------------------------------*/
4986 /*                                                                  */
4987 /* Name         - mono_arch_flush_register_windows                  */
4988 /*                                                                  */
4989 /* Function     -                                                   */
4990 /*                                                                  */
4991 /* Returns      -                                                   */
4992 /*                                                                  */
4993 /*------------------------------------------------------------------*/
4994
4995 void 
4996 mono_arch_flush_register_windows (void)
4997 {
4998 }
4999
5000 /*========================= End of Function ========================*/
5001
5002 /*------------------------------------------------------------------*/
5003 /*                                                                  */
5004 /* Name         - mono_arch_get_lmf_addr                            */
5005 /*                                                                  */
5006 /* Function     -                                                   */
5007 /*                                                                  */
5008 /* Returns      -                                                   */
5009 /*                                                                  */
5010 /*------------------------------------------------------------------*/
5011
5012 gpointer
5013 mono_arch_get_lmf_addr (void)
5014 {
5015         return pthread_getspecific (lmf_addr_key);
5016 }
5017
5018 /*========================= End of Function ========================*/
5019
5020 /*------------------------------------------------------------------*/
5021 /*                                                                  */
5022 /* Name         - mono_arch_is_inst_imm                             */
5023 /*                                                                  */
5024 /* Function     - Determine if operand qualifies as an immediate    */
5025 /*                value. For s390 this is a value -32768-32768      */
5026 /*                                                                  */
5027 /* Returns      - True|False - is [not] immediate value.            */
5028 /*                                                                  */
5029 /*------------------------------------------------------------------*/
5030
5031 gboolean 
5032 mono_arch_is_inst_imm (gint64 imm)
5033 {
5034         return s390_is_imm16 (imm);
5035 }
5036
5037 /*========================= End of Function ========================*/
5038
5039 /*========================= End of Function ========================*/
5040
5041 /*------------------------------------------------------------------*/
5042 /*                                                                  */
5043 /* Name         - mono_arch_get_patch_offset                        */
5044 /*                                                                  */
5045 /* Function     - Dummy entry point until s390x supports aot.       */
5046 /*                                                                  */
5047 /* Returns      - Offset for patch.                                 */
5048 /*                                                                  */
5049 /*------------------------------------------------------------------*/
5050
5051 guint32
5052 mono_arch_get_patch_offset (guint8 *code)
5053 {
5054         return 0;
5055 }
5056
5057 /*========================= End of Function ========================*/
5058
5059 gpointer
5060 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
5061 {
5062         /* FIXME: implement */
5063         g_assert_not_reached ();
5064         return NULL;
5065 }