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