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