1 /*------------------------------------------------------------------*/
3 /* Name - mini-s390.c */
5 /* Function - S/390 backend for the Mono code generator. */
7 /* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
9 /* Date - January, 2004 */
11 /* Derivation - From mini-x86 & mini-ppc by - */
12 /* Paolo Molaro (lupus@ximian.com) */
13 /* Dietmar Maurer (dietmar@ximian.com) */
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 /*------------------------------------------------------------------*/
21 #define NOT_IMPLEMENTED(x) \
22 g_error ("FIXME: %s is not yet implemented. (trampoline)", x);
24 #define EMIT_COND_BRANCH(ins,cond) \
26 if (ins->flags & MONO_INST_BRLABEL) { \
27 if (ins->inst_i0->inst_c0) { \
29 displace = ((cfg->native_code + ins->inst_i0->inst_c0) - code) / 2; \
30 if (s390_is_uimm16(displace)) { \
31 s390_brc (code, cond, displace); \
33 s390_jcl (code, cond, displace); \
36 mono_add_patch_info (cfg, code - cfg->native_code, \
37 MONO_PATCH_INFO_LABEL, ins->inst_i0); \
38 s390_jcl (code, cond, 0); \
41 if (ins->inst_true_bb->native_offset) { \
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); \
48 s390_jcl (code, cond, displace); \
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); \
58 #define EMIT_UNCOND_BRANCH(ins) \
60 if (ins->flags & MONO_INST_BRLABEL) { \
61 if (ins->inst_i0->inst_c0) { \
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); \
67 s390_jcl (code, S390_CC_UN, displace); \
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); \
75 if (ins->inst_target_bb->native_offset) { \
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); \
82 s390_jcl (code, S390_CC_UN, displace); \
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); \
92 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
94 mono_add_patch_info (cfg, code - cfg->native_code, \
95 MONO_PATCH_INFO_EXC, exc_name); \
96 s390_jcl (code, cond, 0); \
100 #define DEBUG(a) if (cfg->verbose_level > 1) a
101 #define reg_is_freeable(r) ((r) >= 3 && (r) <= 10)
102 #define freg_is_freeable(r) ((r) >= 1 && (r) <= 14)
104 /*----------------------------------------*/
105 /* use s390_r3-s390_r10 as temp registers */
106 /*----------------------------------------*/
107 #define S390_CALLER_REGS (0x03f8)
109 /*----------------------------------------*/
110 /* use s390_f2-s390_f14 as temp registers */
111 /*----------------------------------------*/
112 #define S390_CALLER_FREGS (0x73f8)
114 #define S390_TRACE_STACK_SIZE (5*sizeof(gint32)+3*sizeof(gdouble))
116 /*========================= End of Defines =========================*/
118 /*------------------------------------------------------------------*/
119 /* I n c l u d e s */
120 /*------------------------------------------------------------------*/
125 #include <mono/metadata/appdomain.h>
126 #include <mono/metadata/debug-helpers.h>
127 #include <mono/metadata/profiler-private.h>
128 #include <mono/utils/mono-math.h>
130 #include "mini-s390.h"
132 #include "cpu-s390.h"
134 /*========================= End of Includes ========================*/
136 /*------------------------------------------------------------------*/
137 /* T y p e d e f s */
138 /*------------------------------------------------------------------*/
147 /*------------------------------------------------------------------*/
148 /* Used by the instrument_emit_epilog */
149 /*------------------------------------------------------------------*/
166 typedef struct InstList InstList
;
183 gint32 offset
; /* offset from caller's stack */
184 gint32 offparm
; /* offset on callee's stack */
185 guint16 vtsize
; /* in param area */
187 guint8 regtype
; /* See RegType* */
188 guint32 size
; /* Size of structure used by RegTypeStructByVal */
200 gint32 gr
[5]; /* R2-R6 */
201 gdouble fp
[3]; /* F0-F2 */
202 } __attribute__ ((packed
)) RegParm
;
204 /*========================= End of Typedefs ========================*/
206 /*------------------------------------------------------------------*/
207 /* P r o t o t y p e s */
208 /*------------------------------------------------------------------*/
210 static guint32
* emit_memcpy (guint8
*, int, int, int, int, int);
211 static void indent (int);
212 static guint8
* restoreLMF(MonoCompile
*, guint8
*);
213 static guint8
* backUpStackPtr(MonoCompile
*, guint8
*);
214 static void decodeParm (MonoType
*, void *, int);
215 static void enter_method (MonoMethod
*, RegParm
*, char *);
216 static void leave_method (MonoMethod
*, ...);
217 static gboolean
is_regsize_var (MonoType
*);
218 static void add_general (guint
*, size_data
*, ArgInfo
*, gboolean
);
219 static CallInfo
* calculate_sizes (MonoMethodSignature
*, size_data
*, gboolean
);
220 static void peephole_pass (MonoCompile
*, MonoBasicBlock
*);
221 static int mono_spillvar_offset (MonoCompile
*, int);
222 static int mono_spillvar_offset_float (MonoCompile
*, int);
223 static void print_ins (int, MonoInst
*);
224 static void print_regtrack (RegTrack
*, int);
225 static InstList
* inst_list_prepend (MonoMemPool
*, InstList
*, MonoInst
*);
226 static int get_register_force_spilling (MonoCompile
*, InstList
*, MonoInst
*, int);
227 static int get_register_spilling (MonoCompile
*, InstList
*, MonoInst
*, guint32
, int);
228 static int get_float_register_spilling (MonoCompile
*, InstList
*, MonoInst
*, guint32
, int);
229 static MonoInst
* create_copy_ins (MonoCompile
*, int, int, MonoInst
*);
230 static MonoInst
* create_copy_ins_float (MonoCompile
*, int, int, MonoInst
*);
231 static MonoInst
* create_spilled_store (MonoCompile
*, int, int, int, MonoInst
*);
232 static MonoInst
* create_spilled_store_float (MonoCompile
*, int, int, int, MonoInst
*);
233 static void insert_before_ins (MonoInst
*, InstList
*, MonoInst
*);
234 static int alloc_int_reg (MonoCompile
*, InstList
*, MonoInst
*, int, guint32
);
235 static guchar
* emit_float_to_int (MonoCompile
*, guchar
*, int, int, int, gboolean
);
236 static unsigned char * mono_emit_stack_alloc (guchar
*, MonoInst
*);
238 /*========================= End of Prototypes ======================*/
240 /*------------------------------------------------------------------*/
241 /* G l o b a l V a r i a b l e s */
242 /*------------------------------------------------------------------*/
244 int mono_exc_esp_offset
= 0;
246 static int indent_level
= 0;
248 static const char*const * ins_spec
= s390
;
250 /*====================== End of Global Variables ===================*/
252 /*------------------------------------------------------------------*/
254 /* Name - mono_arch_regname */
256 /* Function - Returns the name of the register specified by */
257 /* the input parameter. */
259 /*------------------------------------------------------------------*/
262 mono_arch_regname (int reg
) {
263 static const char * rnames
[] = {
264 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
265 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
266 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
269 if (reg
>= 0 && reg
< 16)
274 /*========================= End of Function ========================*/
276 /*------------------------------------------------------------------*/
278 /* Name - emit_memcpy */
280 /* Function - Emit code to move from memory-to-memory based on */
281 /* the size of the variable. r0 is overwritten. */
283 /*------------------------------------------------------------------*/
286 emit_memcpy (guint8
*code
, int size
, int dreg
, int doffset
, int sreg
, int soffset
)
290 s390_l (code
, s390_r0
, 0, sreg
, soffset
);
291 s390_st (code
, s390_r0
, 0, dreg
, doffset
);
295 s390_icm (code
, s390_r0
, 14, sreg
, soffset
);
296 s390_stcm (code
, s390_r0
, 14, dreg
, doffset
);
300 s390_lh (code
, s390_r0
, 0, sreg
, soffset
);
301 s390_sth (code
, s390_r0
, 0, dreg
, doffset
);
305 s390_ic (code
, s390_r0
, 0, sreg
, soffset
);
306 s390_stc (code
, s390_r0
, 0, dreg
, doffset
);
317 s390_mvc (code
, len
, dreg
, doffset
, sreg
, soffset
);
324 /*========================= End of Function ========================*/
326 /*------------------------------------------------------------------*/
328 /* Name - arch_get_argument_info */
330 /* Function - Gathers information on parameters such as size, */
331 /* alignment, and padding. arg_info should be large */
332 /* enough to hold param_count + 1 entries. */
334 /* Parameters - @csig - Method signature */
335 /* @param_count - No. of parameters to consider */
336 /* @arg_info - An array to store the result info */
338 /* Returns - Size of the activation frame */
340 /*------------------------------------------------------------------*/
343 mono_arch_get_argument_info (MonoMethodSignature
*csig
,
345 MonoJitArgumentInfo
*arg_info
)
347 int k
, frame_size
= 0;
348 int size
, align
, pad
;
351 if (MONO_TYPE_ISSTRUCT (csig
->ret
)) {
352 frame_size
+= sizeof (gpointer
);
356 arg_info
[0].offset
= offset
;
359 frame_size
+= sizeof (gpointer
);
363 arg_info
[0].size
= frame_size
;
365 for (k
= 0; k
< param_count
; k
++) {
368 size
= mono_type_native_stack_size (csig
->params
[k
], &align
);
370 size
= mono_type_stack_size (csig
->params
[k
], &align
);
372 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
373 arg_info
[k
].pad
= pad
;
375 arg_info
[k
+ 1].pad
= 0;
376 arg_info
[k
+ 1].size
= size
;
378 arg_info
[k
+ 1].offset
= offset
;
382 align
= MONO_ARCH_FRAME_ALIGNMENT
;
383 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
384 arg_info
[k
].pad
= pad
;
389 /*========================= End of Function ========================*/
391 /*------------------------------------------------------------------*/
393 /* Name - restoreLMF */
395 /* Function - Restore the LMF state prior to exiting a method. */
397 /*------------------------------------------------------------------*/
399 static inline guint8
*
400 restoreLMF(MonoCompile
*cfg
, guint8
*code
)
404 s390_lr (code
, s390_r13
, cfg
->frame_reg
);
406 lmfOffset
= cfg
->stack_usage
- sizeof(MonoLMF
);
408 /*-------------------------------------------------*/
410 /*-------------------------------------------------*/
411 s390_ahi (code
, s390_r13
, lmfOffset
);
413 /*-------------------------------------------------*/
414 /* r6 = &jit_tls->lmf */
415 /*-------------------------------------------------*/
416 s390_l (code
, s390_r6
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
418 /*-------------------------------------------------*/
419 /* r0 = lmf.previous_lmf */
420 /*-------------------------------------------------*/
421 s390_l (code
, s390_r0
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
423 /*-------------------------------------------------*/
424 /* jit_tls->lmf = previous_lmf */
425 /*-------------------------------------------------*/
426 s390_l (code
, s390_r13
, 0, s390_r6
, 0);
427 s390_st (code
, s390_r0
, 0, s390_r6
, 0);
431 /*========================= End of Function ========================*/
433 /*------------------------------------------------------------------*/
435 /* Name - backStackPtr. */
437 /* Function - Restore Stack Pointer to previous frame. */
439 /*------------------------------------------------------------------*/
441 static inline guint8
*
442 backUpStackPtr(MonoCompile
*cfg
, guint8
*code
)
444 int stackSize
= cfg
->stack_usage
;
446 if (s390_is_imm16 (cfg
->stack_usage
)) {
447 s390_ahi (code
, STK_BASE
, cfg
->stack_usage
);
449 while (stackSize
> 32767) {
450 s390_ahi (code
, STK_BASE
, -32767);
453 s390_ahi (code
, STK_BASE
, -stackSize
);
458 /*========================= End of Function ========================*/
460 /*------------------------------------------------------------------*/
464 /* Function - Perform nice indenting to current level */
466 /*------------------------------------------------------------------*/
472 indent_level
+= diff
;
479 indent_level
+= diff
;
482 /*========================= End of Function ========================*/
484 /*------------------------------------------------------------------*/
486 /* Name - decodeParm */
488 /* Function - Decode a parameter for the trace. */
490 /*------------------------------------------------------------------*/
493 decodeParm(MonoType
*type
, void *curParm
, int size
)
498 printf("[BYREF:%p], ", *((char **) curParm
));
500 simpleType
= type
->type
;
502 switch (simpleType
) {
504 printf ("[INTPTR:%p], ", *((int **) curParm
));
507 printf ("[UINTPTR:%p], ", *((int **) curParm
));
509 case MONO_TYPE_BOOLEAN
:
510 printf ("[BOOL:%p], ", *((int *) curParm
));
512 case MONO_TYPE_CHAR
:
513 printf ("[CHAR:%p], ", *((int *) curParm
));
516 printf ("[INT1:%d], ", *((int *) curParm
));
519 printf ("[INT2:%d], ", *((int *) curParm
));
522 printf ("[INT4:%d], ", *((int *) curParm
));
525 printf ("[UINT1:%ud], ", *((unsigned int *) curParm
));
528 printf ("[UINT2:%ud], ", *((guint16
*) curParm
));
531 printf ("[UINT4:%ud], ", *((guint32
*) curParm
));
534 printf ("[UINT8:%ul], ", *((guint64
*) curParm
));
536 case MONO_TYPE_STRING
: {
537 MonoString
*s
= *((MonoString
**) curParm
);
539 g_assert (((MonoObject
*) s
)->vtable
->klass
== mono_defaults
.string_class
);
540 printf("[STRING:%p:%s], ", s
, mono_string_to_utf8(s
));
542 printf("[STRING:null], ");
546 case MONO_TYPE_CLASS
:
547 case MONO_TYPE_OBJECT
: {
548 MonoObject
*obj
= *((MonoObject
**) curParm
);
551 printf("[CLASS/OBJ:");
552 class = obj
->vtable
->klass
;
553 if (class == mono_defaults
.string_class
) {
554 printf("[STRING:%p:%s]",
555 *obj
, mono_string_to_utf8 (obj
));
556 } else if (class == mono_defaults
.int32_class
) {
557 printf("[INT32:%p:%d]",
558 obj
, *(gint32
*)((char *)obj
+ sizeof (MonoObject
)));
561 class->name_space
, class->name
, obj
);
564 printf("[OBJECT:null], ");
569 printf("[PTR:%p], ", *((gpointer
**) (curParm
)));
571 case MONO_TYPE_FNPTR
:
572 printf("[FNPTR:%p], ", *((gpointer
**) (curParm
)));
574 case MONO_TYPE_ARRAY
:
575 printf("[ARRAY:%p], ", *((gpointer
**) (curParm
)));
577 case MONO_TYPE_SZARRAY
:
578 printf("[SZARRAY:%p], ", *((gpointer
**) (curParm
)));
581 printf("[INT8:%lld], ", *((gint64
*) (curParm
)));
584 printf("[FLOAT4:%f], ", *((float *) (curParm
)));
587 printf("[FLOAT8:%g], ", *((double *) (curParm
)));
589 case MONO_TYPE_VALUETYPE
: {
591 if (type
->data
.klass
->enumtype
) {
592 simpleType
= type
->data
.klass
->enum_basetype
->type
;
593 printf("{VALUETYPE} - ");
596 printf("[VALUETYPE:");
597 for (i
= 0; i
< size
; i
++)
598 printf("%02x,", *((guint8
*)curParm
+i
));
603 printf("[?? - %d], ",simpleType
);
608 /*========================= End of Function ========================*/
610 /*------------------------------------------------------------------*/
612 /* Name - enter_method */
614 /* Function - Perform tracing of the entry to the current */
617 /*------------------------------------------------------------------*/
619 static int methodCount
= 0;
622 enter_method (MonoMethod
*method
, RegParm
*rParm
, char *sp
)
624 int i
, oParm
= 0, iParm
= 0;
627 MonoJitArgumentInfo
*arg_info
;
628 MonoMethodSignature
*sig
;
637 if (methodCount
> 150000) {
641 fname
= mono_method_full_name (method
, TRUE
);
643 printf ("ENTER: %s(", fname
);
646 ip
= (*(guint32
*) (sp
+S390_RET_ADDR_OFFSET
)) & 0x7fffffff;
647 printf (") ip: %p sp: %p\n", ip
, sp
);
652 sig
= method
->signature
;
654 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
656 if (cinfo
->struct_ret
) {
657 printf ("[VALUERET:%p], ", rParm
->gr
[0]);
662 gpointer
*this = (gpointer
*) rParm
->gr
[iParm
];
663 obj
= (MonoObject
*) this;
664 if (method
->klass
->valuetype
) {
666 printf("this:[value:%p:%08x], ",
667 this, *((guint32
*)(this+sizeof(MonoObject
))));
669 printf ("this:[NULL], ");
672 class = obj
->vtable
->klass
;
673 if (class == mono_defaults
.string_class
) {
674 printf ("this:[STRING:%p:%s], ",
675 obj
, mono_string_to_utf8 ((MonoString
*)obj
));
677 printf ("this:%p[%s.%s], ",
678 obj
, class->name_space
, class->name
);
681 printf ("this:NULL, ");
686 for (i
= 0; i
< sig
->param_count
; ++i
) {
687 ainfo
= cinfo
->args
+ (i
+ oParm
);
688 switch (ainfo
->regtype
) {
689 case RegTypeGeneral
:
690 decodeParm(sig
->params
[i
], &(rParm
->gr
[ainfo
->reg
-2]), ainfo
->size
);
693 decodeParm(sig
->params
[i
], &(rParm
->fp
[ainfo
->reg
]), ainfo
->size
);
696 decodeParm(sig
->params
[i
], sp
+ainfo
->offset
, ainfo
->size
);
698 case RegTypeStructByVal
:
699 if (ainfo
->reg
!= STK_BASE
)
700 curParm
= &(rParm
->gr
[ainfo
->reg
-2]);
702 curParm
= sp
+ainfo
->offset
;
704 switch (ainfo
->vtsize
) {
710 decodeParm(sig
->params
[i
],
715 decodeParm(sig
->params
[i
],
716 *((char **) curParm
),
720 case RegTypeStructByAddr
:
721 if (ainfo
->reg
!= STK_BASE
)
722 curParm
= &(rParm
->gr
[ainfo
->reg
-2]);
724 curParm
= sp
+ainfo
->offset
;
726 decodeParm(sig
->params
[i
],
727 *((char **) curParm
),
739 /*========================= End of Function ========================*/
741 /*------------------------------------------------------------------*/
743 /* Name - leave_method */
747 /*------------------------------------------------------------------*/
750 leave_method (MonoMethod
*method
, ...)
757 va_start(ap
, method
);
759 fname
= mono_method_full_name (method
, TRUE
);
761 printf ("LEAVE: %s", fname
);
764 type
= method
->signature
->ret
;
767 switch (type
->type
) {
770 case MONO_TYPE_BOOLEAN
: {
771 int val
= va_arg (ap
, int);
773 printf ("[TRUE:%d]", val
);
779 case MONO_TYPE_CHAR
: {
780 int val
= va_arg (ap
, int);
781 printf ("[CHAR:%d]", val
);
785 int val
= va_arg (ap
, int);
786 printf ("[INT1:%d]", val
);
790 int val
= va_arg (ap
, int);
791 printf ("[UINT1:%d]", val
);
795 int val
= va_arg (ap
, int);
796 printf ("[INT2:%d]", val
);
800 int val
= va_arg (ap
, int);
801 printf ("[UINT2:%d]", val
);
805 int val
= va_arg (ap
, int);
806 printf ("[INT4:%d]", val
);
810 int val
= va_arg (ap
, int);
811 printf ("[UINT4:%d]", val
);
815 int *val
= va_arg (ap
, int*);
816 printf ("[INT:%d]", val
);
821 int *val
= va_arg (ap
, int*);
822 printf ("[UINT:%d]", val
);
826 case MONO_TYPE_STRING
: {
827 MonoString
*s
= va_arg (ap
, MonoString
*);
830 g_assert (((MonoObject
*)s
)->vtable
->klass
== mono_defaults
.string_class
);
831 printf ("[STRING:%p:%s]", s
, mono_string_to_utf8 (s
));
833 printf ("[STRING:null], ");
836 case MONO_TYPE_CLASS
:
837 case MONO_TYPE_OBJECT
: {
838 MonoObject
*o
= va_arg (ap
, MonoObject
*);
841 if (o
->vtable
->klass
== mono_defaults
.boolean_class
) {
842 printf ("[BOOLEAN:%p:%d]", o
, *((guint8
*)o
+ sizeof (MonoObject
)));
843 } else if (o
->vtable
->klass
== mono_defaults
.int32_class
) {
844 printf ("[INT32:%p:%d]", o
, *((gint32
*)((char *)o
+ sizeof (MonoObject
))));
845 } else if (o
->vtable
->klass
== mono_defaults
.int64_class
) {
846 printf ("[INT64:%p:%lld]", o
, *((gint64
*)((char *)o
+ sizeof (MonoObject
))));
848 printf ("[%s.%s:%p]", o
->vtable
->klass
->name_space
, o
->vtable
->klass
->name
, o
);
850 printf ("[OBJECT:%p]", o
);
855 case MONO_TYPE_FNPTR
:
856 case MONO_TYPE_ARRAY
:
857 case MONO_TYPE_SZARRAY
: {
858 gpointer p
= va_arg (ap
, gpointer
);
859 printf ("[result=%p]", p
);
863 gint64 l
= va_arg (ap
, gint64
);
864 printf ("[LONG:%lld]", l
);
868 double f
= va_arg (ap
, double);
869 printf ("[FLOAT4:%f]\n", (float) f
);
873 double f
= va_arg (ap
, double);
874 printf ("[FLOAT8:%g]\n", f
);
877 case MONO_TYPE_VALUETYPE
:
878 if (type
->data
.klass
->enumtype
) {
879 type
= type
->data
.klass
->enum_basetype
;
882 guint8
*p
= va_arg (ap
, gpointer
);
884 size
= mono_type_size (type
, &align
);
886 for (j
= 0; p
&& j
< size
; j
++)
887 printf ("%02x,", p
[j
]);
892 printf ("(unknown return type %x)",
893 method
->signature
->ret
->type
);
896 ip
= ((gint32
) __builtin_return_address (0)) & 0x7fffffff;
897 printf (" ip: %p\n", ip
);
900 /*========================= End of Function ========================*/
902 /*------------------------------------------------------------------*/
904 /* Name - mono_arch_cpu_init */
906 /* Function - Perform CPU specific initialization to execute */
909 /*------------------------------------------------------------------*/
912 mono_arch_cpu_init (void)
916 /*--------------------------------------*/
917 /* Set default rounding mode for FP */
918 /*--------------------------------------*/
919 __asm__ ("SRNM\t%0\n\t"
923 /*========================= End of Function ========================*/
925 /*------------------------------------------------------------------*/
927 /* Name - mono_arch_cpu_optimizazions */
929 /* Function - Returns the optimizations supported on this CPU */
931 /*------------------------------------------------------------------*/
934 mono_arch_cpu_optimizazions (guint32
*exclude_mask
)
938 /* no s390-specific optimizations yet */
939 *exclude_mask
= MONO_OPT_INLINE
|MONO_OPT_LINEARS
;
943 /*========================= End of Function ========================*/
945 /*------------------------------------------------------------------*/
951 /*------------------------------------------------------------------*/
954 is_regsize_var (MonoType
*t
) {
963 case MONO_TYPE_OBJECT
:
964 case MONO_TYPE_STRING
:
965 case MONO_TYPE_CLASS
:
966 case MONO_TYPE_SZARRAY
:
967 case MONO_TYPE_ARRAY
:
969 case MONO_TYPE_VALUETYPE
:
970 if (t
->data
.klass
->enumtype
)
971 return is_regsize_var (t
->data
.klass
->enum_basetype
);
977 /*========================= End of Function ========================*/
979 /*------------------------------------------------------------------*/
981 /* Name - mono_arch_get_allocatable_int_vars */
985 /*------------------------------------------------------------------*/
988 mono_arch_get_allocatable_int_vars (MonoCompile
*cfg
)
993 for (i
= 0; i
< cfg
->num_varinfo
; i
++) {
994 MonoInst
*ins
= cfg
->varinfo
[i
];
995 MonoMethodVar
*vmv
= MONO_VARINFO (cfg
, i
);
998 if (vmv
->range
.first_use
.abs_pos
> vmv
->range
.last_use
.abs_pos
)
1001 if (ins
->flags
& (MONO_INST_VOLATILE
|MONO_INST_INDIRECT
) || (ins
->opcode
!= OP_LOCAL
&& ins
->opcode
!= OP_ARG
))
1004 /* we can only allocate 32 bit values */
1005 if (is_regsize_var (ins
->inst_vtype
)) {
1006 g_assert (MONO_VARINFO (cfg
, i
)->reg
== -1);
1007 g_assert (i
== vmv
->idx
);
1008 vars
= mono_varlist_insert_sorted (cfg
, vars
, vmv
, FALSE
);
1015 /*========================= End of Function ========================*/
1017 /*------------------------------------------------------------------*/
1019 /* Name - mono_arch_global_int_regs */
1021 /* Function - Return a list of usable integer registers. */
1023 /*------------------------------------------------------------------*/
1026 mono_arch_get_global_int_regs (MonoCompile
*cfg
)
1031 for (i
= 3; i
< top
; ++i
)
1032 regs
= g_list_prepend (regs
, GUINT_TO_POINTER (i
));
1037 /*========================= End of Function ========================*/
1039 /*------------------------------------------------------------------*/
1041 /* Name - mono_arch_flush_icache */
1043 /* Function - Flush the CPU icache. */
1045 /*------------------------------------------------------------------*/
1048 mono_arch_flush_icache (guint8
*code
, gint size
)
1052 /*========================= End of Function ========================*/
1054 /*------------------------------------------------------------------*/
1056 /* Name - add_general */
1058 /* Function - Determine code and stack size incremements for a */
1061 /*------------------------------------------------------------------*/
1064 add_general (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
, gboolean simple
)
1067 if (*gr
> S390_LAST_ARG_REG
) {
1068 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1069 ainfo
->offset
= sz
->stack_size
;
1070 ainfo
->reg
= STK_BASE
;
1071 ainfo
->regtype
= RegTypeBase
;
1072 sz
->stack_size
+= sizeof(int);
1073 sz
->code_size
+= 12;
1079 if (*gr
> S390_LAST_ARG_REG
- 1) {
1080 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, S390_STACK_ALIGNMENT
);
1081 ainfo
->offset
= sz
->stack_size
;
1082 ainfo
->reg
= STK_BASE
;
1083 ainfo
->regtype
= RegTypeBase
;
1084 sz
->stack_size
+= sizeof(long long);
1085 sz
->code_size
+= 10;
1095 /*========================= End of Function ========================*/
1097 /*------------------------------------------------------------------*/
1099 /* Name - calculate_sizes */
1101 /* Function - Determine the amount of space required for code */
1102 /* and stack. In addition determine starting points */
1103 /* for stack-based parameters, and area for struct- */
1104 /* ures being returned on the stack. */
1106 /*------------------------------------------------------------------*/
1109 calculate_sizes (MonoMethodSignature
*sig
, size_data
*sz
,
1110 gboolean string_ctor
)
1112 guint i
, fr
, gr
, size
, nWords
;
1113 int nParm
= sig
->hasthis
+ sig
->param_count
;
1114 guint32 simpletype
, align
;
1115 CallInfo
*cinfo
= g_malloc0 (sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1119 cinfo
->struct_ret
= 0;
1121 sz
->stack_size
= S390_MINIMAL_STACK_SIZE
;
1126 /*----------------------------------------------------------*/
1127 /* We determine the size of the return code/stack in case we*/
1128 /* need to reserve a register to be used to address a stack */
1129 /* area that the callee will use. */
1130 /*----------------------------------------------------------*/
1132 // if (sig->ret->byref || string_ctor) {
1133 // sz->code_size += 8;
1134 // add_general (&gr, sz, cinfo->args+nParm, TRUE);
1135 // cinfo->args[nParm].size = sizeof(gpointer);
1139 simpletype
= sig
->ret
->type
;
1141 switch (simpletype
) {
1142 case MONO_TYPE_BOOLEAN
:
1147 case MONO_TYPE_CHAR
:
1152 case MONO_TYPE_CLASS
:
1153 case MONO_TYPE_OBJECT
:
1154 case MONO_TYPE_SZARRAY
:
1155 case MONO_TYPE_ARRAY
:
1157 case MONO_TYPE_STRING
:
1158 cinfo
->ret
.reg
= s390_r2
;
1163 cinfo
->ret
.reg
= s390_f0
;
1168 cinfo
->ret
.reg
= s390_r2
;
1171 case MONO_TYPE_VALUETYPE
:
1172 if (sig
->ret
->data
.klass
->enumtype
) {
1173 simpletype
= sig
->ret
->data
.klass
->enum_basetype
->type
;
1177 size
= mono_class_native_size (sig
->ret
->data
.klass
, &align
);
1179 size
= mono_class_value_size (sig
->ret
->data
.klass
, &align
);
1180 cinfo
->ret
.reg
= s390_r2
;
1181 cinfo
->struct_ret
= 1;
1182 cinfo
->ret
.size
= size
;
1183 cinfo
->ret
.vtsize
= size
;
1184 cinfo
->ret
.offset
= sz
->stack_size
;
1185 sz
->stack_size
+= S390_ALIGN(size
, align
);
1188 case MONO_TYPE_TYPEDBYREF
:
1189 case MONO_TYPE_VOID
:
1192 g_error ("Can't handle as return value 0x%x", sig
->ret
->type
);
1197 add_general (&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1198 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1202 /*----------------------------------------------------------*/
1203 /* We determine the size of the parameter code and stack */
1204 /* requirements by checking the types and sizes of the */
1206 /*----------------------------------------------------------*/
1208 for (i
= 0; i
< sig
->param_count
; ++i
) {
1209 if (sig
->params
[i
]->byref
) {
1210 add_general (&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1211 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1215 simpletype
= sig
->params
[i
]->type
;
1217 switch (simpletype
) {
1218 case MONO_TYPE_BOOLEAN
:
1221 cinfo
->args
[nParm
].size
= sizeof(char);
1222 add_general (&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1227 case MONO_TYPE_CHAR
:
1228 cinfo
->args
[nParm
].size
= sizeof(short);
1229 add_general (&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1234 cinfo
->args
[nParm
].size
= sizeof(int);
1235 add_general (&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1241 case MONO_TYPE_CLASS
:
1242 case MONO_TYPE_OBJECT
:
1243 case MONO_TYPE_STRING
:
1244 case MONO_TYPE_SZARRAY
:
1245 case MONO_TYPE_ARRAY
:
1246 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1247 add_general (&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1250 case MONO_TYPE_VALUETYPE
:
1251 if (sig
->params
[i
]->data
.klass
->enumtype
) {
1252 simpletype
= sig
->params
[i
]->data
.klass
->enum_basetype
->type
;
1253 goto enum_calc_size
;
1256 size
= mono_class_native_size (sig
->params
[i
]->data
.klass
, &align
);
1258 size
= mono_class_value_size (sig
->params
[i
]->data
.klass
, &align
);
1259 nWords
= (size
+ sizeof(gpointer
) - 1) /
1262 cinfo
->args
[nParm
].vtsize
= 0;
1263 cinfo
->args
[nParm
].size
= 0;
1264 cinfo
->args
[nParm
].offparm
= sz
->local_size
;
1267 /*----------------------------------*/
1268 /* On S/390, structures of size 1, */
1269 /* 2, 4, and 8 bytes are passed in */
1270 /* (a) register(s). */
1271 /*----------------------------------*/
1276 add_general(&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1277 // cinfo->args[nParm].size = sizeof(int);
1278 cinfo
->args
[nParm
].size
= size
;
1279 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1281 sz
->local_size
+= sizeof(long);
1284 add_general(&gr
, sz
, cinfo
->args
+nParm
, FALSE
);
1285 cinfo
->args
[nParm
].size
= sizeof(long long);
1286 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1288 sz
->local_size
+= sizeof(long);
1291 add_general(&gr
, sz
, cinfo
->args
+nParm
, TRUE
);
1292 cinfo
->args
[nParm
].size
= sizeof(int);
1293 cinfo
->args
[nParm
].regtype
= RegTypeStructByAddr
;
1294 cinfo
->args
[nParm
].vtsize
= size
;
1295 sz
->code_size
+= 40;
1296 sz
->local_size
+= size
;
1297 if (cinfo
->args
[nParm
].reg
== STK_BASE
)
1298 sz
->local_size
+= sizeof(gpointer
);
1304 cinfo
->args
[nParm
].size
= sizeof(long long);
1305 add_general (&gr
, sz
, cinfo
->args
+nParm
, FALSE
);
1309 cinfo
->args
[nParm
].size
= sizeof(float);
1310 if (fr
<= S390_LAST_FPARG_REG
) {
1311 cinfo
->args
[nParm
].regtype
= RegTypeFP
;
1312 cinfo
->args
[nParm
].reg
= fr
;
1317 cinfo
->args
[nParm
].offset
= sz
->stack_size
;
1318 cinfo
->args
[nParm
].reg
= STK_BASE
;
1319 cinfo
->args
[nParm
].regtype
= RegTypeBase
;
1321 sz
->stack_size
+= sizeof(float);
1326 cinfo
->args
[nParm
].size
= sizeof(double);
1327 if (fr
<= S390_LAST_FPARG_REG
) {
1328 cinfo
->args
[nParm
].regtype
= RegTypeFP
;
1329 cinfo
->args
[nParm
].reg
= fr
;
1333 // sz->stack_size = S390_ALIGN(sz->stack_size,
1334 // S390_STACK_ALIGNMENT);
1335 cinfo
->args
[nParm
].offset
= sz
->stack_size
;
1336 cinfo
->args
[nParm
].reg
= STK_BASE
;
1337 cinfo
->args
[nParm
].regtype
= RegTypeBase
;
1339 sz
->stack_size
+= sizeof(double);
1344 g_error ("Can't trampoline 0x%x", sig
->params
[i
]->type
);
1349 /* align stack size */
1350 cinfo
->stack_usage
= S390_ALIGN(sz
->stack_size
+sz
->local_size
,
1351 S390_STACK_ALIGNMENT
);
1355 /*========================= End of Function ========================*/
1357 /*------------------------------------------------------------------*/
1359 /* Name - mono_arch_allocate_vars */
1361 /* Function - Set var information according to the calling */
1362 /* convention for S/390. The local var stuff should */
1363 /* most likely be split in another method. */
1365 /* Parameter - @m - Compile unit. */
1367 /*------------------------------------------------------------------*/
1370 mono_arch_allocate_vars (MonoCompile
*m
)
1372 MonoMethodSignature
*sig
;
1373 MonoMethodHeader
*header
;
1377 int iParm
, iVar
, offset
, size
, align
, curinst
;
1378 int frame_reg
= STK_BASE
;
1381 header
= ((MonoMethodNormal
*)m
->method
)->header
;
1384 * We use the frame register also for any method that has
1385 * filter clauses. This way, when the handlers are called,
1386 * the code will reference local variables using the frame reg instead of
1387 * the stack pointer: if we had to restore the stack pointer, we'd
1388 * corrupt the method frames that are already on the stack (since
1389 * filters get called before stack unwinding happens) when the filter
1390 * code would call any method.
1392 if ((m
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
1393 // if (m->flags & MONO_CFG_HAS_ALLOCA)
1394 frame_reg
= s390_r11
;
1396 m
->frame_reg
= frame_reg
;
1398 if (frame_reg
!= STK_BASE
)
1399 m
->used_int_regs
|= 1 << frame_reg
;
1401 sig
= m
->method
->signature
;
1403 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
1405 if (cinfo
->struct_ret
) {
1406 m
->ret
->opcode
= OP_REGVAR
;
1407 m
->ret
->inst_c0
= s390_r2
;
1409 /* FIXME: handle long and FP values */
1410 switch (sig
->ret
->type
) {
1411 case MONO_TYPE_VOID
:
1414 m
->ret
->opcode
= OP_REGVAR
;
1415 m
->ret
->dreg
= s390_r2
;
1420 /*--------------------------------------------------------------*/
1421 /* local vars are at a positive offset from the stack pointer */
1423 /* also note that if the function uses alloca, we use s390_r11 */
1424 /* to point at the local variables. */
1425 /* add parameter area size for called functions */
1426 /*--------------------------------------------------------------*/
1427 offset
= (m
->param_area
+ S390_MINIMAL_STACK_SIZE
);
1429 if (cinfo
->struct_ret
) {
1431 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1432 inst
->inst_offset
= offset
;
1433 inst
->opcode
= OP_REGOFFSET
;
1434 inst
->inst_basereg
= frame_reg
;
1435 offset
+= sizeof(gpointer
);
1439 inst
= m
->varinfo
[0];
1440 if (inst
->opcode
!= OP_REGVAR
) {
1441 inst
->opcode
= OP_REGOFFSET
;
1442 inst
->inst_basereg
= frame_reg
;
1443 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1444 inst
->inst_offset
= offset
;
1445 offset
+= sizeof (gpointer
);
1452 eArg
= sig
->param_count
+ sArg
;
1454 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
1455 inst
= m
->varinfo
[curinst
];
1456 if (inst
->opcode
!= OP_REGVAR
) {
1457 switch (cinfo
->args
[iParm
].regtype
) {
1458 case RegTypeStructByAddr
:
1459 inst
->opcode
= OP_S390_LOADARG
;
1460 inst
->inst_basereg
= frame_reg
;
1461 // size = sizeof(long);
1462 size
= abs(cinfo
->args
[iParm
].vtsize
);
1463 offset
= S390_ALIGN(offset
, size
);
1464 inst
->inst_offset
= offset
;
1466 case RegTypeStructByVal
:
1467 inst
->opcode
= OP_S390_ARGPTR
;
1468 inst
->inst_basereg
= frame_reg
;
1469 size
= cinfo
->args
[iParm
].size
;
1470 offset
= S390_ALIGN(offset
, size
);
1471 inst
->inst_offset
= offset
;
1474 if (cinfo
->args
[iParm
].reg
!= STK_BASE
) {
1475 inst
->opcode
= OP_REGOFFSET
;
1476 inst
->inst_basereg
= frame_reg
;
1477 size
= (cinfo
->args
[iParm
].size
< 8
1479 : sizeof(long long));
1480 offset
= S390_ALIGN(offset
, size
);
1481 inst
->inst_offset
= offset
;
1483 inst
->opcode
= OP_S390_STKARG
;
1484 inst
->inst_basereg
= frame_reg
;
1485 size
= (cinfo
->args
[iParm
].size
< 4
1486 ? 4 - cinfo
->args
[iParm
].size
1488 inst
->inst_offset
= cinfo
->args
[iParm
].offset
+
1490 // inst->unused = stackOffset;
1492 size
= sizeof(long);
1500 curinst
= m
->locals_start
;
1501 for (iVar
= curinst
; iVar
< m
->num_varinfo
; ++iVar
) {
1502 inst
= m
->varinfo
[iVar
];
1503 if (inst
->opcode
== OP_REGVAR
)
1506 /* inst->unused indicates native sized value types, this is used by the
1507 * pinvoke wrappers when they call functions returning structure */
1508 if (inst
->unused
&& MONO_TYPE_ISSTRUCT (inst
->inst_vtype
))
1509 size
= mono_class_native_size (inst
->inst_vtype
->data
.klass
, &align
);
1511 size
= mono_type_size (inst
->inst_vtype
, &align
);
1513 offset
= S390_ALIGN(offset
, align
);
1514 inst
->inst_offset
= offset
;
1515 inst
->opcode
= OP_REGOFFSET
;
1516 inst
->inst_basereg
= frame_reg
;
1518 //DEBUG (g_print("allocating local %d to %d\n", iVar, inst->inst_offset));
1521 // if (sig->hasthis)
1522 // curinst = sArg = 1;
1524 // curinst = sArg = 0;
1527 /*------------------------------------------------------*/
1528 /* Allow space for the trace method stack area if needed*/
1529 /*------------------------------------------------------*/
1530 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (m
))
1531 offset
+= S390_TRACE_STACK_SIZE
;
1533 /*------------------------------------------------------*/
1534 /* Reserve space to save LMF and caller saved registers */
1535 /*------------------------------------------------------*/
1536 if (m
->method
->save_lmf
)
1537 offset
+= sizeof (MonoLMF
);
1539 /*------------------------------------------------------*/
1540 /* align the offset */
1541 /*------------------------------------------------------*/
1542 m
->stack_offset
= S390_ALIGN(offset
, S390_STACK_ALIGNMENT
);
1546 /*========================= End of Function ========================*/
1548 /*------------------------------------------------------------------*/
1550 /* Name - mono_arch_call_opcode */
1552 /* Function - Take the arguments and generate the arch-specific */
1553 /* instructions to properly call the function. This */
1554 /* includes pushing, moving argments to the correct */
1557 /* Note - FIXME: We need an alignment solution for */
1558 /* enter_method and mono_arch_call_opcode, currently */
1559 /* alignment in mono_arch_call_opcode is computed */
1560 /* without arch_get_argument_info. */
1562 /*------------------------------------------------------------------*/
1565 mono_arch_call_opcode (MonoCompile
*cfg
, MonoBasicBlock
* bb
, MonoCallInst
*call
, int is_virtual
) {
1567 MonoMethodSignature
*sig
;
1568 int i
, n
, lParamArea
;
1573 sig
= call
->signature
;
1574 n
= sig
->param_count
+ sig
->hasthis
;
1575 DEBUG (g_print ("Call requires: %d parameters\n",n
));
1577 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
1579 call
->stack_usage
= cinfo
->stack_usage
;
1580 lParamArea
= cinfo
->stack_usage
- S390_MINIMAL_STACK_SIZE
;
1581 cfg
->param_area
= MAX (cfg
->param_area
, lParamArea
);
1582 cfg
->flags
|= MONO_CFG_HAS_CALLS
;
1583 /*----------------------------------------------------------*/
1584 /* should set more info in call, such as the stack space */
1585 /* used by the args that needs to be added back to esp */
1586 /*----------------------------------------------------------*/
1588 if (cinfo
->struct_ret
)
1589 call
->used_iregs
|= 1 << cinfo
->struct_ret
;
1591 for (i
= 0; i
< n
; ++i
) {
1592 ainfo
= cinfo
->args
+ i
;
1593 DEBUG (g_print ("Parameter %d - Register: %d Type: %d\n",
1594 i
+1,ainfo
->reg
,ainfo
->regtype
));
1595 if (is_virtual
&& i
== 0) {
1596 /* the argument will be attached to the call instrucion */
1597 in
= call
->args
[i
];
1598 call
->used_iregs
|= 1 << ainfo
->reg
;
1600 MONO_INST_NEW (cfg
, arg
, OP_OUTARG
);
1601 in
= call
->args
[i
];
1602 arg
->cil_code
= in
->cil_code
;
1603 arg
->inst_left
= in
;
1604 arg
->type
= in
->type
;
1605 /* prepend, we'll need to reverse them later */
1606 arg
->next
= call
->out_args
;
1607 call
->out_args
= arg
;
1608 if (ainfo
->regtype
== RegTypeGeneral
) {
1609 arg
->unused
= ainfo
->reg
;
1610 call
->used_iregs
|= 1 << ainfo
->reg
;
1611 if (arg
->type
== STACK_I8
)
1612 call
->used_iregs
|= 1 << (ainfo
->reg
+ 1);
1613 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
1614 call
->used_iregs
|= 1 << ainfo
->reg
;
1615 arg
->sreg1
= ainfo
->reg
;
1616 arg
->opcode
= OP_OUTARG_VT
;
1617 arg
->unused
= -ainfo
->vtsize
;
1618 arg
->inst_imm
= ainfo
->offset
;
1619 arg
->sreg2
= ainfo
->offparm
+ S390_MINIMAL_STACK_SIZE
;
1620 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
1621 if (ainfo
->reg
!= STK_BASE
) {
1622 switch (ainfo
->size
) {
1627 call
->used_iregs
|= 1 << ainfo
->reg
;
1630 call
->used_iregs
|= 1 << ainfo
->reg
;
1631 call
->used_iregs
|= 1 << (ainfo
->reg
+1);
1634 call
->used_iregs
|= 1 << ainfo
->reg
;
1637 arg
->sreg1
= ainfo
->reg
;
1638 arg
->opcode
= OP_OUTARG_VT
;
1639 arg
->unused
= ainfo
->size
;
1640 arg
->inst_imm
= ainfo
->offset
;
1641 arg
->sreg2
= ainfo
->offparm
+ S390_MINIMAL_STACK_SIZE
;
1642 } else if (ainfo
->regtype
== RegTypeBase
) {
1643 arg
->opcode
= OP_OUTARG
;
1644 arg
->unused
= ainfo
->reg
| (ainfo
->size
<< 8);
1645 arg
->inst_imm
= ainfo
->offset
;
1646 call
->used_fregs
|= 1 << ainfo
->reg
;
1647 } else if (ainfo
->regtype
== RegTypeFP
) {
1648 // arg->opcode = OP_OUTARG_R8;
1649 // arg->unused = ainfo->reg;
1650 // call->used_fregs |= 1 << ainfo->reg;
1651 // if (ainfo->size == 4) {
1652 // /* we reduce the precision */
1654 // MONO_INST_NEW (cfg, conv, OP_FCONV_TO_R4);
1655 // conv->inst_left = arg->inst_left;
1656 // arg->inst_left = conv;
1658 arg
->unused
= ainfo
->reg
;
1659 call
->used_fregs
|= 1 << ainfo
->reg
;
1660 if (ainfo
->size
== 4) {
1662 arg
->opcode
= OP_OUTARG_R4
;
1663 MONO_INST_NEW (cfg
, conv
, OP_FCONV_TO_R4
);
1664 conv
->inst_left
= arg
->inst_left
;
1665 arg
->inst_left
= conv
;
1668 arg
->opcode
= OP_OUTARG_R8
;
1670 g_assert_not_reached ();
1675 * Reverse the call->out_args list.
1678 MonoInst
*prev
= NULL
, *list
= call
->out_args
, *next
;
1685 call
->out_args
= prev
;
1692 /*========================= End of Function ========================*/
1694 /*------------------------------------------------------------------*/
1696 /* Name - mono_arch_instrument_mem_needs */
1698 /* Function - Allow tracing to work with this interface (with */
1699 /* an optional argument). */
1701 /*------------------------------------------------------------------*/
1704 mono_arch_instrument_mem_needs (MonoMethod
*method
, int *stack
, int *code
)
1706 /* no stack room needed now (may be needed for FASTCALL-trace support) */
1708 /* split prolog-epilog requirements? */
1709 *code
= 50; /* max bytes needed: check this number */
1712 /*========================= End of Function ========================*/
1714 /*------------------------------------------------------------------*/
1716 /* Name - mono_arch_instrument_prolog */
1718 /* Function - Create an "instrumented" prolog. */
1720 /*------------------------------------------------------------------*/
1723 mono_arch_instrument_prolog (MonoCompile
*cfg
, void *func
, void *p
,
1724 gboolean enable_arguments
)
1730 parmOffset
= cfg
->stack_usage
- S390_TRACE_STACK_SIZE
;
1731 if (cfg
->method
->save_lmf
)
1732 parmOffset
-= sizeof(MonoLMF
);
1733 fpOffset
= parmOffset
+ (5*sizeof(gint32
));
1735 s390_stm (code
, s390_r2
, s390_r6
, STK_BASE
, parmOffset
);
1736 s390_std (code
, s390_f0
, 0, STK_BASE
, fpOffset
);
1737 s390_std (code
, s390_f1
, 0, STK_BASE
, fpOffset
+sizeof(gdouble
));
1738 s390_std (code
, s390_f2
, 0, STK_BASE
, fpOffset
+2*sizeof(gdouble
));
1739 s390_basr (code
, s390_r13
, 0);
1741 s390_word (code
, cfg
->method
);
1742 s390_word (code
, func
);
1743 s390_l (code
, s390_r2
, 0, s390_r13
, 4);
1744 s390_la (code
, s390_r3
, 0, STK_BASE
, parmOffset
);
1745 s390_lr (code
, s390_r4
, STK_BASE
);
1746 s390_ahi (code
, s390_r4
, cfg
->stack_usage
);
1747 s390_l (code
, s390_r1
, 0, s390_r13
, 8);
1748 s390_basr (code
, s390_r14
, s390_r1
);
1749 s390_ld (code
, s390_f2
, 0, STK_BASE
, fpOffset
+2*sizeof(gdouble
));
1750 s390_ld (code
, s390_f1
, 0, STK_BASE
, fpOffset
+sizeof(gdouble
));
1751 s390_ld (code
, s390_f0
, 0, STK_BASE
, fpOffset
);
1752 s390_lm (code
, s390_r2
, s390_r6
, STK_BASE
, parmOffset
);
1757 /*========================= End of Function ========================*/
1759 /*------------------------------------------------------------------*/
1761 /* Name - mono_arch_instrument_epilog */
1763 /* Function - Create an epilog that will handle the returned */
1764 /* values used in instrumentation. */
1766 /*------------------------------------------------------------------*/
1769 mono_arch_instrument_epilog (MonoCompile
*cfg
, void *func
, void *p
, gboolean enable_arguments
)
1772 int save_mode
= SAVE_NONE
,
1774 MonoMethod
*method
= cfg
->method
;
1775 int rtype
= method
->signature
->ret
->type
;
1777 saveOffset
= cfg
->stack_usage
- S390_TRACE_STACK_SIZE
;
1778 if (method
->save_lmf
)
1779 saveOffset
-= sizeof(MonoLMF
);
1783 case MONO_TYPE_VOID
:
1784 /* special case string .ctor icall */
1785 if (strcmp (".ctor", method
->name
) && method
->klass
== mono_defaults
.string_class
)
1786 save_mode
= SAVE_ONE
;
1788 save_mode
= SAVE_NONE
;
1792 save_mode
= SAVE_TWO
;
1796 save_mode
= SAVE_FP
;
1798 case MONO_TYPE_VALUETYPE
:
1799 if (method
->signature
->ret
->data
.klass
->enumtype
) {
1800 rtype
= method
->signature
->ret
->data
.klass
->enum_basetype
->type
;
1803 save_mode
= SAVE_STRUCT
;
1806 save_mode
= SAVE_ONE
;
1810 switch (save_mode
) {
1812 s390_stm (code
, s390_r2
, s390_r3
, cfg
->frame_reg
, saveOffset
);
1813 if (enable_arguments
) {
1814 s390_lr (code
, s390_r4
, s390_r3
);
1815 s390_lr (code
, s390_r3
, s390_r2
);
1819 s390_st (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1820 if (enable_arguments
) {
1821 s390_lr (code
, s390_r3
, s390_r2
);
1825 s390_std (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
1826 if (enable_arguments
) {
1827 /* FIXME: what reg? */
1828 s390_ldr (code
, s390_f2
, s390_f0
);
1829 s390_lm (code
, s390_r3
, s390_r4
, cfg
->frame_reg
, saveOffset
);
1833 s390_st (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1834 if (enable_arguments
) {
1835 s390_l (code
, s390_r3
, 0, cfg
->frame_reg
,
1836 S390_MINIMAL_STACK_SIZE
+cfg
->param_area
);
1844 s390_basr (code
, s390_r13
, 0);
1846 s390_word (code
, cfg
->method
);
1847 s390_word (code
, func
);
1848 s390_l (code
, s390_r2
, 0, s390_r13
, 4);
1849 s390_l (code
, s390_r1
, 0, s390_r13
, 8);
1850 s390_basr (code
, s390_r14
, s390_r1
);
1852 switch (save_mode
) {
1854 s390_lm (code
, s390_r2
, s390_r3
, cfg
->frame_reg
, saveOffset
);
1857 s390_l (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1860 s390_ld (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
1863 s390_l (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1873 /*========================= End of Function ========================*/
1875 /*------------------------------------------------------------------*/
1877 /* Name - peephole_pass */
1879 /* Function - Form a peephole pass at the code looking for */
1880 /* simple optimizations. */
1882 /*------------------------------------------------------------------*/
1885 peephole_pass (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
1887 MonoInst
*ins
, *last_ins
= NULL
;
1892 switch (ins
->opcode
) {
1894 /* remove unnecessary multiplication with 1 */
1895 if (ins
->inst_imm
== 1) {
1896 if (ins
->dreg
!= ins
->sreg1
) {
1897 ins
->opcode
= OP_MOVE
;
1899 last_ins
->next
= ins
->next
;
1905 case OP_LOAD_MEMBASE
:
1906 case OP_LOADI4_MEMBASE
:
1908 * OP_STORE_MEMBASE_REG reg, offset(basereg)
1909 * OP_LOAD_MEMBASE offset(basereg), reg
1911 if (last_ins
&& (last_ins
->opcode
== OP_STOREI4_MEMBASE_REG
1912 || last_ins
->opcode
== OP_STORE_MEMBASE_REG
) &&
1913 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1914 ins
->inst_offset
== last_ins
->inst_offset
) {
1915 if (ins
->dreg
== last_ins
->sreg1
) {
1916 last_ins
->next
= ins
->next
;
1920 //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
1921 ins
->opcode
= OP_MOVE
;
1922 ins
->sreg1
= last_ins
->sreg1
;
1926 * Note: reg1 must be different from the basereg in the second load
1927 * OP_LOAD_MEMBASE offset(basereg), reg1
1928 * OP_LOAD_MEMBASE offset(basereg), reg2
1930 * OP_LOAD_MEMBASE offset(basereg), reg1
1931 * OP_MOVE reg1, reg2
1933 } if (last_ins
&& (last_ins
->opcode
== OP_LOADI4_MEMBASE
1934 || last_ins
->opcode
== OP_LOAD_MEMBASE
) &&
1935 ins
->inst_basereg
!= last_ins
->dreg
&&
1936 ins
->inst_basereg
== last_ins
->inst_basereg
&&
1937 ins
->inst_offset
== last_ins
->inst_offset
) {
1939 if (ins
->dreg
== last_ins
->dreg
) {
1940 last_ins
->next
= ins
->next
;
1944 ins
->opcode
= OP_MOVE
;
1945 ins
->sreg1
= last_ins
->dreg
;
1948 //g_assert_not_reached ();
1952 * OP_STORE_MEMBASE_IMM imm, offset(basereg)
1953 * OP_LOAD_MEMBASE offset(basereg), reg
1955 * OP_STORE_MEMBASE_IMM imm, offset(basereg)
1956 * OP_ICONST reg, imm
1958 } else if (last_ins
&& (last_ins
->opcode
== OP_STOREI4_MEMBASE_IMM
1959 || last_ins
->opcode
== OP_STORE_MEMBASE_IMM
) &&
1960 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1961 ins
->inst_offset
== last_ins
->inst_offset
) {
1962 //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
1963 ins
->opcode
= OP_ICONST
;
1964 ins
->inst_c0
= last_ins
->inst_imm
;
1965 g_assert_not_reached (); // check this rule
1969 case OP_LOADU1_MEMBASE
:
1970 case OP_LOADI1_MEMBASE
:
1971 if (last_ins
&& (last_ins
->opcode
== OP_STOREI1_MEMBASE_REG
) &&
1972 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1973 ins
->inst_offset
== last_ins
->inst_offset
) {
1974 if (ins
->dreg
== last_ins
->sreg1
) {
1975 last_ins
->next
= ins
->next
;
1979 //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
1980 ins
->opcode
= OP_MOVE
;
1981 ins
->sreg1
= last_ins
->sreg1
;
1985 case OP_LOADU2_MEMBASE
:
1986 case OP_LOADI2_MEMBASE
:
1987 if (last_ins
&& (last_ins
->opcode
== OP_STOREI2_MEMBASE_REG
) &&
1988 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1989 ins
->inst_offset
== last_ins
->inst_offset
) {
1990 if (ins
->dreg
== last_ins
->sreg1
) {
1991 last_ins
->next
= ins
->next
;
1995 ins
->opcode
= OP_MOVE
;
1996 ins
->sreg1
= last_ins
->sreg1
;
2006 if (ins
->dreg
== ins
->sreg1
) {
2008 last_ins
->next
= ins
->next
;
2013 * OP_MOVE sreg, dreg
2014 * OP_MOVE dreg, sreg
2016 if (last_ins
&& last_ins
->opcode
== OP_MOVE
&&
2017 ins
->sreg1
== last_ins
->dreg
&&
2018 ins
->dreg
== last_ins
->sreg1
) {
2019 last_ins
->next
= ins
->next
;
2028 bb
->last_ins
= last_ins
;
2031 /*========================= End of Function ========================*/
2033 /*------------------------------------------------------------------*/
2035 /* Name - mono_spillvar_offset */
2037 /* Function - Returns the offset used by spillvar. It allocates */
2038 /* a new spill variable if necessary. */
2040 /*------------------------------------------------------------------*/
2043 mono_spillvar_offset (MonoCompile
*cfg
, int spillvar
)
2045 MonoSpillInfo
**si
, *info
;
2048 si
= &cfg
->spill_info
;
2050 while (i
<= spillvar
) {
2053 *si
= info
= mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSpillInfo
));
2055 info
->offset
= cfg
->stack_offset
;
2056 cfg
->stack_offset
+= sizeof (gpointer
);
2060 return (*si
)->offset
;
2066 g_assert_not_reached ();
2070 /*========================= End of Function ========================*/
2072 /*------------------------------------------------------------------*/
2074 /* Name - mono_spillvar_offset_float */
2078 /*------------------------------------------------------------------*/
2081 mono_spillvar_offset_float (MonoCompile
*cfg
, int spillvar
)
2083 MonoSpillInfo
**si
, *info
;
2086 si
= &cfg
->spill_info_float
;
2088 while (i
<= spillvar
) {
2091 *si
= info
= mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSpillInfo
));
2093 cfg
->stack_offset
= S390_ALIGN(cfg
->stack_offset
, S390_STACK_ALIGNMENT
);
2094 info
->offset
= cfg
->stack_offset
;
2095 cfg
->stack_offset
+= sizeof (double);
2099 return (*si
)->offset
;
2105 g_assert_not_reached ();
2109 /*========================= End of Function ========================*/
2111 /*------------------------------------------------------------------*/
2113 /* Name - print_ins */
2115 /* Function - Decode and print the instruction for tracing. */
2117 /*------------------------------------------------------------------*/
2120 print_ins (int i
, MonoInst
*ins
)
2122 const char *spec
= ins_spec
[ins
->opcode
];
2123 g_print ("\t%-2d %s", i
, mono_inst_name (ins
->opcode
));
2124 if (spec
[MONO_INST_DEST
]) {
2125 if (ins
->dreg
>= MONO_MAX_IREGS
)
2126 g_print (" R%d <-", ins
->dreg
);
2128 g_print (" %s <-", mono_arch_regname (ins
->dreg
));
2130 if (spec
[MONO_INST_SRC1
]) {
2131 if (ins
->sreg1
>= MONO_MAX_IREGS
)
2132 g_print (" R%d", ins
->sreg1
);
2134 g_print (" %s", mono_arch_regname (ins
->sreg1
));
2136 if (spec
[MONO_INST_SRC2
]) {
2137 if (ins
->sreg2
>= MONO_MAX_IREGS
)
2138 g_print (" R%d", ins
->sreg2
);
2140 g_print (" %s", mono_arch_regname (ins
->sreg2
));
2142 if (spec
[MONO_INST_CLOB
])
2143 g_print (" clobbers: %c", spec
[MONO_INST_CLOB
]);
2147 /*========================= End of Function ========================*/
2149 /*------------------------------------------------------------------*/
2151 /* Name - print_regtrack. */
2155 /*------------------------------------------------------------------*/
2158 print_regtrack (RegTrack
*t
, int num
)
2164 for (i
= 0; i
< num
; ++i
) {
2167 if (i
>= MONO_MAX_IREGS
) {
2168 g_snprintf (buf
, sizeof(buf
), "R%d", i
);
2171 r
= mono_arch_regname (i
);
2172 g_print ("liveness: %s [%d - %d]\n", r
, t
[i
].born_in
, t
[i
].last_use
);
2176 /*========================= End of Function ========================*/
2178 /*------------------------------------------------------------------*/
2180 /* Name - inst_list_prepend */
2182 /* Function - Prepend an instruction to the list. */
2184 /*------------------------------------------------------------------*/
2186 static inline InstList
*
2187 inst_list_prepend (MonoMemPool
*pool
, InstList
*list
, MonoInst
*data
)
2189 InstList
*item
= mono_mempool_alloc (pool
, sizeof (InstList
));
2198 /*========================= End of Function ========================*/
2200 /*------------------------------------------------------------------*/
2202 /* Name - get_register_force_spilling */
2204 /* Function - Force the spilling of the variable in the */
2205 /* symbolic register 'reg'. */
2207 /*------------------------------------------------------------------*/
2210 get_register_force_spilling (MonoCompile
*cfg
, InstList
*item
, MonoInst
*ins
, int reg
)
2215 sel
= cfg
->rs
->iassign
[reg
];
2217 spill
= ++cfg
->spill_count
;
2218 cfg
->rs
->iassign
[i
] = -spill
- 1;
2219 mono_regstate_free_int (cfg
->rs
, sel
);
2220 /*----------------------------------------------------------*/
2221 /* we need to create a spill var and insert a load to sel */
2222 /* after the current instruction */
2223 /*----------------------------------------------------------*/
2224 MONO_INST_NEW (cfg
, load
, OP_LOAD_MEMBASE
);
2226 load
->inst_basereg
= cfg
->frame_reg
;
2227 load
->inst_offset
= mono_spillvar_offset (cfg
, spill
);
2229 while (ins
->next
!= item
->prev
->data
)
2232 load
->next
= ins
->next
;
2234 DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n",
2235 spill
, load
->inst_offset
, i
, mono_arch_regname (sel
)));
2236 i
= mono_regstate_alloc_int (cfg
->rs
, 1 << sel
);
2237 g_assert (i
== sel
);
2242 /*========================= End of Function ========================*/
2244 /*------------------------------------------------------------------*/
2246 /* Name - get_register_spilling */
2250 /*------------------------------------------------------------------*/
2253 get_register_spilling (MonoCompile
*cfg
, InstList
*item
, MonoInst
*ins
, guint32 regmask
, int reg
)
2258 DEBUG (g_print ("start regmask to assign R%d: 0x%08x (R%d <- R%d R%d)\n", reg
, regmask
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
));
2259 /* exclude the registers in the current instruction */
2260 if (reg
!= ins
->sreg1
&&
2261 (reg_is_freeable (ins
->sreg1
) ||
2262 (ins
->sreg1
>= MONO_MAX_IREGS
&&
2263 cfg
->rs
->iassign
[ins
->sreg1
] >= 0))) {
2264 if (ins
->sreg1
>= MONO_MAX_IREGS
)
2265 regmask
&= ~ (1 << cfg
->rs
->iassign
[ins
->sreg1
]);
2267 regmask
&= ~ (1 << ins
->sreg1
);
2268 DEBUG (g_print ("excluding sreg1 %s\n", mono_arch_regname (ins
->sreg1
)));
2270 if (reg
!= ins
->sreg2
&&
2271 (reg_is_freeable (ins
->sreg2
) ||
2272 (ins
->sreg2
>= MONO_MAX_IREGS
&&
2273 cfg
->rs
->iassign
[ins
->sreg2
] >= 0))) {
2274 if (ins
->sreg2
>= MONO_MAX_IREGS
)
2275 regmask
&= ~ (1 << cfg
->rs
->iassign
[ins
->sreg2
]);
2277 regmask
&= ~ (1 << ins
->sreg2
);
2278 DEBUG (g_print ("excluding sreg2 %s %d\n", mono_arch_regname (ins
->sreg2
), ins
->sreg2
));
2280 if (reg
!= ins
->dreg
&& reg_is_freeable (ins
->dreg
)) {
2281 regmask
&= ~ (1 << ins
->dreg
);
2282 DEBUG (g_print ("excluding dreg %s\n", mono_arch_regname (ins
->dreg
)));
2285 DEBUG (g_print ("available regmask: 0x%08x\n", regmask
));
2286 g_assert (regmask
); /* need at least a register we can free */
2288 /* we should track prev_use and spill the register that's farther */
2289 for (i
= 0; i
< MONO_MAX_IREGS
; ++i
) {
2290 if (regmask
& (1 << i
)) {
2292 DEBUG (g_print ("selected register %s has assignment %d\n", mono_arch_regname (sel
), cfg
->rs
->iassign
[sel
]));
2296 i
= cfg
->rs
->isymbolic
[sel
];
2297 spill
= ++cfg
->spill_count
;
2298 cfg
->rs
->iassign
[i
] = -spill
- 1;
2299 mono_regstate_free_int (cfg
->rs
, sel
);
2300 /* we need to create a spill var and insert a load to sel after the current instruction */
2301 MONO_INST_NEW (cfg
, load
, OP_LOAD_MEMBASE
);
2303 load
->inst_basereg
= cfg
->frame_reg
;
2304 load
->inst_offset
= mono_spillvar_offset (cfg
, spill
);
2306 while (ins
->next
!= item
->prev
->data
)
2309 load
->next
= ins
->next
;
2311 DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", spill
, load
->inst_offset
, i
, mono_arch_regname (sel
)));
2312 i
= mono_regstate_alloc_int (cfg
->rs
, 1 << sel
);
2313 g_assert (i
== sel
);
2318 /*========================= End of Function ========================*/
2320 /*------------------------------------------------------------------*/
2322 /* Name - get_float_register_spilling */
2326 /*------------------------------------------------------------------*/
2329 get_float_register_spilling (MonoCompile
*cfg
, InstList
*item
, MonoInst
*ins
, guint32 regmask
, int reg
)
2334 DEBUG (g_print ("start regmask to assign R%d: 0x%08x (R%d <- R%d R%d)\n", reg
, regmask
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
));
2335 /* exclude the registers in the current instruction */
2336 if (reg
!= ins
->sreg1
&&
2337 (freg_is_freeable (ins
->sreg1
) ||
2338 (ins
->sreg1
>= MONO_MAX_FREGS
&&
2339 cfg
->rs
->fassign
[ins
->sreg1
] >= 0))) {
2340 if (ins
->sreg1
>= MONO_MAX_FREGS
)
2341 regmask
&= ~ (1 << cfg
->rs
->fassign
[ins
->sreg1
]);
2343 regmask
&= ~ (1 << ins
->sreg1
);
2344 DEBUG (g_print ("excluding sreg1 %s\n", mono_arch_regname (ins
->sreg1
)));
2346 if (reg
!= ins
->sreg2
&&
2347 (freg_is_freeable (ins
->sreg2
) ||
2348 (ins
->sreg2
>= MONO_MAX_FREGS
&&
2349 cfg
->rs
->fassign
[ins
->sreg2
] >= 0))) {
2350 if (ins
->sreg2
>= MONO_MAX_FREGS
)
2351 regmask
&= ~ (1 << cfg
->rs
->fassign
[ins
->sreg2
]);
2353 regmask
&= ~ (1 << ins
->sreg2
);
2354 DEBUG (g_print ("excluding sreg2 %s %d\n", mono_arch_regname (ins
->sreg2
), ins
->sreg2
));
2356 if (reg
!= ins
->dreg
&& freg_is_freeable (ins
->dreg
)) {
2357 regmask
&= ~ (1 << ins
->dreg
);
2358 DEBUG (g_print ("excluding dreg %s\n", mono_arch_regname (ins
->dreg
)));
2361 DEBUG (g_print ("available regmask: 0x%08x\n", regmask
));
2362 g_assert (regmask
); /* need at least a register we can free */
2364 /* we should track prev_use and spill the register that's farther */
2365 for (i
= 0; i
< MONO_MAX_FREGS
; ++i
) {
2366 if (regmask
& (1 << i
)) {
2368 DEBUG (g_print ("selected register %s has assignment %d\n",
2369 mono_arch_regname (sel
), cfg
->rs
->fassign
[sel
]));
2373 i
= cfg
->rs
->fsymbolic
[sel
];
2374 spill
= ++cfg
->spill_count
;
2375 cfg
->rs
->fassign
[i
] = -spill
- 1;
2376 mono_regstate_free_float(cfg
->rs
, sel
);
2377 /* we need to create a spill var and insert a load to sel after the current instruction */
2378 MONO_INST_NEW (cfg
, load
, OP_LOADR8_MEMBASE
);
2380 load
->inst_basereg
= cfg
->frame_reg
;
2381 load
->inst_offset
= mono_spillvar_offset_float (cfg
, spill
);
2383 while (ins
->next
!= item
->prev
->data
)
2386 load
->next
= ins
->next
;
2388 DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", spill
, load
->inst_offset
, i
, mono_arch_regname (sel
)));
2389 i
= mono_regstate_alloc_float (cfg
->rs
, 1 << sel
);
2390 g_assert (i
== sel
);
2395 /*========================= End of Function ========================*/
2397 /*------------------------------------------------------------------*/
2399 /* Name - create_copy_ins */
2401 /* Function - Create an instruction to copy from reg to reg. */
2403 /*------------------------------------------------------------------*/
2406 create_copy_ins (MonoCompile
*cfg
, int dest
, int src
, MonoInst
*ins
)
2409 MONO_INST_NEW (cfg
, copy
, OP_MOVE
);
2413 copy
->next
= ins
->next
;
2416 DEBUG (g_print ("\tforced copy from %s to %s\n",
2417 mono_arch_regname (src
), mono_arch_regname (dest
)));
2421 /*========================= End of Function ========================*/
2423 /*------------------------------------------------------------------*/
2425 /* Name - create_copy_ins_float */
2427 /* Function - Create an instruction to copy from float reg to */
2430 /*------------------------------------------------------------------*/
2433 create_copy_ins_float (MonoCompile
*cfg
, int dest
, int src
, MonoInst
*ins
)
2436 MONO_INST_NEW (cfg
, copy
, OP_FMOVE
);
2440 copy
->next
= ins
->next
;
2443 DEBUG (g_print ("\tforced copy from %s to %s\n",
2444 mono_arch_regname (src
), mono_arch_regname (dest
)));
2448 /*========================= End of Function ========================*/
2450 /*------------------------------------------------------------------*/
2452 /* Name - create_spilled_store */
2454 /* Function - Spill register to storage. */
2456 /*------------------------------------------------------------------*/
2459 create_spilled_store (MonoCompile
*cfg
, int spill
, int reg
, int prev_reg
, MonoInst
*ins
)
2462 MONO_INST_NEW (cfg
, store
, OP_STORE_MEMBASE_REG
);
2464 store
->inst_destbasereg
= cfg
->frame_reg
;
2465 store
->inst_offset
= mono_spillvar_offset (cfg
, spill
);
2467 store
->next
= ins
->next
;
2470 DEBUG (g_print ("SPILLED STORE (%d at 0x%08x(%%sp)) R%d (from %s)\n",
2471 spill
, store
->inst_offset
, prev_reg
, mono_arch_regname (reg
)));
2475 /*========================= End of Function ========================*/
2477 /*------------------------------------------------------------------*/
2479 /* Name - create_spilled_store_float */
2481 /* Function - Spill floating point register to storage. */
2483 /*------------------------------------------------------------------*/
2486 create_spilled_store_float (MonoCompile
*cfg
, int spill
, int reg
, int prev_reg
, MonoInst
*ins
)
2489 MONO_INST_NEW (cfg
, store
, OP_STORER8_MEMBASE_REG
);
2491 store
->inst_destbasereg
= cfg
->frame_reg
;
2492 store
->inst_offset
= mono_spillvar_offset_float (cfg
, spill
);
2494 store
->next
= ins
->next
;
2497 DEBUG (g_print ("SPILLED STORE (%d at 0x%08x(%%sp)) R%d (from %s)\n",
2498 spill
, store
->inst_offset
, prev_reg
, mono_arch_regname (reg
)));
2502 /*========================= End of Function ========================*/
2504 /*------------------------------------------------------------------*/
2506 /* Name - insert_before_ins */
2508 /* Function - Insert an instruction before another. */
2510 /*------------------------------------------------------------------*/
2513 insert_before_ins (MonoInst
*ins
, InstList
*item
, MonoInst
* to_insert
)
2516 g_assert (item
->next
);
2517 prev
= item
->next
->data
;
2519 while (prev
->next
!= ins
)
2521 to_insert
->next
= ins
;
2522 prev
->next
= to_insert
;
2524 * needed otherwise in the next instruction we can add an ins to the
2525 * end and that would get past this instruction.
2527 item
->data
= to_insert
;
2530 /*========================= End of Function ========================*/
2532 /*------------------------------------------------------------------*/
2534 /* Name - alloc_int_reg */
2536 /* Function - Allocate a general register. */
2538 /*------------------------------------------------------------------*/
2541 alloc_int_reg (MonoCompile
*cfg
, InstList
*curinst
, MonoInst
*ins
, int sym_reg
, guint32 allow_mask
)
2543 int val
= cfg
->rs
->iassign
[sym_reg
];
2544 DEBUG (g_print ("Allocating a general register for %d (%d) with mask %08x\n",val
,sym_reg
,allow_mask
));
2548 /* the register gets spilled after this inst */
2551 val
= mono_regstate_alloc_int (cfg
->rs
, allow_mask
);
2553 val
= get_register_spilling (cfg
, curinst
, ins
, allow_mask
, sym_reg
);
2554 cfg
->rs
->iassign
[sym_reg
] = val
;
2555 /* add option to store before the instruction for src registers */
2557 create_spilled_store (cfg
, spill
, val
, sym_reg
, ins
);
2559 DEBUG (g_print ("Allocated %d for %d\n",val
,sym_reg
));
2560 cfg
->rs
->isymbolic
[val
] = sym_reg
;
2564 /*========================= End of Function ========================*/
2566 /*------------------------------------------------------------------*/
2568 /* Name - mono_arch_local_regalloc. */
2570 /* Function - We first scan the list of instructions and we */
2571 /* save the liveness information of each register */
2572 /* (when the register is first used, when its value */
2573 /* is set etc.). We also reverse the list of instr- */
2574 /* uctions (in the InstList list) because assigning */
2575 /* registers backwards allows for more tricks to be */
2578 /*------------------------------------------------------------------*/
2581 mono_arch_local_regalloc (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2584 MonoRegState
*rs
= cfg
->rs
;
2586 RegTrack
*reginfo
, *reginfof
;
2587 RegTrack
*reginfo1
, *reginfo2
, *reginfod
;
2588 InstList
*tmp
, *reversed
= NULL
;
2590 guint32 src1_mask
, src2_mask
, dest_mask
;
2591 guint32 cur_iregs
, cur_fregs
;
2595 rs
->next_vireg
= bb
->max_ireg
;
2596 rs
->next_vfreg
= bb
->max_freg
;
2597 mono_regstate_assign (rs
);
2598 reginfo
= mono_mempool_alloc0 (cfg
->mempool
, sizeof (RegTrack
) * rs
->next_vireg
);
2599 reginfof
= mono_mempool_alloc0 (cfg
->mempool
, sizeof (RegTrack
) * rs
->next_vfreg
);
2600 rs
->ifree_mask
= S390_CALLER_REGS
;
2601 rs
->ffree_mask
= S390_CALLER_FREGS
;
2605 DEBUG (g_print ("LOCAL regalloc: basic block: %d\n", bb
->block_num
));
2606 /* forward pass on the instructions to collect register liveness info */
2608 spec
= ins_spec
[ins
->opcode
];
2609 DEBUG (print_ins (i
, ins
));
2610 if (spec
[MONO_INST_CLOB
] == 'c') {
2611 MonoCallInst
* call
= (MonoCallInst
*)ins
;
2614 if (spec
[MONO_INST_SRC1
]) {
2615 if (spec
[MONO_INST_SRC1
] == 'f')
2616 reginfo1
= reginfof
;
2619 reginfo1
[ins
->sreg1
].prev_use
= reginfo1
[ins
->sreg1
].last_use
;
2620 reginfo1
[ins
->sreg1
].last_use
= i
;
2624 if (spec
[MONO_INST_SRC2
]) {
2625 if (spec
[MONO_INST_SRC2
] == 'f')
2626 reginfo2
= reginfof
;
2629 reginfo2
[ins
->sreg2
].prev_use
= reginfo2
[ins
->sreg2
].last_use
;
2630 reginfo2
[ins
->sreg2
].last_use
= i
;
2634 if (spec
[MONO_INST_DEST
]) {
2635 if (spec
[MONO_INST_DEST
] == 'f')
2636 reginfod
= reginfof
;
2639 if (spec
[MONO_INST_DEST
] != 'b') /* it's not just a base register */
2640 reginfod
[ins
->dreg
].killed_in
= i
;
2641 reginfod
[ins
->dreg
].prev_use
= reginfod
[ins
->dreg
].last_use
;
2642 reginfod
[ins
->dreg
].last_use
= i
;
2643 if (reginfod
[ins
->dreg
].born_in
== 0 || reginfod
[ins
->dreg
].born_in
> i
)
2644 reginfod
[ins
->dreg
].born_in
= i
;
2645 if (spec
[MONO_INST_DEST
] == 'l') {
2646 /* result in eax:edx, the virtual register is allocated sequentially */
2647 reginfod
[ins
->dreg
+ 1].prev_use
= reginfod
[ins
->dreg
+ 1].last_use
;
2648 reginfod
[ins
->dreg
+ 1].last_use
= i
;
2649 if (reginfod
[ins
->dreg
+ 1].born_in
== 0 || reginfod
[ins
->dreg
+ 1].born_in
> i
)
2650 reginfod
[ins
->dreg
+ 1].born_in
= i
;
2655 reversed
= inst_list_prepend (cfg
->mempool
, reversed
, ins
);
2660 cur_iregs
= S390_CALLER_REGS
;
2661 cur_fregs
= S390_CALLER_FREGS
;
2663 DEBUG (print_regtrack (reginfo
, rs
->next_vireg
));
2664 DEBUG (print_regtrack (reginfof
, rs
->next_vfreg
));
2667 int prev_dreg
, prev_sreg1
, prev_sreg2
;
2670 spec
= ins_spec
[ins
->opcode
];
2671 DEBUG (g_print ("processing:"));
2672 DEBUG (print_ins (i
, ins
));
2673 /* make the register available for allocation: FIXME add fp reg */
2674 if (ins
->opcode
== OP_SETREG
|| ins
->opcode
== OP_SETREGIMM
) {
2675 cur_iregs
|= 1 << ins
->dreg
;
2676 DEBUG (g_print ("adding %d to cur_iregs\n", ins
->dreg
));
2677 } else if (ins
->opcode
== OP_SETFREG
) {
2678 cur_fregs
|= 1 << ins
->dreg
;
2679 DEBUG (g_print ("adding %d to cur_fregs\n", ins
->dreg
));
2680 } else if (spec
[MONO_INST_CLOB
] == 'c') {
2681 MonoCallInst
*cinst
= (MonoCallInst
*)ins
;
2682 DEBUG (g_print ("excluding regs 0x%x from cur_iregs (0x%x)\n",
2683 cinst
->used_iregs
, cur_iregs
));
2684 DEBUG (g_print ("excluding fpregs 0x%x from cur_fregs (0x%x)\n",
2685 cinst
->used_fregs
, cur_fregs
));
2686 cur_iregs
&= ~cinst
->used_iregs
;
2687 cur_fregs
&= ~cinst
->used_fregs
;
2688 DEBUG (g_print ("available cur_iregs: 0x%x\n", cur_iregs
));
2689 DEBUG (g_print ("available cur_fregs: 0x%x\n", cur_fregs
));
2690 /*------------------------------------------------------------*/
2691 /* registers used by the calling convention are excluded from */
2692 /* allocation: they will be selectively enabled when they are */
2693 /* assigned by the special SETREG opcodes. */
2694 /*------------------------------------------------------------*/
2696 dest_mask
= src1_mask
= src2_mask
= cur_iregs
;
2697 /*------------------------------------------------------*/
2698 /* update for use with FP regs... */
2699 /*------------------------------------------------------*/
2700 if (spec
[MONO_INST_DEST
] == 'f') {
2701 dest_mask
= cur_fregs
;
2702 if (ins
->dreg
>= MONO_MAX_FREGS
) {
2703 val
= rs
->fassign
[ins
->dreg
];
2704 prev_dreg
= ins
->dreg
;
2708 /* the register gets spilled after this inst */
2711 val
= mono_regstate_alloc_float (rs
, dest_mask
);
2713 val
= get_float_register_spilling (cfg
, tmp
, ins
, dest_mask
, ins
->dreg
);
2714 rs
->fassign
[ins
->dreg
] = val
;
2716 create_spilled_store_float (cfg
, spill
, val
, prev_dreg
, ins
);
2718 DEBUG (g_print ("\tassigned dreg %s to dest R%d\n",
2719 mono_arch_regname (val
), ins
->dreg
));
2720 rs
->fsymbolic
[val
] = prev_dreg
;
2722 if (spec
[MONO_INST_CLOB
] == 'c' && ins
->dreg
!= s390_f0
) {
2723 /* this instruction only outputs to s390_f0, need to copy */
2724 create_copy_ins_float (cfg
, ins
->dreg
, s390_f0
, ins
);
2729 if (freg_is_freeable (ins
->dreg
) && prev_dreg
>= 0 && (reginfof
[prev_dreg
].born_in
>= i
|| !(cur_fregs
& (1 << ins
->dreg
)))) {
2730 DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins
->dreg
), prev_dreg
, reginfo
[prev_dreg
].born_in
));
2731 mono_regstate_free_float (rs
, ins
->dreg
);
2733 } else if (ins
->dreg
>= MONO_MAX_IREGS
) {
2734 val
= rs
->iassign
[ins
->dreg
];
2735 prev_dreg
= ins
->dreg
;
2739 /* the register gets spilled after this inst */
2742 val
= mono_regstate_alloc_int (rs
, dest_mask
);
2744 val
= get_register_spilling (cfg
, tmp
, ins
, dest_mask
, ins
->dreg
);
2745 rs
->iassign
[ins
->dreg
] = val
;
2747 create_spilled_store (cfg
, spill
, val
, prev_dreg
, ins
);
2749 DEBUG (g_print ("\tassigned dreg %s to dest R%d (prev: R%d)\n",
2750 mono_arch_regname (val
), ins
->dreg
, prev_dreg
));
2751 rs
->isymbolic
[val
] = prev_dreg
;
2753 if (spec
[MONO_INST_DEST
] == 'l') {
2754 int hreg
= prev_dreg
+ 1;
2755 val
= rs
->iassign
[hreg
];
2759 /* the register gets spilled after this inst */
2762 val
= mono_regstate_alloc_int (rs
, dest_mask
);
2764 val
= get_register_spilling (cfg
, tmp
, ins
, dest_mask
, hreg
);
2765 rs
->iassign
[hreg
] = val
;
2767 create_spilled_store (cfg
, spill
, val
, hreg
, ins
);
2769 DEBUG (g_print ("\tassigned hreg %s to dest R%d\n", mono_arch_regname (val
), hreg
));
2770 rs
->isymbolic
[val
] = hreg
;
2771 /* FIXME:? ins->dreg = val; */
2772 if (ins
->dreg
== s390_r3
) {
2774 create_copy_ins (cfg
, val
, s390_r2
, ins
);
2775 } else if (ins
->dreg
== s390_r2
) {
2776 if (val
== s390_r3
) {
2778 create_copy_ins (cfg
, s390_r3
, s390_r0
, ins
);
2779 create_copy_ins (cfg
, s390_r2
, s390_r3
, ins
);
2780 create_copy_ins (cfg
, s390_r0
, s390_r2
, ins
);
2782 /* two forced copies */
2783 create_copy_ins (cfg
, ins
->dreg
, s390_r3
, ins
);
2784 create_copy_ins (cfg
, val
, s390_r2
, ins
);
2787 if (val
== s390_r2
) {
2788 create_copy_ins (cfg
, ins
->dreg
, s390_r2
, ins
);
2790 /* two forced copies */
2791 create_copy_ins (cfg
, val
, s390_r2
, ins
);
2792 create_copy_ins (cfg
, ins
->dreg
, s390_r3
, ins
);
2795 if (reg_is_freeable (val
) && hreg
>= 0 && (reginfo
[hreg
].born_in
>= i
&& !(cur_iregs
& (1 << val
)))) {
2796 DEBUG (g_print ("\tfreeable %s (R%d)\n", mono_arch_regname (val
), hreg
));
2797 mono_regstate_free_int (rs
, val
);
2799 } else if (spec
[MONO_INST_DEST
] == 'a' && ins
->dreg
!= s390_r2
&& spec
[MONO_INST_CLOB
] != 'd') {
2800 /* this instruction only outputs to s390_r2, need to copy */
2801 create_copy_ins (cfg
, ins
->dreg
, s390_r2
, ins
);
2806 if (spec
[MONO_INST_DEST
] == 'f' &&
2807 freg_is_freeable (ins
->dreg
) &&
2808 prev_dreg
>= 0 && (reginfof
[prev_dreg
].born_in
>= i
)) {
2809 DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins
->dreg
), prev_dreg
, reginfo
[prev_dreg
].born_in
));
2810 mono_regstate_free_float (rs
, ins
->dreg
);
2811 } else if (spec
[MONO_INST_DEST
] != 'f' &&
2812 reg_is_freeable (ins
->dreg
) &&
2813 prev_dreg
>= 0 && (reginfo
[prev_dreg
].born_in
>= i
)) {
2814 DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins
->dreg
), prev_dreg
, reginfo
[prev_dreg
].born_in
));
2815 mono_regstate_free_int (rs
, ins
->dreg
);
2817 if (spec
[MONO_INST_SRC1
] == 'f') {
2818 src1_mask
= cur_fregs
;
2819 if (ins
->sreg1
>= MONO_MAX_FREGS
) {
2820 val
= rs
->fassign
[ins
->sreg1
];
2821 prev_sreg1
= ins
->sreg1
;
2825 /* the register gets spilled after this inst */
2828 //g_assert (val == -1); /* source cannot be spilled */
2829 val
= mono_regstate_alloc_float (rs
, src1_mask
);
2831 val
= get_float_register_spilling (cfg
, tmp
, ins
, src1_mask
, ins
->sreg1
);
2832 rs
->fassign
[ins
->sreg1
] = val
;
2833 DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", mono_arch_regname (val
), ins
->sreg1
));
2835 MonoInst
*store
= create_spilled_store_float (cfg
, spill
, val
, prev_sreg1
, NULL
);
2836 insert_before_ins (ins
, tmp
, store
);
2839 rs
->fsymbolic
[val
] = prev_sreg1
;
2844 } else if (ins
->sreg1
>= MONO_MAX_IREGS
) {
2845 val
= rs
->iassign
[ins
->sreg1
];
2846 prev_sreg1
= ins
->sreg1
;
2850 /* the register gets spilled after this inst */
2853 val
= mono_regstate_alloc_int (rs
, src1_mask
);
2855 val
= get_register_spilling (cfg
, tmp
, ins
,
2858 rs
->iassign
[ins
->sreg1
] = val
;
2859 DEBUG (g_print ("\tassigned sreg1 %s to R%d\n",
2860 mono_arch_regname (val
), ins
->sreg1
));
2863 store
= create_spilled_store (cfg
, spill
, val
,
2865 insert_before_ins (ins
, tmp
, store
);
2868 rs
->isymbolic
[val
] = prev_sreg1
;
2873 /*----------------------------------------------*/
2874 /* handle clobbering of sreg1 */
2875 /*----------------------------------------------*/
2876 if ((spec
[MONO_INST_CLOB
] == '1' ||
2877 spec
[MONO_INST_CLOB
] == 's') &&
2878 ins
->dreg
!= ins
->sreg1
) {
2880 copy
= create_copy_ins (cfg
, ins
->dreg
, ins
->sreg1
, NULL
);
2881 DEBUG (g_print ("\tneed to copy sreg1 %s to dreg %s\n",
2882 mono_arch_regname (ins
->sreg1
),
2883 mono_arch_regname (ins
->dreg
)));
2884 if (ins
->sreg2
== -1 || spec
[MONO_INST_CLOB
] == 's') {
2885 /* note: the copy is inserted before the current instruction! */
2886 insert_before_ins (ins
, tmp
, copy
);
2887 /* we set sreg1 to dest as well */
2888 prev_sreg1
= ins
->sreg1
= ins
->dreg
;
2890 /* inserted after the operation */
2891 copy
->next
= ins
->next
;
2896 if (spec
[MONO_INST_SRC2
] == 'f') {
2897 src2_mask
= cur_fregs
;
2898 if (ins
->sreg2
>= MONO_MAX_FREGS
) {
2899 val
= rs
->fassign
[ins
->sreg2
];
2900 prev_sreg2
= ins
->sreg2
;
2904 /* the register gets spilled after this inst */
2907 val
= mono_regstate_alloc_float (rs
, src2_mask
);
2909 val
= get_float_register_spilling (cfg
, tmp
, ins
, src2_mask
, ins
->sreg2
);
2910 rs
->fassign
[ins
->sreg2
] = val
;
2911 DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val
), ins
->sreg2
));
2913 create_spilled_store_float (cfg
, spill
, val
, prev_sreg2
, ins
);
2915 rs
->fsymbolic
[val
] = prev_sreg2
;
2920 } else if (ins
->sreg2
>= MONO_MAX_IREGS
) {
2921 val
= rs
->iassign
[ins
->sreg2
];
2922 prev_sreg2
= ins
->sreg2
;
2926 /* the register gets spilled after this inst */
2929 val
= mono_regstate_alloc_int (rs
, src2_mask
);
2931 val
= get_register_spilling (cfg
, tmp
, ins
, src2_mask
, ins
->sreg2
);
2932 rs
->iassign
[ins
->sreg2
] = val
;
2933 DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val
), ins
->sreg2
));
2935 create_spilled_store (cfg
, spill
, val
, prev_sreg2
, ins
);
2937 rs
->isymbolic
[val
] = prev_sreg2
;
2943 if (spec
[MONO_INST_CLOB
] == 'c') {
2945 guint32 clob_mask
= S390_CALLER_REGS
;
2946 for (j
= 0; j
< MONO_MAX_IREGS
; ++j
) {
2948 if ((clob_mask
& s
) && !(rs
->ifree_mask
& s
) && j
!= ins
->sreg1
) {
2949 //g_warning ("register %s busy at call site\n", mono_arch_regname (j));
2953 /*if (reg_is_freeable (ins->sreg1) && prev_sreg1 >= 0 && reginfo [prev_sreg1].born_in >= i) {
2954 DEBUG (g_print ("freeable %s\n", mono_arch_regname (ins->sreg1)));
2955 mono_regstate_free_int (rs, ins->sreg1);
2957 if (reg_is_freeable (ins->sreg2) && prev_sreg2 >= 0 && reginfo [prev_sreg2].born_in >= i) {
2958 DEBUG (g_print ("freeable %s\n", mono_arch_regname (ins->sreg2)));
2959 mono_regstate_free_int (rs, ins->sreg2);
2962 //DEBUG (print_ins (i, ins));
2967 /*========================= End of Function ========================*/
2969 /*------------------------------------------------------------------*/
2971 /* Name - emit_float_to_int */
2973 /* Function - Create instructions which will convert a floating */
2974 /* point value to integer. */
2976 /*------------------------------------------------------------------*/
2979 emit_float_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
2981 /* sreg is a float, dreg is an integer reg. */
2983 s390_cfdbr (code
, dreg
, 5, sreg
);
2986 s390_lhi (code
, s390_r0
, 0);
2987 s390_lhi (code
, s390_r13
, 0xff);
2988 s390_ltr (code
, dreg
, dreg
);
2990 s390_lhi (code
, s390_r0
, 0x80);
2991 s390_nr (code
, dreg
, s390_r13
);
2992 s390_or (code
, dreg
, s390_r0
);
2996 s390_basr (code
, s390_r13
, 0);
2998 s390_double (code
, 0x41e0000000000000);
2999 s390_double (code
, 0x41f0000000000000);
3000 s390_ldr (code
, s390_f15
, sreg
);
3001 s390_cdb (code
, s390_f15
, 0, s390_r13
, 0);
3003 s390_sdb (code
, s390_f15
, 0, s390_r13
, 8);
3004 s390_cfdbr (code
, dreg
, 7, s390_f15
);
3006 s390_cfdbr (code
, dreg
, 5, sreg
);
3009 s390_lhi (code
, s390_r0
, 0xff);
3010 s390_nr (code
, dreg
, s390_r0
);
3013 s390_lhi (code
, s390_r0
, -1);
3014 s390_srl (code
, s390_r0
, 0, 16);
3015 s390_nr (code
, dreg
, s390_r0
);
3022 /*========================= End of Function ========================*/
3024 /*------------------------------------------------------------------*/
3026 /* Name - mono_emit_stack_alloc */
3030 /*------------------------------------------------------------------*/
3032 static unsigned char*
3033 mono_emit_stack_alloc (guchar
*code
, MonoInst
* tree
)
3038 /*========================= End of Function ========================*/
3040 /*------------------------------------------------------------------*/
3042 /* Name - mono_arch_output_basic_block */
3044 /* Function - Perform the "real" work of emitting instructions */
3045 /* that will do the work of in the basic block. */
3047 /*------------------------------------------------------------------*/
3050 mono_arch_output_basic_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
3055 guint8
*code
= cfg
->native_code
+ cfg
->code_len
;
3056 MonoInst
*last_ins
= NULL
;
3057 guint last_offset
= 0;
3061 if (cfg
->opt
& MONO_OPT_PEEPHOLE
)
3062 peephole_pass (cfg
, bb
);
3064 /* we don't align basic blocks of loops on s390 */
3066 if (cfg
->verbose_level
> 2)
3067 g_print ("Basic block %d starting at offset 0x%x\n", bb
->block_num
, bb
->native_offset
);
3069 cpos
= bb
->max_offset
;
3071 if (cfg
->prof_options
& MONO_PROFILE_COVERAGE
) {
3072 //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
3073 //g_assert (!mono_compile_aot);
3076 // cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
3077 /* this is not thread save, but good enough */
3078 /* fixme: howto handle overflows? */
3079 //x86_inc_mem (code, &cov->data [bb->dfn].count);
3084 offset
= code
- cfg
->native_code
;
3086 max_len
= ((guint8
*)ins_spec
[ins
->opcode
])[MONO_INST_LEN
];
3088 if (offset
> (cfg
->code_size
- max_len
- 16)) {
3089 cfg
->code_size
*= 2;
3090 cfg
->native_code
= g_realloc (cfg
->native_code
, cfg
->code_size
);
3091 code
= cfg
->native_code
+ offset
;
3094 switch (ins
->opcode
) {
3095 case OP_STOREI1_MEMBASE_IMM
: {
3096 s390_lhi (code
, s390_r14
, ins
->inst_imm
);
3097 if (s390_is_uimm12(ins
->inst_offset
))
3098 s390_stc (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3100 s390_basr (code
, s390_r13
, 0);
3102 s390_word (code
, ins
->inst_offset
);
3103 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3104 s390_stc (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3108 case OP_STOREI2_MEMBASE_IMM
: {
3109 s390_lhi (code
, s390_r14
, ins
->inst_imm
);
3110 if (s390_is_uimm12(ins
->inst_offset
)) {
3111 s390_sth (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3113 s390_basr (code
, s390_r14
, 0);
3115 s390_word (code
, ins
->inst_offset
);
3116 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3117 s390_sth (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3121 case OP_STORE_MEMBASE_IMM
:
3122 case OP_STOREI4_MEMBASE_IMM
: {
3123 if (s390_is_imm16(ins
->inst_imm
)) {
3124 s390_lhi (code
, s390_r14
, ins
->inst_imm
);
3126 s390_basr (code
, s390_r13
, 0);
3128 s390_word (code
, ins
->inst_imm
);
3129 s390_l (code
, s390_r14
, 0, s390_r13
, 4);
3131 if (s390_is_uimm12(ins
->inst_offset
)) {
3132 s390_st (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3134 s390_basr (code
, s390_r13
, 0);
3136 s390_word (code
, ins
->inst_offset
);
3137 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3138 s390_st (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3142 case OP_STOREI1_MEMBASE_REG
: {
3143 if (s390_is_uimm12(ins
->inst_offset
)) {
3144 s390_stc (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3146 s390_basr (code
, s390_r13
, 0);
3148 s390_word (code
, ins
->inst_offset
);
3149 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3150 s390_stc (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3154 case OP_STOREI2_MEMBASE_REG
: {
3155 if (s390_is_uimm12(ins
->inst_offset
)) {
3156 s390_sth (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3158 s390_basr (code
, s390_r13
, 0);
3160 s390_word (code
, ins
->inst_offset
);
3161 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3162 s390_sth (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3166 case OP_STORE_MEMBASE_REG
:
3167 case OP_STOREI4_MEMBASE_REG
: {
3168 if (s390_is_uimm12(ins
->inst_offset
)) {
3169 s390_st (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3171 s390_basr (code
, s390_r13
, 0);
3173 s390_word (code
, ins
->inst_offset
);
3174 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3175 s390_st (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3181 case CEE_LDIND_U4
: {
3182 s390_basr (code
, s390_r13
, 0);
3184 s390_word (code
, ins
->inst_p0
);
3185 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3186 s390_l (code
, ins
->dreg
, 0, s390_r13
, 0);
3190 g_assert_not_reached ();
3192 case OP_LOAD_MEMBASE
:
3193 case OP_LOADI4_MEMBASE
:
3194 case OP_LOADU4_MEMBASE
: {
3195 if (s390_is_uimm12(ins
->inst_offset
))
3196 s390_l (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3198 if (s390_is_imm16(ins
->inst_offset
)) {
3199 s390_lhi (code
, s390_r13
, ins
->inst_offset
);
3200 s390_l (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
3202 s390_basr (code
, s390_r13
, 0);
3204 s390_word (code
, ins
->inst_offset
);
3205 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3206 s390_l (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
3211 case OP_LOADU1_MEMBASE
: {
3212 s390_lhi (code
, s390_r0
, 0);
3213 if (s390_is_uimm12(ins
->inst_offset
))
3214 s390_ic (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3216 s390_basr (code
, s390_r13
, 0);
3218 s390_word (code
, ins
->inst_offset
);
3219 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3220 s390_ic (code
, s390_r0
, s390_r13
, ins
->inst_basereg
, 0);
3222 s390_lr (code
, ins
->dreg
, s390_r0
);
3225 case OP_LOADI1_MEMBASE
: {
3226 s390_lhi (code
, s390_r0
, 0);
3227 if (s390_is_uimm12(ins
->inst_offset
))
3228 s390_ic (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3230 s390_basr (code
, s390_r13
, 0);
3232 s390_word (code
, ins
->inst_offset
);
3233 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3234 s390_ic (code
, s390_r0
, s390_r13
, ins
->inst_basereg
, 0);
3236 s390_lhi (code
, s390_r13
, 0x80);
3237 s390_nr (code
, s390_r13
, s390_r0
);
3239 s390_lhi (code
, s390_r13
, 0xff00);
3240 s390_or (code
, s390_r0
, s390_r13
);
3241 s390_lr (code
, ins
->dreg
, s390_r0
);
3244 case OP_LOADU2_MEMBASE
: {
3245 s390_lhi (code
, s390_r0
, 0);
3246 if (s390_is_uimm12(ins
->inst_offset
))
3247 s390_icm (code
, s390_r0
, 3, ins
->inst_basereg
, ins
->inst_offset
);
3249 s390_basr (code
, s390_r13
, 0);
3251 s390_word (code
, ins
->inst_offset
);
3252 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3253 s390_ar (code
, s390_r13
, ins
->inst_basereg
);
3254 s390_icm (code
, s390_r0
, 3, s390_r13
, 0);
3256 s390_lr (code
, ins
->dreg
, s390_r0
);
3259 case OP_LOADI2_MEMBASE
: {
3260 s390_lhi (code
, s390_r0
, 0);
3261 if (s390_is_uimm12(ins
->inst_offset
))
3262 s390_lh (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3264 s390_basr (code
, s390_r13
, 0);
3266 s390_word (code
, ins
->inst_offset
);
3267 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3268 s390_lh (code
, s390_r0
, s390_r13
, ins
->inst_basereg
, 0);
3270 s390_lr (code
, ins
->dreg
, s390_r0
);
3274 s390_lhi (code
, s390_r0
, 0x80);
3275 if (ins
->dreg
!= ins
->sreg1
) {
3276 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3278 s390_nr (code
, s390_r0
, ins
->sreg1
);
3280 s390_lhi (code
, s390_r13
, -1);
3281 s390_sll (code
, s390_r13
, 0, 8);
3282 s390_or (code
, ins
->dreg
, s390_r13
);
3286 s390_lhi (code
, s390_r0
, 0x80);
3287 s390_sll (code
, s390_r0
, 0, 8);
3288 if (ins
->dreg
!= ins
->sreg1
) {
3289 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3291 s390_nr (code
, s390_r0
, ins
->sreg1
);
3293 s390_lhi (code
, s390_r13
, -1);
3294 s390_sll (code
, s390_r13
, 0, 16);
3295 s390_or (code
, ins
->dreg
, s390_r13
);
3299 s390_lhi (code
, s390_r0
, 0xff);
3300 if (ins
->dreg
!= ins
->sreg1
) {
3301 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3303 s390_nr (code
, ins
->dreg
, s390_r0
);
3307 s390_lhi (code
, s390_r0
, -1);
3308 s390_sll (code
, s390_r0
, 0, 16);
3309 s390_srl (code
, s390_r0
, 0, 16);
3310 if (ins
->dreg
!= ins
->sreg1
) {
3311 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3313 s390_nr (code
, ins
->dreg
, s390_r0
);
3318 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3319 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3320 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3321 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3322 ((ins
->next
->opcode
== OP_CLT_UN
) ||
3323 (ins
->next
->opcode
== OP_CGT_UN
)))
3324 s390_clr (code
, ins
->sreg1
, ins
->sreg2
);
3326 s390_cr (code
, ins
->sreg1
, ins
->sreg2
);
3329 case OP_COMPARE_IMM
: {
3330 if (s390_is_imm16 (ins
->inst_imm
)) {
3331 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3333 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3334 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3335 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3336 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3337 ((ins
->next
->opcode
== OP_CLT_UN
) ||
3338 (ins
->next
->opcode
== OP_CGT_UN
)))
3339 s390_clr (code
, ins
->sreg1
, s390_r0
);
3341 s390_cr (code
, ins
->sreg1
, s390_r0
);
3344 s390_basr (code
, s390_r13
, 0);
3346 s390_word (code
, ins
->inst_imm
);
3348 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3349 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3350 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3351 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3352 ((ins
->next
->opcode
== OP_CLT_UN
) &&
3353 (ins
->next
->opcode
== OP_CGT_UN
)))
3354 s390_cl (code
, ins
->sreg1
, 0, s390_r13
, 4);
3356 s390_c (code
, ins
->sreg1
, 0, s390_r13
, 4);
3360 case OP_X86_TEST_NULL
: {
3361 s390_ltr (code
, ins
->sreg1
, ins
->sreg1
);
3369 if (ins
->dreg
!= ins
->sreg1
) {
3370 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3372 s390_alr (code
, ins
->dreg
, ins
->sreg2
);
3376 if (ins
->dreg
!= ins
->sreg1
) {
3377 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3379 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
3383 if (ins
->dreg
!= ins
->sreg1
) {
3384 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3386 s390_alcr (code
, ins
->dreg
, ins
->sreg2
);
3391 (ins
->next
->opcode
== OP_ADC_IMM
)) {
3392 s390_basr (code
, s390_r13
, 0);
3394 s390_word (code
, ins
->inst_imm
);
3395 if (ins
->dreg
!= ins
->sreg1
) {
3396 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3398 s390_al (code
, ins
->dreg
, 0, s390_r13
, 4);
3400 if (s390_is_imm16 (ins
->inst_imm
)) {
3401 if (ins
->dreg
!= ins
->sreg1
) {
3402 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3404 s390_ahi (code
, ins
->dreg
, ins
->inst_imm
);
3406 s390_basr (code
, s390_r13
, 0);
3408 s390_word (code
, ins
->inst_imm
);
3409 if (ins
->dreg
!= ins
->sreg1
) {
3410 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3412 s390_a (code
, ins
->dreg
, 0, s390_r13
, 4);
3418 if (s390_is_imm16 (ins
->inst_imm
)) {
3419 if (ins
->dreg
!= ins
->sreg1
) {
3420 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3422 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3423 s390_alcr (code
, ins
->dreg
, s390_r0
);
3425 s390_basr (code
, s390_r13
, 0);
3427 s390_word (code
, ins
->inst_imm
);
3428 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3429 s390_alcr (code
, ins
->dreg
, s390_r13
);
3434 if (ins
->dreg
!= ins
->sreg1
) {
3435 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3437 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
3438 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3441 case CEE_ADD_OVF_UN
: {
3442 if (ins
->dreg
!= ins
->sreg1
) {
3443 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3445 s390_alr (code
, ins
->dreg
, ins
->sreg2
);
3446 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3449 case OP_ADD_OVF_CARRY
: {
3450 if (ins
->dreg
!= ins
->sreg1
) {
3451 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3453 s390_lhi (code
, s390_r0
, 0);
3454 s390_lr (code
, s390_r1
, s390_r0
);
3455 s390_alcr (code
, s390_r0
, s390_r1
);
3456 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
3457 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3458 s390_ar (code
, ins
->dreg
, s390_r0
);
3459 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3462 case OP_ADD_OVF_UN_CARRY
: {
3463 if (ins
->dreg
!= ins
->sreg1
) {
3464 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3466 s390_alcr (code
, ins
->dreg
, ins
->sreg2
);
3467 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3471 if (ins
->dreg
!= ins
->sreg1
) {
3472 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3474 s390_slr (code
, ins
->dreg
, ins
->sreg2
);
3478 if (ins
->dreg
!= ins
->sreg1
) {
3479 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3481 s390_sr (code
, ins
->dreg
, ins
->sreg2
);
3485 if (ins
->dreg
!= ins
->sreg1
) {
3486 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3488 s390_slbr (code
, ins
->dreg
, ins
->sreg2
);
3492 if (s390_is_imm16 (-ins
->inst_imm
)) {
3493 if (ins
->dreg
!= ins
->sreg1
) {
3494 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3496 s390_ahi (code
, ins
->dreg
, -ins
->inst_imm
);
3498 s390_basr (code
, s390_r13
, 0);
3500 s390_word (code
, ins
->inst_imm
);
3501 if (ins
->dreg
!= ins
->sreg1
) {
3502 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3504 s390_s (code
, ins
->dreg
, 0, s390_r13
, 4);
3509 s390_basr (code
, s390_r13
, 0);
3511 s390_word (code
, ins
->inst_imm
);
3512 s390_sl (code
, ins
->dreg
, 0, s390_r13
, 4);
3516 if (ins
->dreg
!= ins
->sreg1
) {
3517 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3519 s390_sr (code
, ins
->dreg
, ins
->sreg2
);
3520 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3523 case CEE_SUB_OVF_UN
: {
3524 if (ins
->dreg
!= ins
->sreg1
) {
3525 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3527 s390_slr (code
, ins
->dreg
, ins
->sreg2
);
3528 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3531 case OP_SUB_OVF_CARRY
: {
3532 if (ins
->dreg
!= ins
->sreg1
) {
3533 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3535 s390_lhi (code
, s390_r0
, 0);
3536 s390_lr (code
, s390_r1
, s390_r0
);
3537 s390_slbr (code
, s390_r0
, s390_r1
);
3538 s390_sr (code
, ins
->dreg
, ins
->sreg2
);
3539 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3540 s390_ar (code
, ins
->dreg
, s390_r0
);
3541 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3544 case OP_SUB_OVF_UN_CARRY
: {
3545 if (ins
->dreg
!= ins
->sreg1
) {
3546 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3548 s390_slbr (code
, ins
->dreg
, ins
->sreg2
);
3549 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3553 if (ins
->sreg1
== ins
->dreg
) {
3554 s390_nr (code
, ins
->dreg
, ins
->sreg2
);
3557 if (ins
->sreg2
== ins
->dreg
) {
3558 s390_nr (code
, ins
->dreg
, ins
->sreg1
);
3561 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3562 s390_nr (code
, ins
->dreg
, ins
->sreg2
);
3568 if (s390_is_imm16 (ins
->inst_imm
)) {
3569 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3570 if (ins
->dreg
!= ins
->sreg1
) {
3571 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3573 s390_nr (code
, ins
->dreg
, s390_r0
);
3575 s390_basr (code
, s390_r13
, 0);
3577 s390_word (code
, ins
->inst_imm
);
3578 if (ins
->dreg
!= ins
->sreg1
) {
3579 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3581 s390_n (code
, ins
->dreg
, 0, s390_r13
, 4);
3586 s390_lr (code
, s390_r0
, ins
->sreg1
);
3587 s390_srda (code
, s390_r0
, 0, 32);
3588 s390_dr (code
, s390_r0
, ins
->sreg2
);
3589 s390_lr (code
, ins
->dreg
, s390_r1
);
3593 s390_lr (code
, s390_r0
, ins
->sreg1
);
3594 s390_srdl (code
, s390_r0
, 0, 32);
3595 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3596 s390_lr (code
, ins
->dreg
, s390_r1
);
3600 if (s390_is_imm16 (ins
->inst_imm
)) {
3601 s390_lhi (code
, s390_r13
, ins
->inst_imm
);
3602 s390_lr (code
, s390_r0
, ins
->sreg1
);
3604 s390_basr (code
, s390_r13
, 0);
3606 s390_word (code
, ins
->inst_imm
);
3607 s390_lr (code
, s390_r0
, ins
->sreg1
);
3608 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3610 s390_srda (code
, s390_r0
, 0, 32);
3611 s390_dr (code
, s390_r0
, ins
->sreg2
);
3612 s390_lr (code
, ins
->dreg
, s390_r1
);
3616 s390_lr (code
, s390_r0
, ins
->sreg1
);
3617 s390_srda (code
, s390_r0
, 0, 32);
3618 s390_dr (code
, s390_r0
, ins
->sreg2
);
3619 s390_lr (code
, ins
->dreg
, s390_r0
);
3622 s390_lr (code
, s390_r0
, ins
->sreg1
);
3623 s390_srdl (code
, s390_r0
, 0, 32);
3624 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3625 s390_lr (code
, ins
->dreg
, s390_r0
);
3629 if (s390_is_imm16 (ins
->inst_imm
)) {
3630 s390_lhi (code
, s390_r13
, ins
->inst_imm
);
3631 s390_lr (code
, s390_r0
, ins
->sreg1
);
3633 s390_basr (code
, s390_r13
, 0);
3635 s390_word (code
, ins
->inst_imm
);
3636 s390_lr (code
, s390_r0
, ins
->sreg1
);
3637 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3639 s390_srda (code
, s390_r0
, 0, 32);
3640 s390_dr (code
, s390_r0
, ins
->sreg2
);
3641 s390_lr (code
, ins
->dreg
, s390_r0
);
3645 if (ins
->sreg1
== ins
->dreg
) {
3646 s390_or (code
, ins
->dreg
, ins
->sreg2
);
3649 if (ins
->sreg2
== ins
->dreg
) {
3650 s390_or (code
, ins
->dreg
, ins
->sreg1
);
3653 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3654 s390_or (code
, ins
->dreg
, ins
->sreg2
);
3660 if (s390_is_imm16 (ins
->inst_imm
)) {
3661 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3662 if (ins
->dreg
!= ins
->sreg1
) {
3663 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3665 s390_or (code
, ins
->dreg
, s390_r0
);
3667 s390_bras (code
, s390_r13
, 4);
3668 s390_word (code
, ins
->inst_imm
);
3669 if (ins
->dreg
!= ins
->sreg1
) {
3670 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3672 s390_o (code
, ins
->dreg
, 0, s390_r13
, 0);
3677 if (ins
->sreg1
== ins
->dreg
) {
3678 s390_xr (code
, ins
->dreg
, ins
->sreg2
);
3681 if (ins
->sreg2
== ins
->dreg
) {
3682 s390_xr (code
, ins
->dreg
, ins
->sreg1
);
3685 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3686 s390_xr (code
, ins
->dreg
, ins
->sreg2
);
3692 if (s390_is_imm16 (ins
->inst_imm
)) {
3693 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3694 if (ins
->dreg
!= ins
->sreg1
) {
3695 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3697 s390_xr (code
, ins
->dreg
, s390_r0
);
3699 s390_basr (code
, s390_r13
, 0);
3701 s390_word (code
, ins
->inst_imm
);
3702 if (ins
->dreg
!= ins
->sreg1
) {
3703 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3705 s390_x (code
, ins
->dreg
, 0, s390_r13
, 4);
3710 if (ins
->sreg1
!= ins
->dreg
) {
3711 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3713 s390_sll (code
, ins
->dreg
, ins
->sreg2
, 0);
3717 if (ins
->sreg1
!= ins
->dreg
) {
3718 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3720 s390_sll (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3724 if (ins
->sreg1
!= ins
->dreg
) {
3725 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3727 s390_sra (code
, ins
->dreg
, ins
->sreg2
, 0);
3731 if (ins
->sreg1
!= ins
->dreg
) {
3732 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3734 s390_sra (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3737 case OP_SHR_UN_IMM
: {
3738 if (ins
->sreg1
!= ins
->dreg
) {
3739 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3741 s390_srl (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3745 if (ins
->sreg1
!= ins
->dreg
) {
3746 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3748 s390_srl (code
, ins
->dreg
, ins
->sreg2
, 0);
3752 if (ins
->sreg1
!= ins
->dreg
) {
3753 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3755 s390_lhi (code
, s390_r0
, -1);
3756 s390_xr (code
, ins
->dreg
, s390_r0
);
3760 s390_lcr (code
, ins
->dreg
, ins
->sreg1
);
3764 if (ins
->sreg1
== ins
->dreg
) {
3765 s390_msr (code
, ins
->dreg
, ins
->sreg2
);
3768 if (ins
->sreg2
== ins
->dreg
) {
3769 s390_msr (code
, ins
->dreg
, ins
->sreg1
);
3772 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3773 s390_msr (code
, ins
->dreg
, ins
->sreg2
);
3779 if (s390_is_imm16 (ins
->inst_imm
)) {
3780 s390_lhi (code
, s390_r13
, ins
->inst_imm
);
3782 s390_basr (code
, s390_r13
, 0);
3784 s390_word (code
, ins
->inst_imm
);
3785 if (ins
->dreg
!= ins
->sreg1
) {
3786 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3788 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3790 s390_msr (code
, ins
->dreg
, s390_r13
);
3795 s390_ltr (code
, s390_r1
, ins
->sreg1
);
3796 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3797 s390_ltr (code
, s390_r0
, ins
->sreg2
);
3799 s390_lhi (code
, s390_r1
, 0);
3800 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3801 s390_xr (code
, s390_r0
, s390_r1
);
3802 s390_msr (code
, s390_r1
, ins
->sreg2
);
3803 s390_xr (code
, s390_r0
, s390_r1
);
3804 s390_srl (code
, s390_r0
, 0, 31);
3805 s390_ltr (code
, s390_r0
, s390_r0
);
3806 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3807 PTRSLOT (code
, o
[0]);
3808 PTRSLOT (code
, o
[1]);
3809 s390_lr (code
, ins
->dreg
, s390_r1
);
3812 case CEE_MUL_OVF_UN
: {
3813 s390_lhi (code
, s390_r0
, 0);
3814 s390_lr (code
, s390_r1
, ins
->sreg1
);
3815 s390_mlr (code
, s390_r0
, ins
->sreg2
);
3816 s390_ltr (code
, s390_r0
, s390_r0
);
3817 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3818 s390_lr (code
, ins
->dreg
, s390_r1
);
3822 s390_l (code
, s390_r0
, 0, ins
->sreg1
, 4);
3823 s390_lr (code
, s390_r14
, s390_r0
);
3824 s390_srda (code
, s390_r0
, 0, 32);
3825 s390_m (code
, s390_r0
, 0, ins
->sreg2
, 4);
3826 s390_srl (code
, s390_r14
, 0, 31);
3827 s390_a (code
, s390_r14
, 0, ins
->sreg1
, 0);
3828 s390_l (code
, s390_r13
, 0, ins
->sreg2
, 0);
3829 s390_srl (code
, s390_r13
, 0, 31);
3830 s390_ms (code
, s390_r13
, 0, ins
->sreg1
, 4);
3831 s390_ar (code
, s390_r14
, s390_r13
);
3832 s390_st (code
, s390_r14
, 0, ins
->dreg
, 0);
3833 s390_st (code
, s390_r1
, 0, ins
->dreg
, 4);
3837 case OP_SETREGIMM
: {
3838 if (s390_is_imm16(ins
->inst_c0
)) {
3839 s390_lhi (code
, ins
->dreg
, ins
->inst_c0
);
3841 s390_basr (code
, s390_r13
, 0);
3843 s390_word (code
, ins
->inst_c0
);
3844 s390_l (code
, ins
->dreg
, 0, s390_r13
, 4);
3849 s390_basr (code
, s390_r13
, 0);
3851 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3852 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
3853 s390_word (code
, 0);
3854 s390_l (code
,ins
->dreg
, 0, s390_r13
, 4);
3861 if (ins
->dreg
!= ins
->sreg1
) {
3862 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3867 int saved
= ins
->sreg1
;
3868 if (ins
->sreg1
== s390_r2
) {
3869 s390_lr (code
, s390_r0
, ins
->sreg1
);
3872 if (ins
->sreg2
!= s390_r2
)
3873 s390_lr (code
, s390_r2
, ins
->sreg2
);
3874 if (saved
!= s390_r3
)
3875 s390_lr (code
, s390_r3
, saved
);
3880 if (ins
->dreg
!= ins
->sreg1
) {
3881 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
3885 case OP_S390_SETF4RET
: {
3886 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
3889 case OP_FCONV_TO_R4
: {
3891 (ins
->next
->opcode
!= OP_STORER4_MEMBASE_REG
))
3892 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
3896 if (cfg
->method
->save_lmf
)
3897 code
= restoreLMF(cfg
, code
);
3899 code
= backUpStackPtr(cfg
, code
);
3900 s390_l (code
, s390_r14
, 0, STK_BASE
, S390_RET_ADDR_OFFSET
);
3901 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3902 MONO_PATCH_INFO_METHOD_JUMP
,
3904 s390_jcl (code
, S390_CC_UN
, 0);
3907 case OP_CHECK_THIS
: {
3908 /* ensure ins->sreg1 is not NULL */
3909 s390_icm (code
, s390_r0
, 15, ins
->sreg1
, 0);
3913 call
= (MonoCallInst
*)ins
;
3914 if (ins
->flags
& MONO_INST_HAS_METHOD
)
3915 mono_add_patch_info (cfg
, offset
, MONO_PATCH_INFO_METHOD
,
3918 mono_add_patch_info (cfg
, offset
, MONO_PATCH_INFO_ABS
,
3920 s390_brasl (code
, s390_r14
, 0);
3921 if (call
->signature
->ret
->type
== MONO_TYPE_R4
)
3922 s390_ldebr (code
, s390_f0
, s390_f0
);
3929 call
= (MonoCallInst
*)ins
;
3930 if (ins
->flags
& MONO_INST_HAS_METHOD
)
3931 mono_add_patch_info (cfg
, offset
, MONO_PATCH_INFO_METHOD
, call
->method
);
3933 mono_add_patch_info (cfg
, offset
, MONO_PATCH_INFO_ABS
, call
->fptr
);
3934 s390_brasl (code
, s390_r14
, 0);
3937 case OP_FCALL_REG
: {
3938 call
= (MonoCallInst
*)ins
;
3939 s390_lr (code
, s390_r1
, ins
->sreg1
);
3940 s390_basr (code
, s390_r14
, s390_r1
);
3941 if (call
->signature
->ret
->type
== MONO_TYPE_R4
)
3942 s390_ldebr (code
, s390_f0
, s390_f0
);
3947 case OP_VOIDCALL_REG
:
3949 s390_lr (code
, s390_r1
, ins
->sreg1
);
3950 s390_basr (code
, s390_r14
, s390_r1
);
3953 case OP_FCALL_MEMBASE
: {
3954 call
= (MonoCallInst
*)ins
;
3955 s390_l (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3956 s390_basr (code
, s390_r14
, s390_r1
);
3957 if (call
->signature
->ret
->type
== MONO_TYPE_R4
)
3958 s390_ldebr (code
, s390_f0
, s390_f0
);
3961 case OP_LCALL_MEMBASE
:
3962 case OP_VCALL_MEMBASE
:
3963 case OP_VOIDCALL_MEMBASE
:
3964 case OP_CALL_MEMBASE
: {
3965 s390_l (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3966 s390_basr (code
, s390_r14
, s390_r1
);
3970 g_assert_not_reached ();
3973 int alloca_skip
= S390_MINIMAL_STACK_SIZE
+ cfg
->param_area
+
3974 S390_STACK_ALIGNMENT
- 1;
3975 int area_offset
= S390_ALIGN(alloca_skip
, S390_STACK_ALIGNMENT
);
3976 s390_lr (code
, s390_r1
, ins
->sreg1
);
3977 s390_ahi (code
, s390_r1
, 14);
3978 s390_srl (code
, s390_r1
, 0, 3);
3979 s390_sll (code
, s390_r1
, 0, 3);
3980 s390_l (code
, s390_r13
, 0, STK_BASE
, 0);
3981 s390_lcr (code
, s390_r1
, s390_r1
);
3982 s390_la (code
, STK_BASE
, STK_BASE
, s390_r1
, 0);
3983 s390_st (code
, s390_r13
, 0, STK_BASE
, 0);
3984 s390_la (code
, ins
->dreg
, 0, STK_BASE
, area_offset
);
3985 s390_srl (code
, ins
->dreg
, 0, 3);
3986 s390_sll (code
, ins
->dreg
, 0, 3);
3990 s390_br (code
, s390_r14
);
3994 s390_lr (code
, s390_r2
, ins
->sreg1
);
3995 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_INTERNAL_METHOD
,
3996 (gpointer
)"mono_arch_throw_exception");
3997 s390_brasl (code
, s390_r14
, 0);
4000 case OP_START_HANDLER
: {
4001 if (s390_is_uimm12 (ins
->inst_left
->inst_offset
)) {
4002 s390_st (code
, s390_r14
, 0,
4003 ins
->inst_left
->inst_basereg
,
4004 ins
->inst_left
->inst_offset
);
4006 s390_basr (code
, s390_r13
, 0);
4008 s390_word (code
, ins
->inst_left
->inst_offset
);
4009 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4010 s390_st (code
, s390_r14
, s390_r13
,
4011 ins
->inst_left
->inst_basereg
, 0);
4015 case OP_ENDFILTER
: {
4016 if (ins
->sreg1
!= s390_r2
)
4017 s390_lr (code
, s390_r2
, ins
->sreg1
);
4018 if (s390_is_uimm12 (ins
->inst_left
->inst_offset
)) {
4019 s390_l (code
, s390_r14
, 0, ins
->inst_left
->inst_basereg
,
4020 ins
->inst_left
->inst_offset
);
4022 s390_basr (code
, s390_r13
, 0);
4024 s390_word (code
, ins
->inst_left
->inst_offset
);
4025 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4026 s390_l (code
, s390_r14
, s390_r13
,
4027 ins
->inst_left
->inst_basereg
, 0);
4029 // s390_l (code, STK_BASE, 0, STK_BASE, 0);
4030 // s390_lm (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
4031 s390_br (code
, s390_r14
);
4034 case CEE_ENDFINALLY
: {
4035 if (s390_is_uimm12 (ins
->inst_left
->inst_offset
)) {
4036 s390_l (code
, s390_r14
, 0, ins
->inst_left
->inst_basereg
,
4037 ins
->inst_left
->inst_offset
);
4039 s390_basr (code
, s390_r13
, 0);
4041 s390_word (code
, ins
->inst_left
->inst_offset
);
4042 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4043 s390_l (code
, s390_r14
, s390_r13
,
4044 ins
->inst_left
->inst_basereg
, 0);
4046 // s390_l (code, s390_r14, 0, ins->inst_left->inst_basereg, ins->inst_left->inst_offset);
4047 s390_br (code
, s390_r14
);
4050 case OP_CALL_HANDLER
: {
4051 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4052 MONO_PATCH_INFO_BB
, ins
->inst_target_bb
);
4053 s390_brasl (code
, s390_r14
, 0);
4057 ins
->inst_c0
= code
- cfg
->native_code
;
4061 EMIT_UNCOND_BRANCH(ins
);
4064 s390_br (code
, ins
->sreg1
);
4068 s390_lhi (code
, ins
->dreg
, 1);
4070 s390_lhi (code
, ins
->dreg
, 0);
4074 s390_lhi (code
, ins
->dreg
, 1);
4076 s390_lhi (code
, ins
->dreg
, 0);
4080 s390_lhi (code
, ins
->dreg
, 1);
4082 s390_lhi (code
, ins
->dreg
, 0);
4086 s390_lhi (code
, ins
->dreg
, 1);
4088 s390_lhi (code
, ins
->dreg
, 0);
4092 s390_lhi (code
, ins
->dreg
, 1);
4094 s390_lhi (code
, ins
->dreg
, 0);
4097 case OP_COND_EXC_EQ
:
4098 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ
, ins
->inst_p1
);
4100 case OP_COND_EXC_NE_UN
:
4101 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE
, ins
->inst_p1
);
4103 case OP_COND_EXC_LT
:
4104 case OP_COND_EXC_LT_UN
:
4105 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, ins
->inst_p1
);
4107 case OP_COND_EXC_GT
:
4108 case OP_COND_EXC_GT_UN
:
4109 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, ins
->inst_p1
);
4111 case OP_COND_EXC_GE
:
4112 case OP_COND_EXC_GE_UN
:
4113 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE
, ins
->inst_p1
);
4115 case OP_COND_EXC_LE
:
4116 case OP_COND_EXC_LE_UN
:
4117 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE
, ins
->inst_p1
);
4119 case OP_COND_EXC_OV
:
4120 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, ins
->inst_p1
);
4122 case OP_COND_EXC_NO
:
4123 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO
, ins
->inst_p1
);
4126 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, ins
->inst_p1
);
4128 case OP_COND_EXC_NC
:
4129 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, ins
->inst_p1
);
4132 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
4135 EMIT_COND_BRANCH (ins
, S390_CC_NE
);
4139 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4143 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4147 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4151 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4154 /* floating point opcodes */
4156 if (*((float *) ins
->inst_p0
) == 0) {
4157 s390_lzdr (code
, ins
->dreg
);
4159 s390_basr (code
, s390_r13
, 0);
4161 s390_word (code
, ins
->inst_p0
);
4162 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4163 s390_ld (code
, ins
->dreg
, 0, s390_r13
, 0);
4168 if (*((float *) ins
->inst_p0
) == 0) {
4169 s390_lzdr (code
, ins
->dreg
);
4171 s390_basr (code
, s390_r13
, 0);
4173 s390_word (code
, ins
->inst_p0
);
4174 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4175 s390_ldeb (code
, ins
->dreg
, 0, s390_r13
, 0);
4176 // s390_ldebr(code, ins->dreg, ins->dreg);
4180 case OP_STORER8_MEMBASE_REG
: {
4181 if (s390_is_uimm12(ins
->inst_offset
)) {
4182 s390_std (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
4184 s390_basr (code
, s390_r13
, 0);
4186 s390_word (code
, ins
->inst_offset
);
4187 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4188 s390_std (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
4192 case OP_LOADR8_MEMBASE
: {
4193 if (s390_is_uimm12(ins
->inst_offset
)) {
4194 s390_ld (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4196 s390_basr (code
, s390_r13
, 0);
4198 s390_word (code
, ins
->inst_offset
);
4199 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4200 s390_ld (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
4204 case OP_STORER4_MEMBASE_REG
: {
4205 if (s390_is_uimm12(ins
->inst_offset
)) {
4206 s390_ledbr(code
, s390_f15
, ins
->sreg1
);
4207 s390_ste (code
, s390_f15
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
4209 s390_basr (code
, s390_r13
, 0);
4211 s390_word (code
, ins
->inst_offset
);
4212 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4213 s390_ledbr(code
, s390_f15
, ins
->sreg1
);
4214 s390_ste (code
, s390_f15
, s390_r13
, ins
->inst_destbasereg
, 0);
4218 case OP_LOADR4_MEMBASE
: {
4219 if (s390_is_uimm12(ins
->inst_offset
)) {
4220 s390_ldeb (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4222 s390_basr (code
, s390_r13
, 0);
4224 s390_word (code
, ins
->inst_offset
);
4225 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4226 s390_ldeb (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
4228 // s390_ldebr (code, ins->dreg, ins->dreg);
4231 case CEE_CONV_R_UN
: {
4232 s390_cdfbr (code
, ins
->dreg
, ins
->sreg1
);
4233 s390_ltr (code
, ins
->sreg1
, ins
->sreg1
);
4234 s390_jnl (code
, 12);
4235 s390_basr (code
, s390_r13
, 0);
4237 s390_word (code
, 0x41f00000);
4238 s390_word (code
, 0);
4239 s390_adb (code
, ins
->dreg
, 0, s390_r13
, 4);
4243 s390_cdfbr (code
, ins
->dreg
, ins
->sreg1
);
4247 s390_cdfbr (code
, ins
->dreg
, ins
->sreg1
);
4250 case OP_FCONV_TO_I1
:
4251 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, TRUE
);
4253 case OP_FCONV_TO_U1
:
4254 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4256 case OP_FCONV_TO_I2
:
4257 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, TRUE
);
4259 case OP_FCONV_TO_U2
:
4260 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4262 case OP_FCONV_TO_I4
:
4264 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, TRUE
);
4266 case OP_FCONV_TO_U4
:
4268 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4270 case OP_FCONV_TO_I8
:
4271 case OP_FCONV_TO_U8
:
4272 g_assert_not_reached ();
4273 /* Implemented as helper calls */
4275 case OP_LCONV_TO_R_UN
:
4276 g_assert_not_reached ();
4277 /* Implemented as helper calls */
4279 case OP_LCONV_TO_OVF_I
: {
4280 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4282 s390_ltr (code
, ins
->sreg2
, ins
->sreg2
);
4283 s390_jnl (code
, 0); CODEPTR(code
, o
[0]);
4284 s390_ltr (code
, ins
->sreg1
, ins
->sreg1
);
4285 s390_jnl (code
, 0); CODEPTR(code
, o
[1]);
4286 s390_lhi (code
, s390_r13
, -1);
4287 s390_cr (code
, ins
->sreg1
, s390_r13
);
4288 s390_jnz (code
, 0); CODEPTR(code
, o
[2]);
4289 if (ins
->dreg
!= ins
->sreg2
)
4290 s390_lr (code
, ins
->dreg
, ins
->sreg2
);
4291 s390_j (code
, 0); CODEPTR(code
, o
[3]);
4292 PTRSLOT(code
, o
[0]);
4293 s390_jz (code
, 0); CODEPTR(code
, o
[4]);
4294 PTRSLOT(code
, o
[1]);
4295 PTRSLOT(code
, o
[2]);
4296 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4297 MONO_PATCH_INFO_EXC
, "OverflowException");
4298 s390_brasl (code
, s390_r14
, 0);
4299 PTRSLOT(code
, o
[3]);
4300 PTRSLOT(code
, o
[4]);
4304 s390_sqdbr (code
, ins
->dreg
, ins
->sreg1
);
4308 if (ins
->dreg
== ins
->sreg1
)
4309 s390_adbr (code
, ins
->dreg
, ins
->sreg2
);
4311 if (ins
->dreg
== ins
->sreg2
)
4312 s390_adbr (code
, ins
->dreg
, ins
->sreg1
);
4314 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4315 s390_adbr (code
, ins
->dreg
, ins
->sreg2
);
4321 if (ins
->dreg
== ins
->sreg1
)
4322 s390_sdbr (code
, ins
->dreg
, ins
->sreg2
);
4324 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4325 s390_sdbr (code
, ins
->dreg
, ins
->sreg2
);
4330 if (ins
->dreg
== ins
->sreg1
)
4331 s390_mdbr (code
, ins
->dreg
, ins
->sreg2
);
4333 if (ins
->dreg
== ins
->sreg2
)
4334 s390_mdbr (code
, ins
->dreg
, ins
->sreg1
);
4336 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4337 s390_mdbr (code
, ins
->dreg
, ins
->sreg2
);
4343 if (ins
->dreg
== ins
->sreg1
)
4344 s390_ddbr (code
, ins
->dreg
, ins
->sreg2
);
4346 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4347 s390_ddbr (code
, ins
->dreg
, ins
->sreg2
);
4352 s390_lcdbr (code
, ins
->dreg
, ins
->sreg1
);
4356 if (ins
->dreg
!= ins
->sreg1
) {
4357 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4359 s390_didbr (code
, ins
->dreg
, ins
->sreg2
, 5, s390_f15
);
4363 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4367 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4368 s390_lhi (code
, ins
->dreg
, 1);
4370 s390_lhi (code
, ins
->dreg
, 0);
4374 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4375 s390_lhi (code
, ins
->dreg
, 1);
4377 s390_lhi (code
, ins
->dreg
, 0);
4381 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4382 s390_lhi (code
, ins
->dreg
, 1);
4384 s390_lhi (code
, ins
->dreg
, 0);
4388 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4389 s390_lhi (code
, ins
->dreg
, 1);
4391 s390_lhi (code
, ins
->dreg
, 0);
4395 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4396 s390_lhi (code
, ins
->dreg
, 1);
4398 s390_lhi (code
, ins
->dreg
, 0);
4402 EMIT_COND_BRANCH (ins
, S390_CC_EQ
|S390_CC_OV
);
4405 EMIT_COND_BRANCH (ins
, S390_CC_NE
|S390_CC_OV
);
4408 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4411 EMIT_COND_BRANCH (ins
, S390_CC_LT
|S390_CC_OV
);
4414 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4417 EMIT_COND_BRANCH (ins
, S390_CC_GT
|S390_CC_OV
);
4420 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4423 EMIT_COND_BRANCH (ins
, S390_CC_GE
|S390_CC_OV
);
4426 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4429 EMIT_COND_BRANCH (ins
, S390_CC_LE
|S390_CC_OV
);
4431 case CEE_CKFINITE
: {
4433 s390_lhi (code
, s390_r13
, 0x7f);
4434 s390_tcdb (code
, ins
->sreg1
, 0, s390_r13
, 0);
4435 s390_jz (code
, 0); CODEPTR(code
, o
);
4436 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4437 MONO_PATCH_INFO_EXC
, "ArithmeticException");
4438 s390_brasl (code
, s390_r14
,0);
4442 case OP_S390_MOVE
: {
4443 if (ins
->unused
> 0) {
4444 if (ins
->unused
<= 256) {
4445 s390_mvc (code
, ins
->unused
, ins
->dreg
,
4446 ins
->inst_offset
, ins
->sreg1
, ins
->inst_imm
);
4448 s390_lr (code
, s390_r0
, ins
->dreg
);
4449 if (s390_is_imm16 (ins
->inst_offset
)) {
4450 s390_ahi (code
, s390_r0
, ins
->inst_offset
);
4452 s390_basr (code
, s390_r13
, 0);
4454 s390_word (code
, ins
->inst_offset
);
4455 s390_a (code
, s390_r0
, 0, s390_r13
, 4);
4457 s390_lr (code
, s390_r1
, ins
->sreg2
);
4458 if (s390_is_imm16 (ins
->inst_imm
)) {
4459 s390_ahi (code
, s390_r1
, ins
->inst_imm
);
4461 s390_basr (code
, s390_r13
, 0);
4463 s390_word (code
, ins
->inst_imm
);
4464 s390_a (code
, s390_r1
, 0, s390_r13
, 4);
4466 s390_lr (code
, s390_r12
, ins
->sreg1
);
4467 s390_lr (code
, s390_r13
, s390_r1
);
4468 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
4475 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins
->opcode
), __FUNCTION__
);
4476 g_assert_not_reached ();
4479 if ((cfg
->opt
& MONO_OPT_BRANCH
) && ((code
- cfg
->native_code
- offset
) > max_len
)) {
4480 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)",
4481 mono_inst_name (ins
->opcode
), max_len
, code
- cfg
->native_code
- offset
);
4482 g_assert_not_reached ();
4488 last_offset
= offset
;
4493 cfg
->code_len
= code
- cfg
->native_code
;
4496 /*========================= End of Function ========================*/
4498 /*------------------------------------------------------------------*/
4500 /* Name - mono_arch_register_lowlevel_calls */
4502 /* Function - Register routines to help with --trace operation. */
4504 /*------------------------------------------------------------------*/
4507 mono_arch_register_lowlevel_calls (void)
4509 mono_register_jit_icall (enter_method
, "mono_enter_method", NULL
, TRUE
);
4510 mono_register_jit_icall (leave_method
, "mono_leave_method", NULL
, TRUE
);
4513 /*========================= End of Function ========================*/
4515 /*------------------------------------------------------------------*/
4517 /* Name - mono_arch_patch_code */
4519 /* Function - Process the patch data created during the */
4520 /* instruction build process. This resolves jumps, */
4521 /* calls, variables etc. */
4523 /*------------------------------------------------------------------*/
4526 mono_arch_patch_code (MonoMethod
*method
, MonoDomain
*domain
, guint8
*code
, MonoJumpInfo
*ji
, gboolean run_cctors
)
4528 MonoJumpInfo
*patch_info
;
4530 for (patch_info
= ji
; patch_info
; patch_info
= patch_info
->next
) {
4531 unsigned char *ip
= patch_info
->ip
.i
+ code
;
4534 switch (patch_info
->type
) {
4535 case MONO_PATCH_INFO_BB
:
4536 target
= S390_RELATIVE((patch_info
->data
.bb
->native_offset
+code
),
4538 ip
+= 2; /* Skip over op-code */
4540 case MONO_PATCH_INFO_ABS
:
4541 target
= S390_RELATIVE(patch_info
->data
.target
, ip
);
4542 ip
+= 2; /* Skip over op-code */
4544 case MONO_PATCH_INFO_LABEL
:
4545 target
= S390_RELATIVE((patch_info
->data
.inst
->inst_c0
+code
),ip
);
4546 ip
+= 2; /* Skip over op-code */
4548 case MONO_PATCH_INFO_IP
:
4551 case MONO_PATCH_INFO_METHOD_REL
:
4552 g_assert_not_reached ();
4553 *((gpointer
*)(ip
)) = code
+ patch_info
->data
.offset
;
4555 case MONO_PATCH_INFO_INTERNAL_METHOD
: {
4556 MonoJitICallInfo
*mi
= mono_find_jit_icall_by_name (patch_info
->data
.name
);
4558 g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info
->data
.name
);
4559 g_assert_not_reached ();
4561 target
= S390_RELATIVE(mono_icall_get_wrapper (mi
), ip
);
4562 ip
+= 2; /* Skip over op-code */
4565 case MONO_PATCH_INFO_METHOD_JUMP
: {
4568 /*------------------------------------------------------*/
4569 /* get the trampoline to the method from the domain */
4570 /*------------------------------------------------------*/
4571 target
= mono_create_jump_trampoline (domain
,
4572 patch_info
->data
.method
,
4574 target
= S390_RELATIVE(target
, ip
);
4575 if (!domain
->jump_target_hash
)
4576 domain
->jump_target_hash
= g_hash_table_new (NULL
, NULL
);
4577 list
= g_hash_table_lookup (domain
->jump_target_hash
,
4578 patch_info
->data
.method
);
4579 list
= g_slist_prepend (list
, ip
);
4580 g_hash_table_insert (domain
->jump_target_hash
,
4581 patch_info
->data
.method
, list
);
4585 case MONO_PATCH_INFO_METHOD
:
4586 if (patch_info
->data
.method
== method
) {
4587 target
= S390_RELATIVE(code
, ip
);
4589 /* get the trampoline to the method from the domain */
4590 target
= S390_RELATIVE(mono_arch_create_jit_trampoline (patch_info
->data
.method
), ip
);
4591 target
= mono_arch_create_jit_trampoline(patch_info
->data
.method
);
4592 target
= S390_RELATIVE(target
, ip
);
4594 ip
+= 2; /* Skip over op-code */
4596 case MONO_PATCH_INFO_SWITCH
: {
4597 gpointer
*table
= (gpointer
*)patch_info
->data
.target
;
4599 /*------------------------------------------------------*/
4600 /* ip is pointing at the basr r13,0/j +4 instruction */
4601 /* the vtable value follows this (i.e. ip+6) */
4602 /*------------------------------------------------------*/
4603 *((gconstpointer
*)(ip
+6)) = table
;
4605 for (i
= 0; i
< patch_info
->table_size
; i
++) {
4606 table
[i
] = (int)patch_info
->data
.table
[i
] + code
;
4610 case MONO_PATCH_INFO_METHODCONST
:
4611 case MONO_PATCH_INFO_CLASS
:
4612 case MONO_PATCH_INFO_IMAGE
:
4613 case MONO_PATCH_INFO_FIELD
:
4614 target
= S390_RELATIVE(patch_info
->data
.target
, ip
);
4616 case MONO_PATCH_INFO_R4
:
4617 case MONO_PATCH_INFO_R8
:
4618 g_assert_not_reached ();
4619 *((gconstpointer
*)(ip
+ 2)) = patch_info
->data
.target
;
4621 case MONO_PATCH_INFO_IID
:
4622 mono_class_init (patch_info
->data
.klass
);
4623 target
= S390_RELATIVE(patch_info
->data
.klass
->interface_id
, ip
);
4625 case MONO_PATCH_INFO_VTABLE
:
4626 target
= S390_RELATIVE(mono_class_vtable (domain
, patch_info
->data
.klass
),ip
);
4629 case MONO_PATCH_INFO_CLASS_INIT
:
4630 target
= S390_RELATIVE(mono_create_class_init_trampoline (mono_class_vtable (domain
, patch_info
->data
.klass
)), ip
);
4633 case MONO_PATCH_INFO_SFLDA
: {
4634 MonoVTable
*vtable
= mono_class_vtable (domain
, patch_info
->data
.field
->parent
);
4635 if (!vtable
->initialized
&& !(vtable
->klass
->flags
& TYPE_ATTRIBUTE_BEFORE_FIELD_INIT
) && mono_class_needs_cctor_run (vtable
->klass
, method
))
4636 /* Done by the generated code */
4640 mono_runtime_class_init (vtable
);
4642 target
= S390_RELATIVE((char*)vtable
->data
+ patch_info
->data
.field
->offset
, ip
);
4646 case MONO_PATCH_INFO_EXC_NAME
:
4647 *((gconstpointer
*)(ip
)) = patch_info
->data
.name
;
4649 case MONO_PATCH_INFO_LDSTR
:
4650 target
= mono_ldstr (domain
, patch_info
->data
.token
->image
,
4651 mono_metadata_token_index (patch_info
->data
.token
->token
));
4653 case MONO_PATCH_INFO_TYPE_FROM_HANDLE
: {
4655 MonoClass
*handle_class
;
4657 handle
= mono_ldtoken (patch_info
->data
.token
->image
,
4658 patch_info
->data
.token
->token
,
4659 &handle_class
, NULL
);
4660 mono_class_init (handle_class
);
4661 mono_class_init (mono_class_from_mono_type (handle
));
4666 case MONO_PATCH_INFO_LDTOKEN
: {
4668 MonoClass
*handle_class
;
4670 handle
= mono_ldtoken (patch_info
->data
.token
->image
,
4671 patch_info
->data
.token
->token
,
4672 &handle_class
, NULL
);
4673 mono_class_init (handle_class
);
4678 case MONO_PATCH_INFO_EXC
:
4679 /* everything is dealt with at epilog output time */
4682 g_assert_not_reached ();
4684 s390_patch (ip
, target
);
4688 /*========================= End of Function ========================*/
4690 /*------------------------------------------------------------------*/
4692 /* Name - mono_arch_max_epilog_size */
4694 /* Function - Determine the maximum size of the epilog code. */
4696 /*------------------------------------------------------------------*/
4699 mono_arch_max_epilog_size (MonoCompile
*cfg
)
4701 int max_epilog_size
= 96;
4702 MonoJumpInfo
*patch_info
;
4704 if (cfg
->method
->save_lmf
)
4705 max_epilog_size
+= 128;
4707 if (mono_jit_trace_calls
!= NULL
)
4708 max_epilog_size
+= 128;
4710 if (cfg
->prof_options
& MONO_PROFILE_ENTER_LEAVE
)
4711 max_epilog_size
+= 128;
4713 /* count the number of exception infos */
4715 for (patch_info
= cfg
->patch_info
; patch_info
; patch_info
= patch_info
->next
) {
4716 if (patch_info
->type
== MONO_PATCH_INFO_EXC
)
4717 max_epilog_size
+= 26;
4720 return max_epilog_size
;
4723 /*========================= End of Function ========================*/
4725 /*------------------------------------------------------------------*/
4727 /* Name - mono_arch_emit_prolog */
4729 /* Function - Create the instruction sequence for a function */
4732 /*------------------------------------------------------------------*/
4735 mono_arch_emit_prolog (MonoCompile
*cfg
)
4737 MonoMethod
*method
= cfg
->method
;
4739 MonoMethodSignature
*sig
;
4741 int alloc_size
, pos
, max_offset
, i
, lmfOffset
;
4747 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (method
))
4750 cfg
->code_size
= 256;
4751 cfg
->native_code
= code
= g_malloc (cfg
->code_size
);
4753 s390_stm (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
4755 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
4756 cfg
->used_int_regs
|= 1 << 11;
4759 alloc_size
= cfg
->stack_offset
;
4761 // alloc_size += S390_TRACE_STACK_SIZE;
4763 /* reserve room to save return value */
4767 // alloc_size += pos;
4769 // if (method->save_lmf)
4770 // alloc_size += sizeof(MonoLMF);
4772 // alloc_size = S390_ALIGN(alloc_size, S390_STACK_ALIGNMENT);
4774 cfg
->stack_usage
= alloc_size
;
4775 s390_lr (code
, s390_r11
, STK_BASE
);
4776 if (s390_is_imm16 (-alloc_size
)) {
4777 s390_ahi (code
, STK_BASE
, -alloc_size
);
4779 int stackSize
= alloc_size
;
4780 while (stackSize
> 32767) {
4781 s390_ahi (code
, STK_BASE
, -32767);
4784 s390_ahi (code
, STK_BASE
, -stackSize
);
4786 s390_st (code
, s390_r11
, 0, STK_BASE
, 0);
4788 // if (cfg->flags & MONO_CFG_HAS_ALLOCA)
4789 if (cfg
->frame_reg
!= STK_BASE
)
4790 s390_lr (code
, s390_r11
, STK_BASE
);
4792 /* compute max_offset in order to use short forward jumps
4793 * we always do it on s390 because the immediate displacement
4794 * for jumps is too small
4797 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
4798 MonoInst
*ins
= bb
->code
;
4799 bb
->max_offset
= max_offset
;
4801 if (cfg
->prof_options
& MONO_PROFILE_COVERAGE
)
4805 max_offset
+= ((guint8
*)ins_spec
[ins
->opcode
])[MONO_INST_LEN
];
4810 /* load arguments allocated to register from the stack */
4811 sig
= method
->signature
;
4814 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
4816 if (cinfo
->struct_ret
) {
4817 ArgInfo
*ainfo
= &cinfo
->ret
;
4819 inst
->unused
= ainfo
->vtsize
;
4820 s390_st (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
4823 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
4824 ArgInfo
*ainfo
= cinfo
->args
+ i
;
4825 inst
= cfg
->varinfo
[pos
];
4827 if (inst
->opcode
== OP_REGVAR
) {
4828 if (ainfo
->regtype
== RegTypeGeneral
)
4829 s390_lr (code
, inst
->dreg
, ainfo
->reg
);
4830 else if (ainfo
->regtype
== RegTypeFP
) {
4831 if (inst
->dreg
!= ainfo
->reg
) {
4832 if (ainfo
->size
== 4) {
4833 s390_ledbr (code
, inst
->dreg
, ainfo
->reg
);
4834 // s390_ler (code, inst->dreg, ainfo->reg);
4836 s390_ldr (code
, inst
->dreg
, ainfo
->reg
);
4840 else if (ainfo
->regtype
== RegTypeBase
) {
4841 s390_lr (code
, s390_r13
, STK_BASE
);
4842 s390_ahi (code
, s390_r13
, alloc_size
);
4843 s390_l (code
, inst
->dreg
, 0, s390_r13
, ainfo
->offset
);
4845 g_assert_not_reached ();
4847 if (cfg
->verbose_level
> 2)
4848 g_print ("Argument %d assigned to register %s\n",
4849 pos
, mono_arch_regname (inst
->dreg
));
4851 if (ainfo
->regtype
== RegTypeGeneral
) {
4852 if (!((ainfo
->reg
>= 2) && (ainfo
->reg
<= 6)))
4853 g_assert_not_reached();
4854 switch (ainfo
->size
) {
4856 s390_stc (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
4859 s390_sth (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
4862 s390_stm (code
, ainfo
->reg
, ainfo
->reg
+ 1,
4863 inst
->inst_basereg
, inst
->inst_offset
);
4866 s390_st (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
4868 } else if (ainfo
->regtype
== RegTypeBase
) {
4869 } else if (ainfo
->regtype
== RegTypeFP
) {
4870 if (ainfo
->size
== 8)
4871 s390_std (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
4872 else if (ainfo
->size
== 4)
4873 s390_ste (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
4875 g_assert_not_reached ();
4876 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
4877 int doffset
= inst
->inst_offset
;
4879 if (ainfo
->reg
!= STK_BASE
)
4883 s390_lr (code
, s390_r13
, STK_BASE
);
4884 s390_ahi (code
, s390_r13
, alloc_size
);
4886 switch (ainfo
->size
) {
4888 if (ainfo
->reg
== STK_BASE
)
4889 s390_ic (code
, reg
, 0, s390_r13
, ainfo
->offset
+3);
4890 s390_stc (code
, reg
, 0, inst
->inst_basereg
, doffset
);
4893 if (ainfo
->reg
== STK_BASE
)
4894 s390_lh (code
, reg
, 0, s390_r13
, ainfo
->offset
+2);
4895 s390_sth (code
, reg
, 0, inst
->inst_basereg
, doffset
);
4898 if (ainfo
->reg
== STK_BASE
)
4899 s390_l (code
, reg
, 0, s390_r13
, ainfo
->offset
);
4900 s390_st (code
, reg
, 0, inst
->inst_basereg
, doffset
);
4903 if (ainfo
->reg
== STK_BASE
)
4904 s390_lm (code
, s390_r0
, s390_r1
, s390_r13
, ainfo
->offset
);
4905 s390_stm (code
, reg
, reg
+1, inst
->inst_basereg
, doffset
);
4908 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
4909 if (ainfo
->reg
== STK_BASE
) {
4910 s390_lr (code
, s390_r13
, ainfo
->reg
);
4911 s390_ahi (code
, s390_r13
, alloc_size
);
4912 s390_l (code
, s390_r13
, 0, s390_r13
,
4913 ainfo
->offparm
+ S390_MINIMAL_STACK_SIZE
);
4914 code
= emit_memcpy (code
, abs(ainfo
->vtsize
),
4916 inst
->inst_offset
, s390_r13
, 0);
4918 code
= emit_memcpy (code
, abs(ainfo
->vtsize
),
4924 g_assert_not_reached ();
4929 if (method
->save_lmf
) {
4930 /*---------------------------------------------------------------*/
4931 /* Preserve the parameter registers while we fix up the lmf */
4932 /*---------------------------------------------------------------*/
4933 s390_lr (code
, s390_r7
, s390_r2
);
4934 s390_lr (code
, s390_r8
, s390_r3
);
4935 s390_lr (code
, s390_r9
, s390_r4
);
4936 s390_lr (code
, s390_r10
, s390_r5
);
4938 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4939 MONO_PATCH_INFO_INTERNAL_METHOD
,
4940 (gpointer
)"mono_get_lmf_addr");
4941 /*---------------------------------------------------------------*/
4942 /* On return from this call r2 have the address of the &lmf */
4943 /*---------------------------------------------------------------*/
4944 s390_brasl (code
, s390_r14
, 0);
4946 /*---------------------------------------------------------------*/
4947 /* we build the MonoLMF structure on the stack - see mini-s390.h */
4948 /*---------------------------------------------------------------*/
4949 lmfOffset
= alloc_size
- sizeof(MonoLMF
);
4951 s390_lr (code
, s390_r13
, cfg
->frame_reg
);
4952 s390_ahi (code
, s390_r13
, lmfOffset
);
4954 /*---------------------------------------------------------------*/
4955 /* Set lmf.lmf_addr = jit_tls->lmf */
4956 /*---------------------------------------------------------------*/
4957 s390_st (code
, s390_r2
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
4959 /*---------------------------------------------------------------*/
4960 /* Get current lmf */
4961 /*---------------------------------------------------------------*/
4962 s390_l (code
, s390_r0
, 0, s390_r2
, 0);
4964 /*---------------------------------------------------------------*/
4965 /* Set our lmf as the current lmf */
4966 /*---------------------------------------------------------------*/
4967 s390_st (code
, s390_r13
, 0, s390_r2
, 0);
4969 /*---------------------------------------------------------------*/
4970 /* Have our lmf.previous_lmf point to the last lmf */
4971 /*---------------------------------------------------------------*/
4972 s390_st (code
, s390_r0
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
4974 /*---------------------------------------------------------------*/
4975 /* save method info */
4976 /*---------------------------------------------------------------*/
4977 s390_basr (code
, s390_r1
, 0);
4979 s390_word (code
, method
);
4980 s390_l (code
, s390_r1
, 0, s390_r1
, 4);
4981 s390_st (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, method
));
4983 /*---------------------------------------------------------------*/
4984 /* save the current IP */
4985 /*---------------------------------------------------------------*/
4986 s390_lr (code
, s390_r1
, cfg
->frame_reg
);
4987 // s390_ahi (code, s390_r1, alloc_size);
4988 s390_st (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, ebp
));
4989 s390_l (code
, s390_r1
, 0, s390_r1
, S390_RET_ADDR_OFFSET
);
4990 s390_la (code
, s390_r1
, 0, s390_r1
, 0);
4991 s390_st (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, eip
));
4993 /*---------------------------------------------------------------*/
4994 /* Save general and floating point registers */
4995 /*---------------------------------------------------------------*/
4996 s390_stm (code
, s390_r2
, s390_r12
, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, gregs
[2]));
4997 for (i
= 0; i
< 16; i
++) {
4998 s390_std (code
, i
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, fregs
[i
]));
5001 /*---------------------------------------------------------------*/
5002 /* Restore the parameter registers now that we've set up the lmf */
5003 /*---------------------------------------------------------------*/
5004 s390_lr (code
, s390_r2
, s390_r7
);
5005 s390_lr (code
, s390_r3
, s390_r8
);
5006 s390_lr (code
, s390_r4
, s390_r9
);
5007 s390_lr (code
, s390_r5
, s390_r10
);
5011 code
= mono_arch_instrument_prolog (cfg
, enter_method
, code
, TRUE
);
5013 cfg
->code_len
= code
- cfg
->native_code
;
5019 /*========================= End of Function ========================*/
5021 /*------------------------------------------------------------------*/
5023 /* Name - mono_arch_emit_epilog */
5025 /* Function - Emit the instructions for a function epilog. */
5027 /*------------------------------------------------------------------*/
5030 mono_arch_emit_epilog (MonoCompile
*cfg
)
5032 MonoJumpInfo
*patch_info
;
5033 MonoMethod
*method
= cfg
->method
;
5034 MonoMethodSignature
*sig
= method
->signature
;
5039 code
= cfg
->native_code
+ cfg
->code_len
;
5041 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (method
)) {
5042 code
= mono_arch_instrument_epilog (cfg
, leave_method
, code
, TRUE
);
5046 if (method
->save_lmf
)
5047 code
= restoreLMF(cfg
, code
);
5049 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
)
5050 s390_l (code
, STK_BASE
, 0, STK_BASE
, 0);
5052 code
= backUpStackPtr(cfg
, code
);
5054 s390_lm (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5055 s390_br (code
, s390_r14
);
5057 /* add code to raise exceptions */
5058 for (patch_info
= cfg
->patch_info
; patch_info
; patch_info
= patch_info
->next
) {
5059 switch (patch_info
->type
) {
5060 case MONO_PATCH_INFO_EXC
: {
5061 /*-----------------------------------------------------*/
5062 /* Patch the branch in epilog to come here */
5063 /*-----------------------------------------------------*/
5064 s390_patch (patch_info
->ip
.i
+cfg
->native_code
+2,
5065 S390_RELATIVE(code
,patch_info
->ip
.i
+cfg
->native_code
));
5066 /*-----------------------------------------------------*/
5067 /* Patch the parameter passed to the handler */
5068 /*-----------------------------------------------------*/
5069 s390_basr (code
, s390_r13
, 0);
5071 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5072 MONO_PATCH_INFO_EXC_NAME
,
5073 patch_info
->data
.target
);
5074 s390_word (code
, 0);
5075 /*-----------------------------------------------------*/
5076 /* Load the return address and the parameter register */
5077 /*-----------------------------------------------------*/
5078 s390_larl (code
, s390_r14
, S390_RELATIVE((patch_info
->ip
.i
+
5079 cfg
->native_code
+ 8), code
));
5080 s390_l (code
, s390_r2
, 0, s390_r13
, 4);
5081 /*-----------------------------------------------------*/
5082 /* Reuse the current patch to set the jump */
5083 /*-----------------------------------------------------*/
5084 patch_info
->type
= MONO_PATCH_INFO_INTERNAL_METHOD
;
5085 patch_info
->data
.name
= "mono_arch_throw_exception_by_name";
5086 patch_info
->ip
.i
= code
- cfg
->native_code
;
5087 s390_jcl (code
, S390_CC_UN
, 0);
5096 cfg
->code_len
= code
- cfg
->native_code
;
5098 g_assert (cfg
->code_len
< cfg
->code_size
);
5102 /*========================= End of Function ========================*/
5104 /*------------------------------------------------------------------*/
5106 /* Name - mono_arch_setup_jit_tls_data */
5108 /* Function - Setup the JIT's Thread Level Specific Data. */
5110 /*------------------------------------------------------------------*/
5113 mono_arch_setup_jit_tls_data (MonoJitTlsData
*tls
)
5117 /*========================= End of Function ========================*/
5119 /*------------------------------------------------------------------*/
5121 /* Name - mono_arch_free_jit_tls_data */
5123 /* Function - Free tls data. */
5125 /*------------------------------------------------------------------*/
5128 mono_arch_free_jit_tls_data (MonoJitTlsData
*tls
)
5132 /*========================= End of Function ========================*/
5134 /*------------------------------------------------------------------*/
5136 /* Name - mono_arch_emit_this_vret_args */
5140 /*------------------------------------------------------------------*/
5143 mono_arch_emit_this_vret_args (MonoCompile
*cfg
, MonoCallInst
*inst
, int this_reg
, int this_type
, int vt_reg
)
5145 int this_dreg
= s390_r2
;
5148 this_dreg
= s390_r3
;
5150 /* add the this argument */
5151 if (this_reg
!= -1) {
5153 MONO_INST_NEW (cfg
, this, OP_SETREG
);
5154 this->type
= this_type
;
5155 this->sreg1
= this_reg
;
5156 this->dreg
= this_dreg
;
5157 mono_bblock_add_inst (cfg
->cbb
, this);
5162 MONO_INST_NEW (cfg
, vtarg
, OP_SETREG
);
5163 vtarg
->type
= STACK_MP
;
5164 vtarg
->sreg1
= vt_reg
;
5165 vtarg
->dreg
= s390_r2
;
5166 mono_bblock_add_inst (cfg
->cbb
, vtarg
);
5170 /*========================= End of Function ========================*/
5172 /*------------------------------------------------------------------*/
5174 /* Name - mono_arch_get_opcode_for_method */
5176 /* Function - Check for opcodes we can handle directly in */
5179 /*------------------------------------------------------------------*/
5182 mono_arch_get_opcode_for_method (MonoCompile
*cfg
, MonoMethod
*cmethod
, MonoMethodSignature
*fsig
, MonoInst
**args
)
5184 if (cmethod
->klass
== mono_defaults
.math_class
) {
5185 if (strcmp (cmethod
->name
, "Sqrt") == 0)
5191 /*========================= End of Function ========================*/
5193 /*------------------------------------------------------------------*/
5195 /* Name - mono_arch_print_tree */
5197 /* Function - Print platform-specific opcode details. */
5199 /* Returns - 1 - opcode details have been printed */
5200 /* 0 - opcode details have not been printed */
5202 /*------------------------------------------------------------------*/
5205 mono_arch_print_tree (MonoInst
*tree
, int arity
)
5209 switch (tree
->opcode
) {
5210 case OP_S390_LOADARG
:
5211 case OP_S390_ARGPTR
:
5212 case OP_S390_STKARG
:
5213 printf ("[0x%x(%s)]", tree
->inst_offset
,
5214 mono_arch_regname (tree
->inst_basereg
));
5218 printf ("[0x%x(%d,%s),0x%x(%s)]",
5219 tree
->inst_offset
, tree
->unused
,
5220 tree
->dreg
, tree
->inst_imm
,
5224 case OP_S390_SETF4RET
:
5225 printf ("[f%d,f%d]",
5226 mono_arch_regname (tree
->dreg
),
5227 mono_arch_regname (tree
->sreg1
));
5234 /*========================= End of Function ========================*/
5236 /*------------------------------------------------------------------*/
5238 /* Name - mono_arch_regalloc_cost */
5240 /* Function - Determine the cost, in the number of memory */
5241 /* references, of the action of allocating the var- */
5242 /* iable VMV into a register during global register */
5245 /* Returns - Cost */
5247 /*------------------------------------------------------------------*/
5250 mono_arch_regalloc_cost (MonoCompile
*cfg
, MonoMethodVar
*vmv
)
5256 /*========================= End of Function ========================*/