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