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(gint64)+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-s390x.h"
132 #include "cpu-s390x.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 gint64 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 guint8
* 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
*);
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
= s390x
;
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 - mono_arch_is_inst_imm */
280 /* Function - Determine whether an instruction qualifies as an */
283 /*------------------------------------------------------------------*/
286 mono_arch_is_inst_imm (gint64 imm
)
288 return s390_is_imm16 (imm
);
291 /*========================= End of Function ========================*/
293 /*------------------------------------------------------------------*/
295 /* Name - emit_memcpy */
297 /* Function - Emit code to move from memory-to-memory based on */
298 /* the size of the variable. r0 is overwritten. */
300 /*------------------------------------------------------------------*/
303 emit_memcpy (guint8
*code
, int size
, int dreg
, int doffset
, int sreg
, int soffset
)
307 s390_l (code
, s390_r0
, 0, sreg
, soffset
);
308 s390_st (code
, s390_r0
, 0, dreg
, doffset
);
312 s390_icm (code
, s390_r0
, 14, sreg
, soffset
);
313 s390_stcm (code
, s390_r0
, 14, dreg
, doffset
);
317 s390_lh (code
, s390_r0
, 0, sreg
, soffset
);
318 s390_sth (code
, s390_r0
, 0, dreg
, doffset
);
322 s390_ic (code
, s390_r0
, 0, sreg
, soffset
);
323 s390_stc (code
, s390_r0
, 0, dreg
, doffset
);
334 s390_mvc (code
, len
, dreg
, doffset
, sreg
, soffset
);
341 /*========================= End of Function ========================*/
343 /*------------------------------------------------------------------*/
345 /* Name - arch_get_argument_info */
347 /* Function - Gathers information on parameters such as size, */
348 /* alignment, and padding. arg_info should be large */
349 /* enough to hold param_count + 1 entries. */
351 /* Parameters - @csig - Method signature */
352 /* @param_count - No. of parameters to consider */
353 /* @arg_info - An array to store the result info */
355 /* Returns - Size of the activation frame */
357 /*------------------------------------------------------------------*/
360 mono_arch_get_argument_info (MonoMethodSignature
*csig
,
362 MonoJitArgumentInfo
*arg_info
)
364 int k
, frame_size
= 0;
365 int size
, align
, pad
;
368 if (MONO_TYPE_ISSTRUCT (csig
->ret
)) {
369 frame_size
+= sizeof (gpointer
);
373 arg_info
[0].offset
= offset
;
376 frame_size
+= sizeof (gpointer
);
380 arg_info
[0].size
= frame_size
;
382 for (k
= 0; k
< param_count
; k
++) {
385 size
= mono_type_native_stack_size (csig
->params
[k
], &align
);
387 size
= mono_type_stack_size (csig
->params
[k
], &align
);
389 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
390 arg_info
[k
].pad
= pad
;
392 arg_info
[k
+ 1].pad
= 0;
393 arg_info
[k
+ 1].size
= size
;
395 arg_info
[k
+ 1].offset
= offset
;
399 align
= MONO_ARCH_FRAME_ALIGNMENT
;
400 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
401 arg_info
[k
].pad
= pad
;
406 /*========================= End of Function ========================*/
408 /*------------------------------------------------------------------*/
410 /* Name - restoreLMF */
412 /* Function - Restore the LMF state prior to exiting a method. */
414 /*------------------------------------------------------------------*/
416 static inline guint8
*
417 restoreLMF(MonoCompile
*cfg
, guint8
*code
)
421 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
423 lmfOffset
= cfg
->stack_usage
- sizeof(MonoLMF
);
425 /*-------------------------------------------------*/
427 /*-------------------------------------------------*/
428 s390_aghi (code
, s390_r13
, lmfOffset
);
430 /*-------------------------------------------------*/
431 /* r6 = &jit_tls->lmf */
432 /*-------------------------------------------------*/
433 s390_lg (code
, s390_r6
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
435 /*-------------------------------------------------*/
436 /* r0 = lmf.previous_lmf */
437 /*-------------------------------------------------*/
438 s390_lg (code
, s390_r0
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
440 /*-------------------------------------------------*/
441 /* jit_tls->lmf = previous_lmf */
442 /*-------------------------------------------------*/
443 s390_lg (code
, s390_r13
, 0, s390_r6
, 0);
444 s390_stg (code
, s390_r0
, 0, s390_r6
, 0);
448 /*========================= End of Function ========================*/
450 /*------------------------------------------------------------------*/
452 /* Name - backStackPtr. */
454 /* Function - Restore Stack Pointer to previous frame. */
456 /*------------------------------------------------------------------*/
458 static inline guint8
*
459 backUpStackPtr(MonoCompile
*cfg
, guint8
*code
)
461 int stackSize
= cfg
->stack_usage
;
463 if (s390_is_imm16 (cfg
->stack_usage
)) {
464 s390_aghi (code
, STK_BASE
, cfg
->stack_usage
);
466 while (stackSize
> 32767) {
467 s390_aghi (code
, STK_BASE
, 32767);
470 s390_aghi (code
, STK_BASE
, stackSize
);
475 /*========================= End of Function ========================*/
477 /*------------------------------------------------------------------*/
481 /* Function - Perform nice indenting to current level */
483 /*------------------------------------------------------------------*/
489 indent_level
+= diff
;
496 indent_level
+= diff
;
499 /*========================= End of Function ========================*/
501 /*------------------------------------------------------------------*/
503 /* Name - decodeParm */
505 /* Function - Decode a parameter for the trace. */
507 /*------------------------------------------------------------------*/
510 decodeParm(MonoType
*type
, void *curParm
, int size
)
515 printf("[BYREF:%p], ", *((char **) curParm
));
517 simpleType
= type
->type
;
519 switch (simpleType
) {
521 printf ("[INTPTR:%p], ", *((int **) curParm
));
524 printf ("[UINTPTR:%p], ", *((int **) curParm
));
526 case MONO_TYPE_BOOLEAN
:
527 printf ("[BOOL:%p], ", *((int *) curParm
));
529 case MONO_TYPE_CHAR
:
530 printf ("[CHAR:%p], ", *((int *) curParm
));
533 printf ("[INT1:%d], ", *((int *) curParm
));
536 printf ("[INT2:%d], ", *((int *) curParm
));
539 printf ("[INT4:%d], ", *((int *) curParm
));
542 printf ("[UINT1:%ud], ", *((unsigned int *) curParm
));
545 printf ("[UINT2:%ud], ", *((guint16
*) curParm
));
548 printf ("[UINT4:%ud], ", *((guint32
*) curParm
));
551 printf ("[UINT8:%ul], ", *((guint64
*) curParm
));
553 case MONO_TYPE_STRING
: {
554 MonoString
*s
= *((MonoString
**) curParm
);
556 g_assert (((MonoObject
*) s
)->vtable
->klass
== mono_defaults
.string_class
);
557 printf("[STRING:%p:%s], ", s
, mono_string_to_utf8(s
));
559 printf("[STRING:null], ");
563 case MONO_TYPE_CLASS
:
564 case MONO_TYPE_OBJECT
: {
565 MonoObject
*obj
= *((MonoObject
**) curParm
);
568 printf("[CLASS/OBJ:");
569 class = obj
->vtable
->klass
;
570 if (class == mono_defaults
.string_class
) {
571 printf("[STRING:%p:%s]",
572 *obj
, mono_string_to_utf8 (obj
));
573 } else if (class == mono_defaults
.int32_class
) {
574 printf("[INT32:%p:%d]",
575 obj
, *(gint32
*)((char *)obj
+ sizeof (MonoObject
)));
578 class->name_space
, class->name
, obj
);
581 printf("[OBJECT:null], ");
586 printf("[PTR:%p], ", *((gpointer
**) (curParm
)));
588 case MONO_TYPE_FNPTR
:
589 printf("[FNPTR:%p], ", *((gpointer
**) (curParm
)));
591 case MONO_TYPE_ARRAY
:
592 printf("[ARRAY:%p], ", *((gpointer
**) (curParm
)));
594 case MONO_TYPE_SZARRAY
:
595 printf("[SZARRAY:%p], ", *((gpointer
**) (curParm
)));
598 printf("[INT8:%lld], ", *((gint64
*) (curParm
)));
601 printf("[FLOAT4:%f], ", *((float *) (curParm
)));
604 printf("[FLOAT8:%g], ", *((double *) (curParm
)));
606 case MONO_TYPE_VALUETYPE
: {
608 if (type
->data
.klass
->enumtype
) {
609 simpleType
= type
->data
.klass
->enum_basetype
->type
;
610 printf("{VALUETYPE} - ");
613 printf("[VALUETYPE:");
614 for (i
= 0; i
< size
; i
++)
615 printf("%02x,", *((guint8
*)curParm
+i
));
620 printf("[?? - %d], ",simpleType
);
625 /*========================= End of Function ========================*/
627 /*------------------------------------------------------------------*/
629 /* Name - enter_method */
631 /* Function - Perform tracing of the entry to the current */
634 /*------------------------------------------------------------------*/
637 enter_method (MonoMethod
*method
, RegParm
*rParm
, char *sp
)
639 int i
, oParm
= 0, iParm
= 0;
642 MonoJitArgumentInfo
*arg_info
;
643 MonoMethodSignature
*sig
;
651 fname
= mono_method_full_name (method
, TRUE
);
653 printf ("ENTER: %s(", fname
);
656 ip
= (*(guint64
*) (sp
+S390_RET_ADDR_OFFSET
));
657 printf (") ip: %p sp: %p - ", ip
, sp
);
662 sig
= method
->signature
;
664 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
666 if (cinfo
->struct_ret
) {
667 printf ("[VALUERET:%p], ", rParm
->gr
[0]);
672 gpointer
*this = (gpointer
*) rParm
->gr
[iParm
];
673 obj
= (MonoObject
*) this;
674 if (method
->klass
->valuetype
) {
676 printf("this:[value:%p:%08x], ",
677 this, *((guint64
*)(this+sizeof(MonoObject
))));
679 printf ("this:[NULL], ");
682 class = obj
->vtable
->klass
;
683 if (class == mono_defaults
.string_class
) {
684 printf ("this:[STRING:%p:%s], ",
685 obj
, mono_string_to_utf8 ((MonoString
*)obj
));
687 printf ("this:%p[%s.%s], ",
688 obj
, class->name_space
, class->name
);
691 printf ("this:NULL, ");
696 for (i
= 0; i
< sig
->param_count
; ++i
) {
697 ainfo
= cinfo
->args
+ (i
+ oParm
);
698 switch (ainfo
->regtype
) {
699 case RegTypeGeneral
:
700 decodeParm(sig
->params
[i
], &(rParm
->gr
[ainfo
->reg
-2]), ainfo
->size
);
703 decodeParm(sig
->params
[i
], &(rParm
->fp
[ainfo
->reg
]), ainfo
->size
);
706 decodeParm(sig
->params
[i
], sp
+ainfo
->offset
, ainfo
->size
);
708 case RegTypeStructByVal
:
709 if (ainfo
->reg
!= STK_BASE
)
710 curParm
= &(rParm
->gr
[ainfo
->reg
-2]);
712 curParm
= sp
+ainfo
->offset
;
714 switch (ainfo
->vtsize
) {
720 decodeParm(sig
->params
[i
],
725 decodeParm(sig
->params
[i
],
726 *((char **) curParm
),
730 case RegTypeStructByAddr
:
731 if (ainfo
->reg
!= STK_BASE
)
732 curParm
= &(rParm
->gr
[ainfo
->reg
-2]);
734 curParm
= sp
+ainfo
->offset
;
736 decodeParm(sig
->params
[i
],
737 *((char **) curParm
),
749 /*========================= End of Function ========================*/
751 /*------------------------------------------------------------------*/
753 /* Name - leave_method */
757 /*------------------------------------------------------------------*/
760 leave_method (MonoMethod
*method
, ...)
767 va_start(ap
, method
);
769 fname
= mono_method_full_name (method
, TRUE
);
771 printf ("LEAVE: %s", fname
);
774 type
= method
->signature
->ret
;
777 switch (type
->type
) {
780 case MONO_TYPE_BOOLEAN
: {
781 int val
= va_arg (ap
, int);
783 printf ("[TRUE:%d]", val
);
789 case MONO_TYPE_CHAR
: {
790 int val
= va_arg (ap
, int);
791 printf ("[CHAR:%d]", val
);
795 int val
= va_arg (ap
, int);
796 printf ("[INT1:%d]", val
);
800 int val
= va_arg (ap
, int);
801 printf ("[UINT1:%d]", val
);
805 int val
= va_arg (ap
, int);
806 printf ("[INT2:%d]", val
);
810 int val
= va_arg (ap
, int);
811 printf ("[UINT2:%d]", val
);
815 int val
= va_arg (ap
, int);
816 printf ("[INT4:%d]", val
);
820 int val
= va_arg (ap
, int);
821 printf ("[UINT4:%d]", val
);
825 int *val
= va_arg (ap
, int*);
826 printf ("[INT:%d]", val
);
831 int *val
= va_arg (ap
, int*);
832 printf ("[UINT:%d]", val
);
836 case MONO_TYPE_STRING
: {
837 MonoString
*s
= va_arg (ap
, MonoString
*);
840 g_assert (((MonoObject
*)s
)->vtable
->klass
== mono_defaults
.string_class
);
841 printf ("[STRING:%p:%s]", s
, mono_string_to_utf8 (s
));
843 printf ("[STRING:null], ");
846 case MONO_TYPE_CLASS
:
847 case MONO_TYPE_OBJECT
: {
848 MonoObject
*o
= va_arg (ap
, MonoObject
*);
851 if (o
->vtable
->klass
== mono_defaults
.boolean_class
) {
852 printf ("[BOOLEAN:%p:%d]", o
, *((guint8
*)o
+ sizeof (MonoObject
)));
853 } else if (o
->vtable
->klass
== mono_defaults
.int32_class
) {
854 printf ("[INT32:%p:%d]", o
, *((gint32
*)((char *)o
+ sizeof (MonoObject
))));
855 } else if (o
->vtable
->klass
== mono_defaults
.int64_class
) {
856 printf ("[INT64:%p:%lld]", o
, *((gint64
*)((char *)o
+ sizeof (MonoObject
))));
858 printf ("[%s.%s:%p]", o
->vtable
->klass
->name_space
, o
->vtable
->klass
->name
, o
);
860 printf ("[OBJECT:%p]", o
);
865 case MONO_TYPE_FNPTR
:
866 case MONO_TYPE_ARRAY
:
867 case MONO_TYPE_SZARRAY
: {
868 gpointer p
= va_arg (ap
, gpointer
);
869 printf ("[result=%p]", p
);
873 gint64 l
= va_arg (ap
, gint64
);
874 printf ("[LONG:%lld]", l
);
878 double f
= va_arg (ap
, double);
879 printf ("[FLOAT4:%f]\n", (float) f
);
883 double f
= va_arg (ap
, double);
884 printf ("[FLOAT8:%g]\n", f
);
887 case MONO_TYPE_VALUETYPE
:
888 if (type
->data
.klass
->enumtype
) {
889 type
= type
->data
.klass
->enum_basetype
;
892 guint8
*p
= va_arg (ap
, gpointer
);
894 size
= mono_type_size (type
, &align
);
896 for (j
= 0; p
&& j
< size
; j
++)
897 printf ("%02x,", p
[j
]);
902 printf ("(unknown return type %x)",
903 method
->signature
->ret
->type
);
906 ip
= ((gint64
) __builtin_return_address (0));
907 printf (" ip: %p\n", ip
);
910 /*========================= End of Function ========================*/
912 /*------------------------------------------------------------------*/
914 /* Name - mono_arch_cpu_init */
916 /* Function - Perform CPU specific initialization to execute */
919 /*------------------------------------------------------------------*/
922 mono_arch_cpu_init (void)
926 /*--------------------------------------*/
927 /* Set default rounding mode for FP */
928 /*--------------------------------------*/
929 __asm__ ("SRNM\t%0\n\t"
933 /*========================= End of Function ========================*/
935 /*------------------------------------------------------------------*/
937 /* Name - mono_arch_cpu_optimizazions */
939 /* Function - Returns the optimizations supported on this CPU */
941 /*------------------------------------------------------------------*/
944 mono_arch_cpu_optimizazions (guint32
*exclude_mask
)
948 /* no s390-specific optimizations yet */
949 *exclude_mask
= MONO_OPT_INLINE
|MONO_OPT_LINEARS
;
953 /*========================= End of Function ========================*/
955 /*------------------------------------------------------------------*/
961 /*------------------------------------------------------------------*/
964 is_regsize_var (MonoType
*t
) {
973 case MONO_TYPE_OBJECT
:
974 case MONO_TYPE_STRING
:
975 case MONO_TYPE_CLASS
:
976 case MONO_TYPE_SZARRAY
:
977 case MONO_TYPE_ARRAY
:
979 case MONO_TYPE_VALUETYPE
:
980 if (t
->data
.klass
->enumtype
)
981 return is_regsize_var (t
->data
.klass
->enum_basetype
);
987 /*========================= End of Function ========================*/
989 /*------------------------------------------------------------------*/
991 /* Name - mono_arch_get_allocatable_int_vars */
995 /*------------------------------------------------------------------*/
998 mono_arch_get_allocatable_int_vars (MonoCompile
*cfg
)
1003 for (i
= 0; i
< cfg
->num_varinfo
; i
++) {
1004 MonoInst
*ins
= cfg
->varinfo
[i
];
1005 MonoMethodVar
*vmv
= MONO_VARINFO (cfg
, i
);
1008 if (vmv
->range
.first_use
.abs_pos
> vmv
->range
.last_use
.abs_pos
)
1011 if (ins
->flags
& (MONO_INST_VOLATILE
|MONO_INST_INDIRECT
) ||
1012 (ins
->opcode
!= OP_LOCAL
&& ins
->opcode
!= OP_ARG
))
1015 /* we can only allocate 32 bit values */
1016 if (is_regsize_var (ins
->inst_vtype
)) {
1017 g_assert (MONO_VARINFO (cfg
, i
)->reg
== -1);
1018 g_assert (i
== vmv
->idx
);
1019 vars
= mono_varlist_insert_sorted (cfg
, vars
, vmv
, FALSE
);
1026 /*========================= End of Function ========================*/
1028 /*------------------------------------------------------------------*/
1030 /* Name - mono_arch_global_int_regs */
1032 /* Function - Return a list of usable integer registers. */
1034 /*------------------------------------------------------------------*/
1037 mono_arch_get_global_int_regs (MonoCompile
*cfg
)
1042 for (i
= 3; i
< top
; ++i
)
1043 regs
= g_list_prepend (regs
, GUINT_TO_POINTER (i
));
1048 /*========================= End of Function ========================*/
1050 /*------------------------------------------------------------------*/
1052 /* Name - mono_arch_flush_icache */
1054 /* Function - Flush the CPU icache. */
1056 /*------------------------------------------------------------------*/
1059 mono_arch_flush_icache (guint8
*code
, gint size
)
1063 /*========================= End of Function ========================*/
1065 /*------------------------------------------------------------------*/
1067 /* Name - add_general */
1069 /* Function - Determine code and stack size incremements for a */
1072 /*------------------------------------------------------------------*/
1075 add_general (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
)
1077 if (*gr
> S390_LAST_ARG_REG
) {
1078 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1079 ainfo
->offset
= sz
->stack_size
;
1080 ainfo
->reg
= STK_BASE
;
1081 ainfo
->regtype
= RegTypeBase
;
1082 sz
->stack_size
+= sizeof(int);
1083 sz
->code_size
+= 12;
1091 /*========================= End of Function ========================*/
1093 /*------------------------------------------------------------------*/
1095 /* Name - calculate_sizes */
1097 /* Function - Determine the amount of space required for code */
1098 /* and stack. In addition determine starting points */
1099 /* for stack-based parameters, and area for struct- */
1100 /* ures being returned on the stack. */
1102 /*------------------------------------------------------------------*/
1105 calculate_sizes (MonoMethodSignature
*sig
, size_data
*sz
,
1106 gboolean string_ctor
)
1108 guint i
, fr
, gr
, size
, nWords
;
1109 int nParm
= sig
->hasthis
+ sig
->param_count
;
1110 guint32 simpletype
, align
;
1111 CallInfo
*cinfo
= g_malloc0 (sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1116 cinfo
->struct_ret
= 0;
1118 sz
->stack_size
= S390_MINIMAL_STACK_SIZE
;
1122 /*----------------------------------------------------------*/
1123 /* We determine the size of the return code/stack in case we*/
1124 /* need to reserve a register to be used to address a stack */
1125 /* area that the callee will use. */
1126 /*----------------------------------------------------------*/
1128 simpletype
= sig
->ret
->type
;
1130 switch (simpletype
) {
1131 case MONO_TYPE_BOOLEAN
:
1136 case MONO_TYPE_CHAR
:
1141 case MONO_TYPE_CLASS
:
1142 case MONO_TYPE_OBJECT
:
1143 case MONO_TYPE_SZARRAY
:
1144 case MONO_TYPE_ARRAY
:
1146 case MONO_TYPE_STRING
:
1147 cinfo
->ret
.reg
= s390_r2
;
1152 cinfo
->ret
.reg
= s390_f0
;
1157 cinfo
->ret
.reg
= s390_r2
;
1160 case MONO_TYPE_VALUETYPE
:
1161 if (sig
->ret
->data
.klass
->enumtype
) {
1162 simpletype
= sig
->ret
->data
.klass
->enum_basetype
->type
;
1166 size
= mono_class_native_size (sig
->ret
->data
.klass
, &align
);
1168 size
= mono_class_value_size (sig
->ret
->data
.klass
, &align
);
1169 cinfo
->ret
.reg
= s390_r2
;
1170 cinfo
->struct_ret
= 1;
1171 cinfo
->ret
.size
= size
;
1172 cinfo
->ret
.vtsize
= size
;
1173 cinfo
->ret
.offset
= sz
->stack_size
;
1174 sz
->stack_size
+= S390_ALIGN(size
, align
);
1177 case MONO_TYPE_TYPEDBYREF
:
1178 case MONO_TYPE_VOID
:
1181 g_error ("Can't handle as return value 0x%x", sig
->ret
->type
);
1185 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1186 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1190 /*----------------------------------------------------------*/
1191 /* We determine the size of the parameter code and stack */
1192 /* requirements by checking the types and sizes of the */
1194 /*----------------------------------------------------------*/
1196 for (i
= 0; i
< sig
->param_count
; ++i
) {
1197 if (sig
->params
[i
]->byref
) {
1198 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1199 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1203 simpletype
= sig
->params
[i
]->type
;
1205 switch (simpletype
) {
1206 case MONO_TYPE_BOOLEAN
:
1209 cinfo
->args
[nParm
].size
= sizeof(char);
1210 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1215 case MONO_TYPE_CHAR
:
1216 cinfo
->args
[nParm
].size
= sizeof(short);
1217 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1222 cinfo
->args
[nParm
].size
= sizeof(int);
1223 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1229 case MONO_TYPE_CLASS
:
1230 case MONO_TYPE_OBJECT
:
1231 case MONO_TYPE_STRING
:
1232 case MONO_TYPE_SZARRAY
:
1233 case MONO_TYPE_ARRAY
:
1234 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1235 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1238 case MONO_TYPE_VALUETYPE
:
1239 if (sig
->params
[i
]->data
.klass
->enumtype
) {
1240 simpletype
= sig
->params
[i
]->data
.klass
->enum_basetype
->type
;
1241 goto enum_calc_size
;
1244 size
= mono_class_native_size (sig
->params
[i
]->data
.klass
, &align
);
1246 size
= mono_class_value_size (sig
->params
[i
]->data
.klass
, &align
);
1247 nWords
= (size
+ sizeof(gpointer
) - 1) /
1250 cinfo
->args
[nParm
].vtsize
= 0;
1251 cinfo
->args
[nParm
].size
= 0;
1252 cinfo
->args
[nParm
].offparm
= sz
->local_size
;
1255 /*----------------------------------*/
1256 /* On S/390, structures of size 1, */
1257 /* 2, 4, and 8 bytes are passed in */
1258 /* (a) register(s). */
1259 /*----------------------------------*/
1264 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1265 cinfo
->args
[nParm
].size
= size
;
1266 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1268 sz
->local_size
+= sizeof(long);
1271 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1272 cinfo
->args
[nParm
].size
= sizeof(long long);
1273 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1275 sz
->local_size
+= sizeof(long);
1278 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1279 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1280 cinfo
->args
[nParm
].regtype
= RegTypeStructByAddr
;
1281 cinfo
->args
[nParm
].vtsize
= size
;
1282 sz
->code_size
+= 40;
1283 sz
->local_size
+= size
;
1284 if (cinfo
->args
[nParm
].reg
== STK_BASE
)
1285 sz
->local_size
+= sizeof(gpointer
);
1291 cinfo
->args
[nParm
].size
= sizeof(long long);
1292 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1296 cinfo
->args
[nParm
].size
= sizeof(float);
1297 if (fr
<= S390_LAST_FPARG_REG
) {
1298 cinfo
->args
[nParm
].regtype
= RegTypeFP
;
1299 cinfo
->args
[nParm
].reg
= fr
;
1304 cinfo
->args
[nParm
].offset
= sz
->stack_size
;
1305 cinfo
->args
[nParm
].reg
= STK_BASE
;
1306 cinfo
->args
[nParm
].regtype
= RegTypeBase
;
1308 sz
->stack_size
+= sizeof(float);
1313 cinfo
->args
[nParm
].size
= sizeof(double);
1314 if (fr
<= S390_LAST_FPARG_REG
) {
1315 cinfo
->args
[nParm
].regtype
= RegTypeFP
;
1316 cinfo
->args
[nParm
].reg
= fr
;
1320 cinfo
->args
[nParm
].offset
= sz
->stack_size
;
1321 cinfo
->args
[nParm
].reg
= STK_BASE
;
1322 cinfo
->args
[nParm
].regtype
= RegTypeBase
;
1324 sz
->stack_size
+= sizeof(double);
1329 g_error ("Can't trampoline 0x%x", sig
->params
[i
]->type
);
1333 cinfo
->stack_usage
= S390_ALIGN(sz
->stack_size
+sz
->local_size
,
1334 S390_STACK_ALIGNMENT
);
1338 /*========================= End of Function ========================*/
1340 /*------------------------------------------------------------------*/
1342 /* Name - mono_arch_allocate_vars */
1344 /* Function - Set var information according to the calling */
1345 /* convention for S/390. The local var stuff should */
1346 /* most likely be split in another method. */
1348 /* Parameter - @m - Compile unit. */
1350 /*------------------------------------------------------------------*/
1353 mono_arch_allocate_vars (MonoCompile
*m
)
1355 MonoMethodSignature
*sig
;
1356 MonoMethodHeader
*header
;
1360 int iParm
, iVar
, offset
, size
, align
, curinst
;
1361 int frame_reg
= STK_BASE
;
1364 header
= ((MonoMethodNormal
*)m
->method
)->header
;
1366 /*---------------------------------------------------------*/
1367 /* We use the frame register also for any method that has */
1368 /* filter clauses. This way, when the handlers are called, */
1369 /* the code will reference local variables using the frame */
1370 /* reg instead of the stack pointer: if we had to restore */
1371 /* the stack pointer, we'd corrupt the method frames that */
1372 /* are already on the stack (since filters get called */
1373 /* before stack unwinding happens) when the filter code */
1374 /* would call any method. */
1375 /*---------------------------------------------------------*/
1376 if ((m
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
1377 frame_reg
= s390_r11
;
1379 m
->frame_reg
= frame_reg
;
1381 if (frame_reg
!= STK_BASE
)
1382 m
->used_int_regs
|= 1 << frame_reg
;
1384 sig
= m
->method
->signature
;
1386 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
1388 if (cinfo
->struct_ret
) {
1389 m
->ret
->opcode
= OP_REGVAR
;
1390 m
->ret
->inst_c0
= s390_r2
;
1392 /* FIXME: handle long and FP values */
1393 switch (sig
->ret
->type
) {
1394 case MONO_TYPE_VOID
:
1397 m
->ret
->opcode
= OP_REGVAR
;
1398 m
->ret
->dreg
= s390_r2
;
1403 /*--------------------------------------------------------------*/
1404 /* local vars are at a positive offset from the stack pointer */
1406 /* also note that if the function uses alloca, we use s390_r11 */
1407 /* to point at the local variables. */
1408 /* add parameter area size for called functions */
1409 /*--------------------------------------------------------------*/
1410 offset
= (m
->param_area
+ S390_MINIMAL_STACK_SIZE
);
1412 if (cinfo
->struct_ret
) {
1414 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1415 inst
->inst_offset
= offset
;
1416 inst
->opcode
= OP_REGOFFSET
;
1417 inst
->inst_basereg
= frame_reg
;
1418 offset
+= sizeof(gpointer
);
1422 inst
= m
->varinfo
[0];
1423 if (inst
->opcode
!= OP_REGVAR
) {
1424 inst
->opcode
= OP_REGOFFSET
;
1425 inst
->inst_basereg
= frame_reg
;
1426 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1427 inst
->inst_offset
= offset
;
1428 offset
+= sizeof (gpointer
);
1435 eArg
= sig
->param_count
+ sArg
;
1437 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
1438 inst
= m
->varinfo
[curinst
];
1439 if (inst
->opcode
!= OP_REGVAR
) {
1440 switch (cinfo
->args
[iParm
].regtype
) {
1441 case RegTypeStructByAddr
:
1442 inst
->opcode
= OP_S390_LOADARG
;
1443 inst
->inst_basereg
= frame_reg
;
1444 size
= abs(cinfo
->args
[iParm
].vtsize
);
1445 offset
= S390_ALIGN(offset
, size
);
1446 inst
->inst_offset
= offset
;
1448 case RegTypeStructByVal
:
1449 inst
->opcode
= OP_S390_ARGPTR
;
1450 inst
->inst_basereg
= frame_reg
;
1451 size
= cinfo
->args
[iParm
].size
;
1452 offset
= S390_ALIGN(offset
, size
);
1453 inst
->inst_offset
= offset
;
1456 if (cinfo
->args
[iParm
].reg
!= STK_BASE
) {
1457 inst
->opcode
= OP_REGOFFSET
;
1458 inst
->inst_basereg
= frame_reg
;
1459 size
= (cinfo
->args
[iParm
].size
< 8
1461 : sizeof(long long));
1462 offset
= S390_ALIGN(offset
, size
);
1463 inst
->inst_offset
= offset
;
1465 inst
->opcode
= OP_S390_STKARG
;
1466 inst
->inst_basereg
= frame_reg
;
1467 size
= (cinfo
->args
[iParm
].size
< 4
1468 ? 4 - cinfo
->args
[iParm
].size
1470 inst
->inst_offset
= cinfo
->args
[iParm
].offset
+
1473 size
= sizeof(long);
1481 curinst
= m
->locals_start
;
1482 for (iVar
= curinst
; iVar
< m
->num_varinfo
; ++iVar
) {
1483 inst
= m
->varinfo
[iVar
];
1484 if (inst
->opcode
== OP_REGVAR
)
1487 /*--------------------------------------------------*/
1488 /* inst->unused indicates native sized value types, */
1489 /* this is used by the pinvoke wrappers when they */
1490 /* call functions returning structure */
1491 /*--------------------------------------------------*/
1492 if (inst
->unused
&& MONO_TYPE_ISSTRUCT (inst
->inst_vtype
))
1493 size
= mono_class_native_size (inst
->inst_vtype
->data
.klass
, &align
);
1495 size
= mono_type_size (inst
->inst_vtype
, &align
);
1497 offset
= S390_ALIGN(offset
, align
);
1498 inst
->inst_offset
= offset
;
1499 inst
->opcode
= OP_REGOFFSET
;
1500 inst
->inst_basereg
= frame_reg
;
1502 //DEBUG (g_print("allocating local %d to %d\n", iVar, inst->inst_offset));
1505 /*------------------------------------------------------*/
1506 /* Allow space for the trace method stack area if needed*/
1507 /*------------------------------------------------------*/
1508 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (m
))
1509 offset
+= S390_TRACE_STACK_SIZE
;
1511 /*------------------------------------------------------*/
1512 /* Reserve space to save LMF and caller saved registers */
1513 /*------------------------------------------------------*/
1514 if (m
->method
->save_lmf
)
1515 offset
+= sizeof (MonoLMF
);
1517 /*------------------------------------------------------*/
1518 /* align the offset */
1519 /*------------------------------------------------------*/
1520 m
->stack_offset
= S390_ALIGN(offset
, S390_STACK_ALIGNMENT
);
1525 /*========================= End of Function ========================*/
1527 /*------------------------------------------------------------------*/
1529 /* Name - mono_arch_call_opcode */
1531 /* Function - Take the arguments and generate the arch-specific */
1532 /* instructions to properly call the function. This */
1533 /* includes pushing, moving argments to the correct */
1536 /* Note - FIXME: We need an alignment solution for */
1537 /* enter_method and mono_arch_call_opcode, currently */
1538 /* alignment in mono_arch_call_opcode is computed */
1539 /* without arch_get_argument_info. */
1541 /*------------------------------------------------------------------*/
1544 mono_arch_call_opcode (MonoCompile
*cfg
, MonoBasicBlock
* bb
,
1545 MonoCallInst
*call
, int is_virtual
) {
1547 MonoMethodSignature
*sig
;
1548 int i
, n
, lParamArea
;
1553 sig
= call
->signature
;
1554 n
= sig
->param_count
+ sig
->hasthis
;
1555 DEBUG (g_print ("Call requires: %d parameters\n",n
));
1557 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
1559 call
->stack_usage
= cinfo
->stack_usage
;
1560 lParamArea
= cinfo
->stack_usage
- S390_MINIMAL_STACK_SIZE
;
1561 cfg
->param_area
= MAX (cfg
->param_area
, lParamArea
);
1562 cfg
->flags
|= MONO_CFG_HAS_CALLS
;
1564 if (cinfo
->struct_ret
)
1565 call
->used_iregs
|= 1 << cinfo
->struct_ret
;
1567 for (i
= 0; i
< n
; ++i
) {
1568 ainfo
= cinfo
->args
+ i
;
1569 DEBUG (g_print ("Parameter %d - Register: %d Type: %d\n",
1570 i
+1,ainfo
->reg
,ainfo
->regtype
));
1571 if (is_virtual
&& i
== 0) {
1572 /* the argument will be attached to the call instrucion */
1573 in
= call
->args
[i
];
1574 call
->used_iregs
|= 1 << ainfo
->reg
;
1576 MONO_INST_NEW (cfg
, arg
, OP_OUTARG
);
1577 in
= call
->args
[i
];
1578 arg
->cil_code
= in
->cil_code
;
1579 arg
->inst_left
= in
;
1580 arg
->type
= in
->type
;
1581 /* prepend, we'll need to reverse them later */
1582 arg
->next
= call
->out_args
;
1583 call
->out_args
= arg
;
1584 if (ainfo
->regtype
== RegTypeGeneral
) {
1585 arg
->unused
= ainfo
->reg
;
1586 call
->used_iregs
|= 1 << ainfo
->reg
;
1587 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
1588 call
->used_iregs
|= 1 << ainfo
->reg
;
1589 arg
->sreg1
= ainfo
->reg
;
1590 arg
->opcode
= OP_OUTARG_VT
;
1591 arg
->unused
= -ainfo
->vtsize
;
1592 arg
->inst_imm
= ainfo
->offset
;
1593 arg
->sreg2
= ainfo
->offparm
+ S390_MINIMAL_STACK_SIZE
;
1594 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
1595 if (ainfo
->reg
!= STK_BASE
) {
1596 call
->used_iregs
|= 1 << ainfo
->reg
;
1598 arg
->sreg1
= ainfo
->reg
;
1599 arg
->opcode
= OP_OUTARG_VT
;
1600 arg
->unused
= ainfo
->size
;
1601 arg
->inst_imm
= ainfo
->offset
;
1602 arg
->sreg2
= ainfo
->offparm
+ S390_MINIMAL_STACK_SIZE
;
1603 } else if (ainfo
->regtype
== RegTypeBase
) {
1604 arg
->opcode
= OP_OUTARG
;
1605 arg
->unused
= ainfo
->reg
| (ainfo
->size
<< 8);
1606 arg
->inst_imm
= ainfo
->offset
;
1607 call
->used_fregs
|= 1 << ainfo
->reg
;
1608 } else if (ainfo
->regtype
== RegTypeFP
) {
1609 arg
->unused
= ainfo
->reg
;
1610 call
->used_fregs
|= 1 << ainfo
->reg
;
1611 if (ainfo
->size
== 4) {
1613 arg
->opcode
= OP_OUTARG_R4
;
1614 MONO_INST_NEW (cfg
, conv
, OP_FCONV_TO_R4
);
1615 conv
->inst_left
= arg
->inst_left
;
1616 arg
->inst_left
= conv
;
1619 arg
->opcode
= OP_OUTARG_R8
;
1621 g_assert_not_reached ();
1626 * Reverse the call->out_args list.
1629 MonoInst
*prev
= NULL
, *list
= call
->out_args
, *next
;
1636 call
->out_args
= prev
;
1643 /*========================= End of Function ========================*/
1645 /*------------------------------------------------------------------*/
1647 /* Name - mono_arch_instrument_mem_needs */
1649 /* Function - Allow tracing to work with this interface (with */
1650 /* an optional argument). */
1652 /*------------------------------------------------------------------*/
1655 mono_arch_instrument_mem_needs (MonoMethod
*method
, int *stack
, int *code
)
1657 /* no stack room needed now (may be needed for FASTCALL-trace support) */
1659 /* split prolog-epilog requirements? */
1660 *code
= 50; /* max bytes needed: check this number */
1663 /*========================= End of Function ========================*/
1665 /*------------------------------------------------------------------*/
1667 /* Name - mono_arch_instrument_prolog */
1669 /* Function - Create an "instrumented" prolog. */
1671 /*------------------------------------------------------------------*/
1674 mono_arch_instrument_prolog (MonoCompile
*cfg
, void *func
, void *p
,
1675 gboolean enable_arguments
)
1681 parmOffset
= cfg
->stack_usage
- S390_TRACE_STACK_SIZE
;
1682 if (cfg
->method
->save_lmf
)
1683 parmOffset
-= sizeof(MonoLMF
);
1684 fpOffset
= parmOffset
+ (5*sizeof(long));
1686 s390_stmg (code
, s390_r2
, s390_r6
, STK_BASE
, parmOffset
);
1687 s390_std (code
, s390_f0
, 0, STK_BASE
, fpOffset
);
1688 s390_std (code
, s390_f1
, 0, STK_BASE
, fpOffset
+sizeof(gdouble
));
1689 s390_std (code
, s390_f2
, 0, STK_BASE
, fpOffset
+2*sizeof(gdouble
));
1690 s390_basr (code
, s390_r13
, 0);
1692 s390_llong(code
, cfg
->method
);
1693 s390_llong(code
, func
);
1694 s390_lg (code
, s390_r2
, 0, s390_r13
, 4);
1695 s390_la (code
, s390_r3
, 0, STK_BASE
, parmOffset
);
1696 s390_lgr (code
, s390_r4
, STK_BASE
);
1697 s390_aghi (code
, s390_r4
, cfg
->stack_usage
);
1698 s390_lg (code
, s390_r1
, 0, s390_r13
, 12);
1699 s390_basr (code
, s390_r14
, s390_r1
);
1700 s390_ld (code
, s390_f2
, 0, STK_BASE
, fpOffset
+2*sizeof(gdouble
));
1701 s390_ld (code
, s390_f1
, 0, STK_BASE
, fpOffset
+sizeof(gdouble
));
1702 s390_ld (code
, s390_f0
, 0, STK_BASE
, fpOffset
);
1703 s390_lmg (code
, s390_r2
, s390_r6
, STK_BASE
, parmOffset
);
1708 /*========================= End of Function ========================*/
1710 /*------------------------------------------------------------------*/
1712 /* Name - mono_arch_instrument_epilog */
1714 /* Function - Create an epilog that will handle the returned */
1715 /* values used in instrumentation. */
1717 /*------------------------------------------------------------------*/
1720 mono_arch_instrument_epilog (MonoCompile
*cfg
, void *func
, void *p
, gboolean enable_arguments
)
1723 int save_mode
= SAVE_NONE
,
1725 MonoMethod
*method
= cfg
->method
;
1726 int rtype
= method
->signature
->ret
->type
;
1728 saveOffset
= cfg
->stack_usage
- S390_TRACE_STACK_SIZE
;
1729 if (method
->save_lmf
)
1730 saveOffset
-= sizeof(MonoLMF
);
1734 case MONO_TYPE_VOID
:
1735 /* special case string .ctor icall */
1736 if (strcmp (".ctor", method
->name
) && method
->klass
== mono_defaults
.string_class
)
1737 save_mode
= SAVE_ONE
;
1739 save_mode
= SAVE_NONE
;
1743 save_mode
= SAVE_TWO
;
1747 save_mode
= SAVE_FP
;
1749 case MONO_TYPE_VALUETYPE
:
1750 if (method
->signature
->ret
->data
.klass
->enumtype
) {
1751 rtype
= method
->signature
->ret
->data
.klass
->enum_basetype
->type
;
1754 save_mode
= SAVE_STRUCT
;
1757 save_mode
= SAVE_ONE
;
1761 switch (save_mode
) {
1763 s390_stg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1764 if (enable_arguments
)
1765 s390_lgr (code
, s390_r3
, s390_r2
);
1768 s390_stg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1769 if (enable_arguments
)
1770 s390_lgr (code
, s390_r3
, s390_r2
);
1773 s390_std (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
1774 if (enable_arguments
) {
1775 /* FIXME: what reg? */
1776 s390_ldr (code
, s390_f2
, s390_f0
);
1777 s390_lg (code
, s390_r3
, 0, cfg
->frame_reg
, saveOffset
);
1781 s390_stg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1782 if (enable_arguments
)
1783 s390_lg (code
, s390_r3
, 0, cfg
->frame_reg
,
1784 S390_MINIMAL_STACK_SIZE
+cfg
->param_area
);
1791 s390_basr (code
, s390_r13
, 0);
1793 s390_llong(code
, cfg
->method
);
1794 s390_llong(code
, func
);
1795 s390_lg (code
, s390_r2
, 0, s390_r13
, 4);
1796 s390_lg (code
, s390_r1
, 0, s390_r13
, 12);
1797 s390_basr (code
, s390_r14
, s390_r1
);
1799 switch (save_mode
) {
1801 s390_lg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1804 s390_lg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1807 s390_ld (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
1810 s390_lg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
1820 /*========================= End of Function ========================*/
1822 /*------------------------------------------------------------------*/
1824 /* Name - peephole_pass */
1826 /* Function - Form a peephole pass at the code looking for */
1827 /* simple optimizations. */
1829 /*------------------------------------------------------------------*/
1832 peephole_pass (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
1834 MonoInst
*ins
, *last_ins
= NULL
;
1839 switch (ins
->opcode
) {
1841 /* remove unnecessary multiplication with 1 */
1842 if (ins
->inst_imm
== 1) {
1843 if (ins
->dreg
!= ins
->sreg1
) {
1844 ins
->opcode
= OP_MOVE
;
1846 last_ins
->next
= ins
->next
;
1852 case OP_LOAD_MEMBASE
:
1853 case OP_LOADI4_MEMBASE
:
1855 * OP_STORE_MEMBASE_REG reg, offset(basereg)
1856 * OP_LOAD_MEMBASE offset(basereg), reg
1858 if (last_ins
&& (last_ins
->opcode
== OP_STOREI4_MEMBASE_REG
1859 || last_ins
->opcode
== OP_STORE_MEMBASE_REG
) &&
1860 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1861 ins
->inst_offset
== last_ins
->inst_offset
) {
1862 if (ins
->dreg
== last_ins
->sreg1
) {
1863 last_ins
->next
= ins
->next
;
1867 //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++);
1868 ins
->opcode
= OP_MOVE
;
1869 ins
->sreg1
= last_ins
->sreg1
;
1873 * Note: reg1 must be different from the basereg in the second load
1874 * OP_LOAD_MEMBASE offset(basereg), reg1
1875 * OP_LOAD_MEMBASE offset(basereg), reg2
1877 * OP_LOAD_MEMBASE offset(basereg), reg1
1878 * OP_MOVE reg1, reg2
1880 } if (last_ins
&& (last_ins
->opcode
== OP_LOADI4_MEMBASE
1881 || last_ins
->opcode
== OP_LOAD_MEMBASE
) &&
1882 ins
->inst_basereg
!= last_ins
->dreg
&&
1883 ins
->inst_basereg
== last_ins
->inst_basereg
&&
1884 ins
->inst_offset
== last_ins
->inst_offset
) {
1886 if (ins
->dreg
== last_ins
->dreg
) {
1887 last_ins
->next
= ins
->next
;
1891 ins
->opcode
= OP_MOVE
;
1892 ins
->sreg1
= last_ins
->dreg
;
1896 case OP_LOADU1_MEMBASE
:
1897 case OP_LOADI1_MEMBASE
:
1898 if (last_ins
&& (last_ins
->opcode
== OP_STOREI1_MEMBASE_REG
) &&
1899 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1900 ins
->inst_offset
== last_ins
->inst_offset
) {
1901 if (ins
->dreg
== last_ins
->sreg1
) {
1902 last_ins
->next
= ins
->next
;
1906 ins
->opcode
= OP_MOVE
;
1907 ins
->sreg1
= last_ins
->sreg1
;
1911 case OP_LOADU2_MEMBASE
:
1912 case OP_LOADI2_MEMBASE
:
1913 if (last_ins
&& (last_ins
->opcode
== OP_STOREI2_MEMBASE_REG
) &&
1914 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
1915 ins
->inst_offset
== last_ins
->inst_offset
) {
1916 if (ins
->dreg
== last_ins
->sreg1
) {
1917 last_ins
->next
= ins
->next
;
1921 ins
->opcode
= OP_MOVE
;
1922 ins
->sreg1
= last_ins
->sreg1
;
1932 if (ins
->dreg
== ins
->sreg1
) {
1934 last_ins
->next
= ins
->next
;
1939 * OP_MOVE sreg, dreg
1940 * OP_MOVE dreg, sreg
1942 if (last_ins
&& last_ins
->opcode
== OP_MOVE
&&
1943 ins
->sreg1
== last_ins
->dreg
&&
1944 ins
->dreg
== last_ins
->sreg1
) {
1945 last_ins
->next
= ins
->next
;
1954 bb
->last_ins
= last_ins
;
1957 /*========================= End of Function ========================*/
1959 /*------------------------------------------------------------------*/
1961 /* Name - mono_spillvar_offset */
1963 /* Function - Returns the offset used by spillvar. It allocates */
1964 /* a new spill variable if necessary. */
1966 /*------------------------------------------------------------------*/
1969 mono_spillvar_offset (MonoCompile
*cfg
, int spillvar
)
1971 MonoSpillInfo
**si
, *info
;
1974 si
= &cfg
->spill_info
;
1976 while (i
<= spillvar
) {
1979 *si
= info
= mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSpillInfo
));
1981 info
->offset
= cfg
->stack_offset
;
1982 cfg
->stack_offset
+= sizeof (gpointer
);
1986 return (*si
)->offset
;
1992 g_assert_not_reached ();
1996 /*========================= End of Function ========================*/
1998 /*------------------------------------------------------------------*/
2000 /* Name - mono_spillvar_offset_float */
2004 /*------------------------------------------------------------------*/
2007 mono_spillvar_offset_float (MonoCompile
*cfg
, int spillvar
)
2009 MonoSpillInfo
**si
, *info
;
2012 si
= &cfg
->spill_info_float
;
2014 while (i
<= spillvar
) {
2017 *si
= info
= mono_mempool_alloc (cfg
->mempool
, sizeof (MonoSpillInfo
));
2019 cfg
->stack_offset
= S390_ALIGN(cfg
->stack_offset
, S390_STACK_ALIGNMENT
);
2020 info
->offset
= cfg
->stack_offset
;
2021 cfg
->stack_offset
+= sizeof (double);
2025 return (*si
)->offset
;
2031 g_assert_not_reached ();
2035 /*========================= End of Function ========================*/
2037 /*------------------------------------------------------------------*/
2039 /* Name - print_ins */
2041 /* Function - Decode and print the instruction for tracing. */
2043 /*------------------------------------------------------------------*/
2046 print_ins (int i
, MonoInst
*ins
)
2048 const char *spec
= ins_spec
[ins
->opcode
];
2049 g_print ("\t%-2d %s", i
, mono_inst_name (ins
->opcode
));
2050 if (spec
[MONO_INST_DEST
]) {
2051 if (ins
->dreg
>= MONO_MAX_IREGS
)
2052 g_print (" R%d <-", ins
->dreg
);
2054 g_print (" %s <-", mono_arch_regname (ins
->dreg
));
2056 if (spec
[MONO_INST_SRC1
]) {
2057 if (ins
->sreg1
>= MONO_MAX_IREGS
)
2058 g_print (" R%d", ins
->sreg1
);
2060 g_print (" %s", mono_arch_regname (ins
->sreg1
));
2062 if (spec
[MONO_INST_SRC2
]) {
2063 if (ins
->sreg2
>= MONO_MAX_IREGS
)
2064 g_print (" R%d", ins
->sreg2
);
2066 g_print (" %s", mono_arch_regname (ins
->sreg2
));
2068 if (spec
[MONO_INST_CLOB
])
2069 g_print (" clobbers: %c", spec
[MONO_INST_CLOB
]);
2073 /*========================= End of Function ========================*/
2075 /*------------------------------------------------------------------*/
2077 /* Name - print_regtrack. */
2081 /*------------------------------------------------------------------*/
2084 print_regtrack (RegTrack
*t
, int num
)
2090 for (i
= 0; i
< num
; ++i
) {
2093 if (i
>= MONO_MAX_IREGS
) {
2094 g_snprintf (buf
, sizeof(buf
), "R%d", i
);
2097 r
= mono_arch_regname (i
);
2098 g_print ("liveness: %s [%d - %d]\n", r
, t
[i
].born_in
, t
[i
].last_use
);
2102 /*========================= End of Function ========================*/
2104 /*------------------------------------------------------------------*/
2106 /* Name - inst_list_prepend */
2108 /* Function - Prepend an instruction to the list. */
2110 /*------------------------------------------------------------------*/
2112 static inline InstList
*
2113 inst_list_prepend (MonoMemPool
*pool
, InstList
*list
, MonoInst
*data
)
2115 InstList
*item
= mono_mempool_alloc (pool
, sizeof (InstList
));
2124 /*========================= End of Function ========================*/
2126 /*------------------------------------------------------------------*/
2128 /* Name - get_register_force_spilling */
2130 /* Function - Force the spilling of the variable in the */
2131 /* symbolic register 'reg'. */
2133 /*------------------------------------------------------------------*/
2136 get_register_force_spilling (MonoCompile
*cfg
, InstList
*item
, MonoInst
*ins
, int reg
)
2141 sel
= cfg
->rs
->iassign
[reg
];
2143 spill
= ++cfg
->spill_count
;
2144 cfg
->rs
->iassign
[i
] = -spill
- 1;
2145 mono_regstate_free_int (cfg
->rs
, sel
);
2146 /*----------------------------------------------------------*/
2147 /* we need to create a spill var and insert a load to sel */
2148 /* after the current instruction */
2149 /*----------------------------------------------------------*/
2150 MONO_INST_NEW (cfg
, load
, OP_LOAD_MEMBASE
);
2152 load
->inst_basereg
= cfg
->frame_reg
;
2153 load
->inst_offset
= mono_spillvar_offset (cfg
, spill
);
2155 while (ins
->next
!= item
->prev
->data
)
2158 load
->next
= ins
->next
;
2160 DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n",
2161 spill
, load
->inst_offset
, i
, mono_arch_regname (sel
)));
2162 i
= mono_regstate_alloc_int (cfg
->rs
, 1 << sel
);
2163 g_assert (i
== sel
);
2168 /*========================= End of Function ========================*/
2170 /*------------------------------------------------------------------*/
2172 /* Name - get_register_spilling */
2176 /*------------------------------------------------------------------*/
2179 get_register_spilling (MonoCompile
*cfg
, InstList
*item
, MonoInst
*ins
, guint32 regmask
, int reg
)
2184 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
));
2185 /* exclude the registers in the current instruction */
2186 if (reg
!= ins
->sreg1
&&
2187 (reg_is_freeable (ins
->sreg1
) ||
2188 (ins
->sreg1
>= MONO_MAX_IREGS
&&
2189 cfg
->rs
->iassign
[ins
->sreg1
] >= 0))) {
2190 if (ins
->sreg1
>= MONO_MAX_IREGS
)
2191 regmask
&= ~ (1 << cfg
->rs
->iassign
[ins
->sreg1
]);
2193 regmask
&= ~ (1 << ins
->sreg1
);
2194 DEBUG (g_print ("excluding sreg1 %s\n", mono_arch_regname (ins
->sreg1
)));
2196 if (reg
!= ins
->sreg2
&&
2197 (reg_is_freeable (ins
->sreg2
) ||
2198 (ins
->sreg2
>= MONO_MAX_IREGS
&&
2199 cfg
->rs
->iassign
[ins
->sreg2
] >= 0))) {
2200 if (ins
->sreg2
>= MONO_MAX_IREGS
)
2201 regmask
&= ~ (1 << cfg
->rs
->iassign
[ins
->sreg2
]);
2203 regmask
&= ~ (1 << ins
->sreg2
);
2204 DEBUG (g_print ("excluding sreg2 %s %d\n", mono_arch_regname (ins
->sreg2
), ins
->sreg2
));
2206 if (reg
!= ins
->dreg
&& reg_is_freeable (ins
->dreg
)) {
2207 regmask
&= ~ (1 << ins
->dreg
);
2208 DEBUG (g_print ("excluding dreg %s\n", mono_arch_regname (ins
->dreg
)));
2211 DEBUG (g_print ("available regmask: 0x%08x\n", regmask
));
2212 g_assert (regmask
); /* need at least a register we can free */
2214 /* we should track prev_use and spill the register that's farther */
2215 for (i
= 0; i
< MONO_MAX_IREGS
; ++i
) {
2216 if (regmask
& (1 << i
)) {
2218 DEBUG (g_print ("selected register %s has assignment %d\n", mono_arch_regname (sel
), cfg
->rs
->iassign
[sel
]));
2222 i
= cfg
->rs
->isymbolic
[sel
];
2223 spill
= ++cfg
->spill_count
;
2224 cfg
->rs
->iassign
[i
] = -spill
- 1;
2225 mono_regstate_free_int (cfg
->rs
, sel
);
2226 /* we need to create a spill var and insert a load to sel after the current instruction */
2227 MONO_INST_NEW (cfg
, load
, OP_LOAD_MEMBASE
);
2229 load
->inst_basereg
= cfg
->frame_reg
;
2230 load
->inst_offset
= mono_spillvar_offset (cfg
, spill
);
2232 while (ins
->next
!= item
->prev
->data
)
2235 load
->next
= ins
->next
;
2237 DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", spill
, load
->inst_offset
, i
, mono_arch_regname (sel
)));
2238 i
= mono_regstate_alloc_int (cfg
->rs
, 1 << sel
);
2239 g_assert (i
== sel
);
2244 /*========================= End of Function ========================*/
2246 /*------------------------------------------------------------------*/
2248 /* Name - get_float_register_spilling */
2252 /*------------------------------------------------------------------*/
2255 get_float_register_spilling (MonoCompile
*cfg
, InstList
*item
, MonoInst
*ins
, guint32 regmask
, int reg
)
2260 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
));
2261 /* exclude the registers in the current instruction */
2262 if (reg
!= ins
->sreg1
&&
2263 (freg_is_freeable (ins
->sreg1
) ||
2264 (ins
->sreg1
>= MONO_MAX_FREGS
&&
2265 cfg
->rs
->fassign
[ins
->sreg1
] >= 0))) {
2266 if (ins
->sreg1
>= MONO_MAX_FREGS
)
2267 regmask
&= ~ (1 << cfg
->rs
->fassign
[ins
->sreg1
]);
2269 regmask
&= ~ (1 << ins
->sreg1
);
2270 DEBUG (g_print ("excluding sreg1 %s\n", mono_arch_regname (ins
->sreg1
)));
2272 if (reg
!= ins
->sreg2
&&
2273 (freg_is_freeable (ins
->sreg2
) ||
2274 (ins
->sreg2
>= MONO_MAX_FREGS
&&
2275 cfg
->rs
->fassign
[ins
->sreg2
] >= 0))) {
2276 if (ins
->sreg2
>= MONO_MAX_FREGS
)
2277 regmask
&= ~ (1 << cfg
->rs
->fassign
[ins
->sreg2
]);
2279 regmask
&= ~ (1 << ins
->sreg2
);
2280 DEBUG (g_print ("excluding sreg2 %s %d\n", mono_arch_regname (ins
->sreg2
), ins
->sreg2
));
2282 if (reg
!= ins
->dreg
&& freg_is_freeable (ins
->dreg
)) {
2283 regmask
&= ~ (1 << ins
->dreg
);
2284 DEBUG (g_print ("excluding dreg %s\n", mono_arch_regname (ins
->dreg
)));
2287 DEBUG (g_print ("available regmask: 0x%08x\n", regmask
));
2288 g_assert (regmask
); /* need at least a register we can free */
2290 /* we should track prev_use and spill the register that's farther */
2291 for (i
= 0; i
< MONO_MAX_FREGS
; ++i
) {
2292 if (regmask
& (1 << i
)) {
2294 DEBUG (g_print ("selected register %s has assignment %d\n",
2295 mono_arch_regname (sel
), cfg
->rs
->fassign
[sel
]));
2299 i
= cfg
->rs
->fsymbolic
[sel
];
2300 spill
= ++cfg
->spill_count
;
2301 cfg
->rs
->fassign
[i
] = -spill
- 1;
2302 mono_regstate_free_float(cfg
->rs
, sel
);
2303 /* we need to create a spill var and insert a load to sel after the current instruction */
2304 MONO_INST_NEW (cfg
, load
, OP_LOADR8_MEMBASE
);
2306 load
->inst_basereg
= cfg
->frame_reg
;
2307 load
->inst_offset
= mono_spillvar_offset_float (cfg
, spill
);
2309 while (ins
->next
!= item
->prev
->data
)
2312 load
->next
= ins
->next
;
2314 DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", spill
, load
->inst_offset
, i
, mono_arch_regname (sel
)));
2315 i
= mono_regstate_alloc_float (cfg
->rs
, 1 << sel
);
2316 g_assert (i
== sel
);
2321 /*========================= End of Function ========================*/
2323 /*------------------------------------------------------------------*/
2325 /* Name - create_copy_ins */
2327 /* Function - Create an instruction to copy from reg to reg. */
2329 /*------------------------------------------------------------------*/
2332 create_copy_ins (MonoCompile
*cfg
, int dest
, int src
, MonoInst
*ins
)
2335 MONO_INST_NEW (cfg
, copy
, OP_MOVE
);
2339 copy
->next
= ins
->next
;
2342 DEBUG (g_print ("\tforced copy from %s to %s\n",
2343 mono_arch_regname (src
), mono_arch_regname (dest
)));
2347 /*========================= End of Function ========================*/
2349 /*------------------------------------------------------------------*/
2351 /* Name - create_copy_ins_float */
2353 /* Function - Create an instruction to copy from float reg to */
2356 /*------------------------------------------------------------------*/
2359 create_copy_ins_float (MonoCompile
*cfg
, int dest
, int src
, MonoInst
*ins
)
2362 MONO_INST_NEW (cfg
, copy
, OP_FMOVE
);
2366 copy
->next
= ins
->next
;
2369 DEBUG (g_print ("\tforced copy from %s to %s\n",
2370 mono_arch_regname (src
), mono_arch_regname (dest
)));
2374 /*========================= End of Function ========================*/
2376 /*------------------------------------------------------------------*/
2378 /* Name - create_spilled_store */
2380 /* Function - Spill register to storage. */
2382 /*------------------------------------------------------------------*/
2385 create_spilled_store (MonoCompile
*cfg
, int spill
, int reg
, int prev_reg
, MonoInst
*ins
)
2388 MONO_INST_NEW (cfg
, store
, OP_STORE_MEMBASE_REG
);
2390 store
->inst_destbasereg
= cfg
->frame_reg
;
2391 store
->inst_offset
= mono_spillvar_offset (cfg
, spill
);
2393 store
->next
= ins
->next
;
2396 DEBUG (g_print ("SPILLED STORE (%d at 0x%08x(%%sp)) R%d (from %s)\n",
2397 spill
, store
->inst_offset
, prev_reg
, mono_arch_regname (reg
)));
2401 /*========================= End of Function ========================*/
2403 /*------------------------------------------------------------------*/
2405 /* Name - create_spilled_store_float */
2407 /* Function - Spill floating point register to storage. */
2409 /*------------------------------------------------------------------*/
2412 create_spilled_store_float (MonoCompile
*cfg
, int spill
, int reg
, int prev_reg
, MonoInst
*ins
)
2415 MONO_INST_NEW (cfg
, store
, OP_STORER8_MEMBASE_REG
);
2417 store
->inst_destbasereg
= cfg
->frame_reg
;
2418 store
->inst_offset
= mono_spillvar_offset_float (cfg
, spill
);
2420 store
->next
= ins
->next
;
2423 DEBUG (g_print ("SPILLED STORE (%d at 0x%08x(%%sp)) R%d (from %s)\n",
2424 spill
, store
->inst_offset
, prev_reg
, mono_arch_regname (reg
)));
2428 /*========================= End of Function ========================*/
2430 /*------------------------------------------------------------------*/
2432 /* Name - insert_before_ins */
2434 /* Function - Insert an instruction before another. */
2436 /*------------------------------------------------------------------*/
2439 insert_before_ins (MonoInst
*ins
, InstList
*item
, MonoInst
* to_insert
)
2442 g_assert (item
->next
);
2443 prev
= item
->next
->data
;
2445 while (prev
->next
!= ins
)
2447 to_insert
->next
= ins
;
2448 prev
->next
= to_insert
;
2450 * needed otherwise in the next instruction we can add an ins to the
2451 * end and that would get past this instruction.
2453 item
->data
= to_insert
;
2456 /*========================= End of Function ========================*/
2458 /*------------------------------------------------------------------*/
2460 /* Name - alloc_int_reg */
2462 /* Function - Allocate a general register. */
2464 /*------------------------------------------------------------------*/
2467 alloc_int_reg (MonoCompile
*cfg
, InstList
*curinst
, MonoInst
*ins
, int sym_reg
, guint32 allow_mask
)
2469 int val
= cfg
->rs
->iassign
[sym_reg
];
2470 DEBUG (g_print ("Allocating a general register for %d (%d) with mask %08x\n",val
,sym_reg
,allow_mask
));
2474 /* the register gets spilled after this inst */
2477 val
= mono_regstate_alloc_int (cfg
->rs
, allow_mask
);
2479 val
= get_register_spilling (cfg
, curinst
, ins
, allow_mask
, sym_reg
);
2480 cfg
->rs
->iassign
[sym_reg
] = val
;
2481 /* add option to store before the instruction for src registers */
2483 create_spilled_store (cfg
, spill
, val
, sym_reg
, ins
);
2485 DEBUG (g_print ("Allocated %d for %d\n",val
,sym_reg
));
2486 cfg
->rs
->isymbolic
[val
] = sym_reg
;
2490 /*========================= End of Function ========================*/
2492 /*------------------------------------------------------------------*/
2494 /* Name - mono_arch_local_regalloc. */
2496 /* Function - We first scan the list of instructions and we */
2497 /* save the liveness information of each register */
2498 /* (when the register is first used, when its value */
2499 /* is set etc.). We also reverse the list of instr- */
2500 /* uctions (in the InstList list) because assigning */
2501 /* registers backwards allows for more tricks to be */
2504 /*------------------------------------------------------------------*/
2507 mono_arch_local_regalloc (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2510 MonoRegState
*rs
= cfg
->rs
;
2512 RegTrack
*reginfo
, *reginfof
;
2513 RegTrack
*reginfo1
, *reginfo2
, *reginfod
;
2514 InstList
*tmp
, *reversed
= NULL
;
2516 guint32 src1_mask
, src2_mask
, dest_mask
;
2517 guint32 cur_iregs
, cur_fregs
;
2521 rs
->next_vireg
= bb
->max_ireg
;
2522 rs
->next_vfreg
= bb
->max_freg
;
2523 mono_regstate_assign (rs
);
2524 reginfo
= mono_mempool_alloc0 (cfg
->mempool
, sizeof (RegTrack
) * rs
->next_vireg
);
2525 reginfof
= mono_mempool_alloc0 (cfg
->mempool
, sizeof (RegTrack
) * rs
->next_vfreg
);
2526 rs
->ifree_mask
= S390_CALLER_REGS
;
2527 rs
->ffree_mask
= S390_CALLER_FREGS
;
2531 DEBUG (g_print ("LOCAL regalloc: basic block: %d\n", bb
->block_num
));
2532 /* forward pass on the instructions to collect register liveness info */
2534 spec
= ins_spec
[ins
->opcode
];
2535 DEBUG (print_ins (i
, ins
));
2536 if (spec
[MONO_INST_CLOB
] == 'c') {
2537 MonoCallInst
* call
= (MonoCallInst
*)ins
;
2540 if (spec
[MONO_INST_SRC1
]) {
2541 if (spec
[MONO_INST_SRC1
] == 'f')
2542 reginfo1
= reginfof
;
2545 reginfo1
[ins
->sreg1
].prev_use
= reginfo1
[ins
->sreg1
].last_use
;
2546 reginfo1
[ins
->sreg1
].last_use
= i
;
2550 if (spec
[MONO_INST_SRC2
]) {
2551 if (spec
[MONO_INST_SRC2
] == 'f')
2552 reginfo2
= reginfof
;
2555 reginfo2
[ins
->sreg2
].prev_use
= reginfo2
[ins
->sreg2
].last_use
;
2556 reginfo2
[ins
->sreg2
].last_use
= i
;
2560 if (spec
[MONO_INST_DEST
]) {
2561 if (spec
[MONO_INST_DEST
] == 'f')
2562 reginfod
= reginfof
;
2565 if (spec
[MONO_INST_DEST
] != 'b') /* it's not just a base register */
2566 reginfod
[ins
->dreg
].killed_in
= i
;
2567 reginfod
[ins
->dreg
].prev_use
= reginfod
[ins
->dreg
].last_use
;
2568 reginfod
[ins
->dreg
].last_use
= i
;
2569 if (reginfod
[ins
->dreg
].born_in
== 0 || reginfod
[ins
->dreg
].born_in
> i
)
2570 reginfod
[ins
->dreg
].born_in
= i
;
2571 if (spec
[MONO_INST_DEST
] == 'l') {
2572 /* result in eax:edx, the virtual register is allocated sequentially */
2573 reginfod
[ins
->dreg
+ 1].prev_use
= reginfod
[ins
->dreg
+ 1].last_use
;
2574 reginfod
[ins
->dreg
+ 1].last_use
= i
;
2575 if (reginfod
[ins
->dreg
+ 1].born_in
== 0 || reginfod
[ins
->dreg
+ 1].born_in
> i
)
2576 reginfod
[ins
->dreg
+ 1].born_in
= i
;
2581 reversed
= inst_list_prepend (cfg
->mempool
, reversed
, ins
);
2586 cur_iregs
= S390_CALLER_REGS
;
2587 cur_fregs
= S390_CALLER_FREGS
;
2589 DEBUG (print_regtrack (reginfo
, rs
->next_vireg
));
2590 DEBUG (print_regtrack (reginfof
, rs
->next_vfreg
));
2593 int prev_dreg
, prev_sreg1
, prev_sreg2
;
2596 spec
= ins_spec
[ins
->opcode
];
2597 DEBUG (g_print ("processing:"));
2598 DEBUG (print_ins (i
, ins
));
2599 /* make the register available for allocation: FIXME add fp reg */
2600 if (ins
->opcode
== OP_SETREG
|| ins
->opcode
== OP_SETREGIMM
) {
2601 cur_iregs
|= 1 << ins
->dreg
;
2602 DEBUG (g_print ("adding %d to cur_iregs\n", ins
->dreg
));
2603 } else if (ins
->opcode
== OP_SETFREG
) {
2604 cur_fregs
|= 1 << ins
->dreg
;
2605 DEBUG (g_print ("adding %d to cur_fregs\n", ins
->dreg
));
2606 } else if (spec
[MONO_INST_CLOB
] == 'c') {
2607 MonoCallInst
*cinst
= (MonoCallInst
*)ins
;
2608 DEBUG (g_print ("excluding regs 0x%x from cur_iregs (0x%x)\n",
2609 cinst
->used_iregs
, cur_iregs
));
2610 DEBUG (g_print ("excluding fpregs 0x%x from cur_fregs (0x%x)\n",
2611 cinst
->used_fregs
, cur_fregs
));
2612 cur_iregs
&= ~cinst
->used_iregs
;
2613 cur_fregs
&= ~cinst
->used_fregs
;
2614 DEBUG (g_print ("available cur_iregs: 0x%x\n", cur_iregs
));
2615 DEBUG (g_print ("available cur_fregs: 0x%x\n", cur_fregs
));
2616 /*------------------------------------------------------------*/
2617 /* registers used by the calling convention are excluded from */
2618 /* allocation: they will be selectively enabled when they are */
2619 /* assigned by the special SETREG opcodes. */
2620 /*------------------------------------------------------------*/
2622 dest_mask
= src1_mask
= src2_mask
= cur_iregs
;
2623 /*------------------------------------------------------*/
2624 /* update for use with FP regs... */
2625 /*------------------------------------------------------*/
2626 if (spec
[MONO_INST_DEST
] == 'f') {
2627 dest_mask
= cur_fregs
;
2628 if (ins
->dreg
>= MONO_MAX_FREGS
) {
2629 val
= rs
->fassign
[ins
->dreg
];
2630 prev_dreg
= ins
->dreg
;
2634 /* the register gets spilled after this inst */
2637 val
= mono_regstate_alloc_float (rs
, dest_mask
);
2639 val
= get_float_register_spilling (cfg
, tmp
, ins
, dest_mask
, ins
->dreg
);
2640 rs
->fassign
[ins
->dreg
] = val
;
2642 create_spilled_store_float (cfg
, spill
, val
, prev_dreg
, ins
);
2644 DEBUG (g_print ("\tassigned dreg %s to dest R%d\n",
2645 mono_arch_regname (val
), ins
->dreg
));
2646 rs
->fsymbolic
[val
] = prev_dreg
;
2648 if (spec
[MONO_INST_CLOB
] == 'c' && ins
->dreg
!= s390_f0
) {
2649 /* this instruction only outputs to s390_f0, need to copy */
2650 create_copy_ins_float (cfg
, ins
->dreg
, s390_f0
, ins
);
2655 if (freg_is_freeable (ins
->dreg
) && prev_dreg
>= 0 && (reginfof
[prev_dreg
].born_in
>= i
|| !(cur_fregs
& (1 << ins
->dreg
)))) {
2656 DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins
->dreg
), prev_dreg
, reginfo
[prev_dreg
].born_in
));
2657 mono_regstate_free_float (rs
, ins
->dreg
);
2659 } else if (ins
->dreg
>= MONO_MAX_IREGS
) {
2660 val
= rs
->iassign
[ins
->dreg
];
2661 prev_dreg
= ins
->dreg
;
2665 /* the register gets spilled after this inst */
2668 val
= mono_regstate_alloc_int (rs
, dest_mask
);
2670 val
= get_register_spilling (cfg
, tmp
, ins
, dest_mask
, ins
->dreg
);
2671 rs
->iassign
[ins
->dreg
] = val
;
2673 create_spilled_store (cfg
, spill
, val
, prev_dreg
, ins
);
2675 DEBUG (g_print ("\tassigned dreg %s to dest R%d (prev: R%d)\n",
2676 mono_arch_regname (val
), ins
->dreg
, prev_dreg
));
2677 rs
->isymbolic
[val
] = prev_dreg
;
2679 if (spec
[MONO_INST_DEST
] == 'l') {
2680 int hreg
= prev_dreg
+ 1;
2681 val
= rs
->iassign
[hreg
];
2685 /* the register gets spilled after this inst */
2688 val
= mono_regstate_alloc_int (rs
, dest_mask
);
2690 val
= get_register_spilling (cfg
, tmp
, ins
, dest_mask
, hreg
);
2691 rs
->iassign
[hreg
] = val
;
2693 create_spilled_store (cfg
, spill
, val
, hreg
, ins
);
2695 DEBUG (g_print ("\tassigned hreg %s to dest R%d\n", mono_arch_regname (val
), hreg
));
2696 rs
->isymbolic
[val
] = hreg
;
2698 /* FIXME:? ins->dreg = val; */
2699 if (ins
->dreg
== s390_r3
) {
2701 create_copy_ins (cfg
, val
, s390_r2
, ins
);
2702 } else if (ins
->dreg
== s390_r2
) {
2703 if (val
== s390_r3
) {
2705 create_copy_ins (cfg
, s390_r3
, s390_r0
, ins
);
2706 create_copy_ins (cfg
, s390_r2
, s390_r3
, ins
);
2707 create_copy_ins (cfg
, s390_r0
, s390_r2
, ins
);
2709 /* two forced copies */
2710 create_copy_ins (cfg
, ins
->dreg
, s390_r3
, ins
);
2711 create_copy_ins (cfg
, val
, s390_r2
, ins
);
2714 if (val
== s390_r2
) {
2715 create_copy_ins (cfg
, ins
->dreg
, s390_r2
, ins
);
2717 /* two forced copies */
2718 create_copy_ins (cfg
, val
, s390_r2
, ins
);
2719 create_copy_ins (cfg
, ins
->dreg
, s390_r3
, ins
);
2723 if (reg_is_freeable (val
) && hreg
>= 0 && (reginfo
[hreg
].born_in
>= i
&& !(cur_iregs
& (1 << val
)))) {
2724 DEBUG (g_print ("\tfreeable %s (R%d)\n", mono_arch_regname (val
), hreg
));
2725 mono_regstate_free_int (rs
, val
);
2727 } else if (spec
[MONO_INST_DEST
] == 'a' && ins
->dreg
!= s390_r2
&& spec
[MONO_INST_CLOB
] != 'd') {
2728 /* this instruction only outputs to s390_r2, need to copy */
2729 create_copy_ins (cfg
, ins
->dreg
, s390_r2
, ins
);
2734 if (spec
[MONO_INST_DEST
] == 'f' &&
2735 freg_is_freeable (ins
->dreg
) &&
2736 prev_dreg
>= 0 && (reginfof
[prev_dreg
].born_in
>= i
)) {
2737 DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins
->dreg
), prev_dreg
, reginfo
[prev_dreg
].born_in
));
2738 mono_regstate_free_float (rs
, ins
->dreg
);
2739 } else if (spec
[MONO_INST_DEST
] != 'f' &&
2740 reg_is_freeable (ins
->dreg
) &&
2741 prev_dreg
>= 0 && (reginfo
[prev_dreg
].born_in
>= i
)) {
2742 DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins
->dreg
), prev_dreg
, reginfo
[prev_dreg
].born_in
));
2743 mono_regstate_free_int (rs
, ins
->dreg
);
2745 if (spec
[MONO_INST_SRC1
] == 'f') {
2746 src1_mask
= cur_fregs
;
2747 if (ins
->sreg1
>= MONO_MAX_FREGS
) {
2748 val
= rs
->fassign
[ins
->sreg1
];
2749 prev_sreg1
= ins
->sreg1
;
2753 /* the register gets spilled after this inst */
2756 //g_assert (val == -1); /* source cannot be spilled */
2757 val
= mono_regstate_alloc_float (rs
, src1_mask
);
2759 val
= get_float_register_spilling (cfg
, tmp
, ins
, src1_mask
, ins
->sreg1
);
2760 rs
->fassign
[ins
->sreg1
] = val
;
2761 DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", mono_arch_regname (val
), ins
->sreg1
));
2763 MonoInst
*store
= create_spilled_store_float (cfg
, spill
, val
, prev_sreg1
, NULL
);
2764 insert_before_ins (ins
, tmp
, store
);
2767 rs
->fsymbolic
[val
] = prev_sreg1
;
2772 } else if (ins
->sreg1
>= MONO_MAX_IREGS
) {
2773 val
= rs
->iassign
[ins
->sreg1
];
2774 prev_sreg1
= ins
->sreg1
;
2778 /* the register gets spilled after this inst */
2781 val
= mono_regstate_alloc_int (rs
, src1_mask
);
2783 val
= get_register_spilling (cfg
, tmp
, ins
,
2786 rs
->iassign
[ins
->sreg1
] = val
;
2787 DEBUG (g_print ("\tassigned sreg1 %s to R%d\n",
2788 mono_arch_regname (val
), ins
->sreg1
));
2791 store
= create_spilled_store (cfg
, spill
, val
,
2793 insert_before_ins (ins
, tmp
, store
);
2796 rs
->isymbolic
[val
] = prev_sreg1
;
2801 /*----------------------------------------------*/
2802 /* handle clobbering of sreg1 */
2803 /*----------------------------------------------*/
2804 if ((spec
[MONO_INST_CLOB
] == '1' ||
2805 spec
[MONO_INST_CLOB
] == 's') &&
2806 ins
->dreg
!= ins
->sreg1
) {
2808 copy
= create_copy_ins (cfg
, ins
->dreg
, ins
->sreg1
, NULL
);
2809 DEBUG (g_print ("\tneed to copy sreg1 %s to dreg %s\n",
2810 mono_arch_regname (ins
->sreg1
),
2811 mono_arch_regname (ins
->dreg
)));
2812 if (ins
->sreg2
== -1 || spec
[MONO_INST_CLOB
] == 's') {
2813 /* note: the copy is inserted before the current instruction! */
2814 insert_before_ins (ins
, tmp
, copy
);
2815 /* we set sreg1 to dest as well */
2816 prev_sreg1
= ins
->sreg1
= ins
->dreg
;
2818 /* inserted after the operation */
2819 copy
->next
= ins
->next
;
2824 if (spec
[MONO_INST_SRC2
] == 'f') {
2825 src2_mask
= cur_fregs
;
2826 if (ins
->sreg2
>= MONO_MAX_FREGS
) {
2827 val
= rs
->fassign
[ins
->sreg2
];
2828 prev_sreg2
= ins
->sreg2
;
2832 /* the register gets spilled after this inst */
2835 val
= mono_regstate_alloc_float (rs
, src2_mask
);
2837 val
= get_float_register_spilling (cfg
, tmp
, ins
, src2_mask
, ins
->sreg2
);
2838 rs
->fassign
[ins
->sreg2
] = val
;
2839 DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val
), ins
->sreg2
));
2841 create_spilled_store_float (cfg
, spill
, val
, prev_sreg2
, ins
);
2843 rs
->fsymbolic
[val
] = prev_sreg2
;
2848 } else if (ins
->sreg2
>= MONO_MAX_IREGS
) {
2849 val
= rs
->iassign
[ins
->sreg2
];
2850 prev_sreg2
= ins
->sreg2
;
2854 /* the register gets spilled after this inst */
2857 val
= mono_regstate_alloc_int (rs
, src2_mask
);
2859 val
= get_register_spilling (cfg
, tmp
, ins
, src2_mask
, ins
->sreg2
);
2860 rs
->iassign
[ins
->sreg2
] = val
;
2861 DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val
), ins
->sreg2
));
2863 create_spilled_store (cfg
, spill
, val
, prev_sreg2
, ins
);
2865 rs
->isymbolic
[val
] = prev_sreg2
;
2871 if (spec
[MONO_INST_CLOB
] == 'c') {
2873 guint32 clob_mask
= S390_CALLER_REGS
;
2874 for (j
= 0; j
< MONO_MAX_IREGS
; ++j
) {
2876 if ((clob_mask
& s
) && !(rs
->ifree_mask
& s
) && j
!= ins
->sreg1
) {
2884 /*========================= End of Function ========================*/
2886 /*------------------------------------------------------------------*/
2888 /* Name - emit_float_to_int */
2890 /* Function - Create instructions which will convert a floating */
2891 /* point value to integer. */
2893 /*------------------------------------------------------------------*/
2896 emit_float_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
2898 /* sreg is a float, dreg is an integer reg. */
2900 s390_cfdbr (code
, dreg
, 5, sreg
);
2903 s390_lghi (code
, s390_r0
, 0);
2904 s390_lghi (code
, s390_r13
, 0xff);
2905 s390_ltgr (code
, dreg
, dreg
);
2907 s390_lhi (code
, s390_r0
, 0x80);
2908 s390_ngr (code
, dreg
, s390_r13
);
2909 s390_ogr (code
, dreg
, s390_r0
);
2913 s390_basr (code
, s390_r13
, 0);
2915 s390_llong (code
, 0x41e0000000000000);
2916 s390_llong (code
, 0x41f0000000000000);
2917 s390_ldr (code
, s390_f15
, sreg
);
2918 s390_cdb (code
, s390_f15
, 0, s390_r13
, 0);
2920 s390_sdb (code
, s390_f15
, 0, s390_r13
, 8);
2921 s390_cfdbr (code
, dreg
, 7, s390_f15
);
2923 s390_cfdbr (code
, dreg
, 5, sreg
);
2926 s390_lghi (code
, s390_r0
, 0xff);
2927 s390_ngr (code
, dreg
, s390_r0
);
2930 s390_lghi (code
, s390_r0
, -1);
2931 s390_srlg (code
, s390_r0
, s390_r0
, 0, 16);
2932 s390_ngr (code
, dreg
, s390_r0
);
2939 /*========================= End of Function ========================*/
2941 /*------------------------------------------------------------------*/
2943 /* Name - mono_emit_stack_alloc */
2947 /*------------------------------------------------------------------*/
2949 static unsigned char*
2950 mono_emit_stack_alloc (guchar
*code
, MonoInst
* tree
)
2955 /*========================= End of Function ========================*/
2957 /*------------------------------------------------------------------*/
2959 /* Name - mono_arch_output_basic_block */
2961 /* Function - Perform the "real" work of emitting instructions */
2962 /* that will do the work of in the basic block. */
2964 /*------------------------------------------------------------------*/
2967 mono_arch_output_basic_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2972 guint8
*code
= cfg
->native_code
+ cfg
->code_len
;
2973 MonoInst
*last_ins
= NULL
;
2974 guint last_offset
= 0;
2978 if (cfg
->opt
& MONO_OPT_PEEPHOLE
)
2979 peephole_pass (cfg
, bb
);
2981 /* we don't align basic blocks of loops on s390 */
2983 if (cfg
->verbose_level
> 2)
2984 g_print ("Basic block %d starting at offset 0x%x\n", bb
->block_num
, bb
->native_offset
);
2986 cpos
= bb
->max_offset
;
2988 if (cfg
->prof_options
& MONO_PROFILE_COVERAGE
) {
2989 //MonoCoverageInfo *cov = mono_get_coverage_info (cfg->method);
2990 //g_assert (!mono_compile_aot);
2993 // cov->data [bb->dfn].iloffset = bb->cil_code - cfg->cil_code;
2994 /* this is not thread save, but good enough */
2995 /* fixme: howto handle overflows? */
2996 //x86_inc_mem (code, &cov->data [bb->dfn].count);
3001 offset
= code
- cfg
->native_code
;
3003 max_len
= ((guint8
*)ins_spec
[ins
->opcode
])[MONO_INST_LEN
];
3005 if (offset
> (cfg
->code_size
- max_len
- 16)) {
3006 cfg
->code_size
*= 2;
3007 cfg
->native_code
= g_realloc (cfg
->native_code
, cfg
->code_size
);
3008 code
= cfg
->native_code
+ offset
;
3011 mono_debug_record_line_number (cfg
, ins
, offset
);
3013 switch (ins
->opcode
) {
3014 case OP_STOREI1_MEMBASE_IMM
: {
3015 s390_lghi (code
, s390_r14
, ins
->inst_imm
);
3016 if (s390_is_uimm12(ins
->inst_offset
))
3017 s390_stc (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3019 s390_basr (code
, s390_r13
, 0);
3021 s390_llong(code
, ins
->inst_offset
);
3022 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3023 s390_stc (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3027 case OP_STOREI2_MEMBASE_IMM
: {
3028 s390_lghi (code
, s390_r14
, ins
->inst_imm
);
3029 if (s390_is_uimm12(ins
->inst_offset
)) {
3030 s390_sth (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3032 s390_basr (code
, s390_r13
, 0);
3034 s390_llong(code
, ins
->inst_offset
);
3035 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3036 s390_sth (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3040 case OP_STORE_MEMBASE_IMM
:
3041 case OP_STOREI8_MEMBASE_IMM
: {
3042 if (s390_is_imm16(ins
->inst_imm
)) {
3043 s390_lghi (code
, s390_r14
, ins
->inst_imm
);
3045 s390_basr (code
, s390_r13
, 0);
3047 s390_llong(code
, ins
->inst_imm
);
3048 s390_lg (code
, s390_r14
, 0, s390_r13
, 4);
3050 if (s390_is_uimm12(ins
->inst_offset
)) {
3051 s390_stg (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3053 s390_basr (code
, s390_r13
, 0);
3055 s390_llong(code
, ins
->inst_offset
);
3056 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3057 s390_stg (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3061 case OP_STOREI4_MEMBASE_IMM
: {
3062 if (s390_is_imm16(ins
->inst_imm
)) {
3063 s390_lghi (code
, s390_r14
, ins
->inst_imm
);
3065 s390_basr (code
, s390_r13
, 0);
3067 s390_llong(code
, ins
->inst_imm
);
3068 s390_lg (code
, s390_r14
, 0, s390_r13
, 4);
3070 if (s390_is_uimm12(ins
->inst_offset
)) {
3071 s390_st (code
, s390_r14
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3073 s390_basr (code
, s390_r13
, 0);
3075 s390_llong(code
, ins
->inst_offset
);
3076 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3077 s390_st (code
, s390_r14
, s390_r13
, ins
->inst_destbasereg
, 0);
3081 case OP_STOREI1_MEMBASE_REG
: {
3082 if (s390_is_uimm12(ins
->inst_offset
)) {
3083 s390_stc (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3085 s390_basr (code
, s390_r13
, 0);
3087 s390_llong(code
, ins
->inst_offset
);
3088 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3089 s390_stc (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3093 case OP_STOREI2_MEMBASE_REG
: {
3094 if (s390_is_uimm12(ins
->inst_offset
)) {
3095 s390_sth (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3097 s390_basr (code
, s390_r13
, 0);
3099 s390_llong(code
, ins
->inst_offset
);
3100 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3101 s390_sth (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3105 case OP_STORE_MEMBASE_REG
:
3106 case OP_STOREI8_MEMBASE_REG
: {
3107 if (s390_is_uimm12(ins
->inst_offset
)) {
3108 s390_stg (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3110 s390_basr (code
, s390_r13
, 0);
3112 s390_llong(code
, ins
->inst_offset
);
3113 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3114 s390_stg (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3118 case OP_STOREI4_MEMBASE_REG
: {
3119 if (s390_is_uimm12(ins
->inst_offset
)) {
3120 s390_st (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
3122 s390_basr (code
, s390_r13
, 0);
3124 s390_llong(code
, ins
->inst_offset
);
3125 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3126 s390_st (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
3132 case CEE_LDIND_U4
: {
3133 s390_basr (code
, s390_r13
, 0);
3135 s390_word (code
, ins
->inst_p0
);
3136 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3137 s390_lgf (code
, ins
->dreg
, 0, s390_r13
, 0);
3141 g_assert_not_reached ();
3143 case OP_LOAD_MEMBASE
:
3144 case OP_LOADI8_MEMBASE
: {
3145 if (s390_is_uimm12(ins
->inst_offset
))
3146 s390_lg (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3148 if (s390_is_imm16(ins
->inst_offset
)) {
3149 s390_lghi(code
, s390_r13
, ins
->inst_offset
);
3150 s390_lg (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
3152 s390_basr (code
, s390_r13
, 0);
3154 s390_llong(code
, ins
->inst_offset
);
3155 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3156 s390_lg (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
3161 case OP_LOADI4_MEMBASE
:
3162 case OP_LOADU4_MEMBASE
: {
3163 if (s390_is_uimm12(ins
->inst_offset
))
3164 s390_lgf (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3166 if (s390_is_imm16(ins
->inst_offset
)) {
3167 s390_lghi(code
, s390_r13
, ins
->inst_offset
);
3168 s390_lgf (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
3170 s390_basr (code
, s390_r13
, 0);
3172 s390_llong(code
, ins
->inst_offset
);
3173 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3174 s390_lgf (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
3179 case OP_LOADU1_MEMBASE
: {
3180 s390_lghi(code
, s390_r0
, 0);
3181 if (s390_is_uimm12(ins
->inst_offset
))
3182 s390_ic (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3184 s390_basr (code
, s390_r13
, 0);
3186 s390_llong(code
, ins
->inst_offset
);
3187 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3188 s390_ic (code
, s390_r0
, s390_r13
, ins
->inst_basereg
, 0);
3190 s390_lgr (code
, ins
->dreg
, s390_r0
);
3193 case OP_LOADI1_MEMBASE
: {
3194 s390_lghi(code
, s390_r0
, 0);
3195 if (s390_is_uimm12(ins
->inst_offset
))
3196 s390_lgb (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3198 s390_basr (code
, s390_r13
, 0);
3200 s390_llong(code
, ins
->inst_offset
);
3201 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3202 s390_lgb (code
, s390_r0
, s390_r13
, ins
->inst_basereg
, 0);
3206 case OP_LOADU2_MEMBASE
: {
3207 s390_lghi(code
, s390_r0
, 0);
3208 if (s390_is_uimm12(ins
->inst_offset
))
3209 s390_icm (code
, s390_r0
, 3, ins
->inst_basereg
, ins
->inst_offset
);
3211 s390_basr (code
, s390_r13
, 0);
3213 s390_llong(code
, ins
->inst_offset
);
3214 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3215 s390_agr (code
, s390_r13
, ins
->inst_basereg
);
3216 s390_icm (code
, s390_r0
, 3, s390_r13
, 0);
3218 s390_lgr (code
, ins
->dreg
, s390_r0
);
3221 case OP_LOADI2_MEMBASE
: {
3222 s390_lghi(code
, s390_r0
, 0);
3223 if (s390_is_uimm12(ins
->inst_offset
))
3224 s390_lh (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
3226 s390_basr (code
, s390_r13
, 0);
3228 s390_llong(code
, ins
->inst_offset
);
3229 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3230 s390_lh (code
, s390_r0
, s390_r13
, ins
->inst_basereg
, 0);
3232 s390_lgr (code
, ins
->dreg
, s390_r0
);
3236 s390_lghi (code
, s390_r0
, 0x80);
3237 if (ins
->dreg
!= ins
->sreg1
) {
3238 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3240 s390_ngr (code
, s390_r0
, ins
->sreg1
);
3242 s390_lghi (code
, s390_r13
, -1);
3243 s390_sllg (code
, s390_r13
, s390_r13
, 0, 8);
3244 s390_ogr (code
, ins
->dreg
, s390_r13
);
3248 s390_lghi (code
, s390_r0
, 0x80);
3249 s390_sllg (code
, s390_r0
, s390_r0
, 0, 8);
3250 if (ins
->dreg
!= ins
->sreg1
) {
3251 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3253 s390_ngr (code
, s390_r0
, ins
->sreg1
);
3255 s390_lghi (code
, s390_r13
, -1);
3256 s390_sllg (code
, s390_r13
, s390_r13
, 0, 16);
3257 s390_ogr (code
, ins
->dreg
, s390_r13
);
3261 s390_lghi (code
, s390_r0
, 0xff);
3262 if (ins
->dreg
!= ins
->sreg1
) {
3263 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3265 s390_ngr (code
, ins
->dreg
, s390_r0
);
3269 s390_lghi (code
, s390_r0
, -1);
3270 s390_sllg (code
, s390_r0
, s390_r0
, 0, 48);
3271 s390_srlg (code
, s390_r0
, s390_r0
, 0, 48);
3272 if (ins
->dreg
!= ins
->sreg1
) {
3273 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3275 s390_ngr (code
, ins
->dreg
, s390_r0
);
3281 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3282 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3283 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3284 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3285 ((ins
->next
->opcode
== OP_CLT_UN
) ||
3286 (ins
->next
->opcode
== OP_CGT_UN
)))
3287 s390_clgr (code
, ins
->sreg1
, ins
->sreg2
);
3289 s390_cgr (code
, ins
->sreg1
, ins
->sreg2
);
3292 case OP_COMPARE_IMM
: {
3293 if (s390_is_imm16 (ins
->inst_imm
)) {
3294 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3296 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3297 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3298 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3299 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3300 ((ins
->next
->opcode
== OP_CLT_UN
) ||
3301 (ins
->next
->opcode
== OP_CGT_UN
)))
3302 s390_clgr (code
, ins
->sreg1
, s390_r0
);
3304 s390_cgr (code
, ins
->sreg1
, s390_r0
);
3307 s390_basr (code
, s390_r13
, 0);
3309 s390_llong(code
, ins
->inst_imm
);
3311 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3312 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3313 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3314 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3315 ((ins
->next
->opcode
== OP_CLT_UN
) &&
3316 (ins
->next
->opcode
== OP_CGT_UN
)))
3317 s390_clg (code
, ins
->sreg1
, 0, s390_r13
, 4);
3319 s390_cg (code
, ins
->sreg1
, 0, s390_r13
, 4);
3325 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3326 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3327 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3328 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3329 ((ins
->next
->opcode
== OP_CLT_UN
) ||
3330 (ins
->next
->opcode
== OP_CGT_UN
)))
3331 s390_clr (code
, ins
->sreg1
, ins
->sreg2
);
3333 s390_cr (code
, ins
->sreg1
, ins
->sreg2
);
3336 case OP_ICOMPARE_IMM
: {
3337 if (s390_is_imm16 (ins
->inst_imm
)) {
3338 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3340 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3341 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3342 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3343 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3344 ((ins
->next
->opcode
== OP_CLT_UN
) ||
3345 (ins
->next
->opcode
== OP_CGT_UN
)))
3346 s390_clr (code
, ins
->sreg1
, s390_r0
);
3348 s390_cr (code
, ins
->sreg1
, s390_r0
);
3351 s390_basr (code
, s390_r13
, 0);
3353 s390_word (code
, ins
->inst_imm
);
3355 ((ins
->next
->opcode
>= CEE_BNE_UN
) &&
3356 (ins
->next
->opcode
<= CEE_BLT_UN
)) ||
3357 ((ins
->next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3358 (ins
->next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3359 ((ins
->next
->opcode
== OP_CLT_UN
) &&
3360 (ins
->next
->opcode
== OP_CGT_UN
)))
3361 s390_cl (code
, ins
->sreg1
, 0, s390_r13
, 4);
3363 s390_c (code
, ins
->sreg1
, 0, s390_r13
, 4);
3367 case OP_X86_TEST_NULL
: {
3368 s390_ltgr(code
, ins
->sreg1
, ins
->sreg1
);
3376 if (ins
->dreg
!= ins
->sreg1
) {
3377 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3379 s390_algr (code
, ins
->dreg
, ins
->sreg2
);
3383 if (ins
->dreg
!= ins
->sreg1
) {
3384 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3386 s390_agr (code
, ins
->dreg
, ins
->sreg2
);
3390 if (ins
->dreg
!= ins
->sreg1
) {
3391 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3393 s390_alcgr (code
, ins
->dreg
, ins
->sreg2
);
3398 (ins
->next
->opcode
== OP_ADC_IMM
)) {
3399 s390_basr (code
, s390_r13
, 0);
3401 s390_llong (code
, ins
->inst_imm
);
3402 if (ins
->dreg
!= ins
->sreg1
) {
3403 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3405 s390_alg (code
, ins
->dreg
, 0, s390_r13
, 4);
3407 if (s390_is_imm16 (ins
->inst_imm
)) {
3408 if (ins
->dreg
!= ins
->sreg1
) {
3409 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3411 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
3413 s390_basr (code
, s390_r13
, 0);
3415 s390_llong (code
, ins
->inst_imm
);
3416 if (ins
->dreg
!= ins
->sreg1
) {
3417 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3419 s390_ag (code
, ins
->dreg
, 0, s390_r13
, 4);
3425 if (s390_is_imm16 (ins
->inst_imm
)) {
3426 if (ins
->dreg
!= ins
->sreg1
) {
3427 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3429 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3430 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3432 s390_basr (code
, s390_r13
, 0);
3434 s390_llong(code
, ins
->inst_imm
);
3435 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3436 s390_alcgr(code
, ins
->dreg
, s390_r13
);
3441 if (ins
->dreg
!= ins
->sreg1
) {
3442 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3444 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
3445 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3448 case CEE_ADD_OVF_UN
: {
3449 if (ins
->dreg
!= ins
->sreg1
) {
3450 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3452 s390_algr (code
, ins
->dreg
, ins
->sreg2
);
3453 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3456 case OP_ADD_OVF_CARRY
: {
3457 if (ins
->dreg
!= ins
->sreg1
) {
3458 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3460 s390_lghi (code
, s390_r0
, 0);
3461 s390_lgr (code
, s390_r1
, s390_r0
);
3462 s390_alcgr(code
, s390_r0
, s390_r1
);
3463 s390_agr (code
, ins
->dreg
, ins
->sreg2
);
3464 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3465 s390_agr (code
, ins
->dreg
, s390_r0
);
3466 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3469 case OP_ADD_OVF_UN_CARRY
: {
3470 if (ins
->dreg
!= ins
->sreg1
) {
3471 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3473 s390_alcgr (code
, ins
->dreg
, ins
->sreg2
);
3474 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3478 if (ins
->dreg
!= ins
->sreg1
) {
3479 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3481 s390_slgr (code
, ins
->dreg
, ins
->sreg2
);
3485 if (ins
->dreg
!= ins
->sreg1
) {
3486 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3488 s390_sgr (code
, ins
->dreg
, ins
->sreg2
);
3492 if (ins
->dreg
!= ins
->sreg1
) {
3493 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3495 s390_slbgr (code
, ins
->dreg
, ins
->sreg2
);
3499 if (s390_is_imm16 (-ins
->inst_imm
)) {
3500 if (ins
->dreg
!= ins
->sreg1
) {
3501 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3503 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
3505 s390_basr (code
, s390_r13
, 0);
3507 s390_llong(code
, ins
->inst_imm
);
3508 if (ins
->dreg
!= ins
->sreg1
) {
3509 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3511 s390_sg (code
, ins
->dreg
, 0, s390_r13
, 4);
3516 s390_basr (code
, s390_r13
, 0);
3518 s390_llong(code
, ins
->inst_imm
);
3519 s390_slg (code
, ins
->dreg
, 0, s390_r13
, 4);
3523 if (ins
->dreg
!= ins
->sreg1
) {
3524 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3526 s390_sgr (code
, ins
->dreg
, ins
->sreg2
);
3527 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3530 case CEE_SUB_OVF_UN
: {
3531 if (ins
->dreg
!= ins
->sreg1
) {
3532 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3534 s390_slr (code
, ins
->dreg
, ins
->sreg2
);
3535 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3538 case OP_SUB_OVF_CARRY
: {
3539 if (ins
->dreg
!= ins
->sreg1
) {
3540 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3542 s390_lghi (code
, s390_r0
, 0);
3543 s390_lgr (code
, s390_r1
, s390_r0
);
3544 s390_slbr (code
, s390_r0
, s390_r1
);
3545 s390_sr (code
, ins
->dreg
, ins
->sreg2
);
3546 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3547 s390_agr (code
, ins
->dreg
, s390_r0
);
3548 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3551 case OP_SUB_OVF_UN_CARRY
: {
3552 if (ins
->dreg
!= ins
->sreg1
) {
3553 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3555 s390_slbgr (code
, ins
->dreg
, ins
->sreg2
);
3556 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3560 if (ins
->sreg1
== ins
->dreg
) {
3561 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
3564 if (ins
->sreg2
== ins
->dreg
) {
3565 s390_ngr (code
, ins
->dreg
, ins
->sreg1
);
3568 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3569 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
3575 if (s390_is_imm16 (ins
->inst_imm
)) {
3576 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3577 if (ins
->dreg
!= ins
->sreg1
) {
3578 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3580 s390_ngr (code
, ins
->dreg
, s390_r0
);
3582 s390_basr (code
, s390_r13
, 0);
3584 s390_llong(code
, ins
->inst_imm
);
3585 if (ins
->dreg
!= ins
->sreg1
) {
3586 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3588 s390_ng (code
, ins
->dreg
, 0, s390_r13
, 4);
3593 s390_lr (code
, s390_r0
, ins
->sreg1
);
3594 s390_srda (code
, s390_r0
, 0, 32);
3595 s390_dr (code
, s390_r0
, ins
->sreg2
);
3596 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3600 s390_lr (code
, s390_r0
, ins
->sreg1
);
3601 s390_srdl (code
, s390_r0
, 0, 32);
3602 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3603 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3607 if (s390_is_imm16 (ins
->inst_imm
)) {
3608 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3609 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3611 s390_basr (code
, s390_r13
, 0);
3613 s390_llong(code
, ins
->inst_imm
);
3614 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3615 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3617 s390_srda (code
, s390_r0
, 0, 32);
3618 s390_dr (code
, s390_r0
, ins
->sreg2
);
3619 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3623 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3624 s390_srda (code
, s390_r0
, 0, 32);
3625 s390_dr (code
, s390_r0
, ins
->sreg2
);
3626 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3629 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3630 s390_srdl (code
, s390_r0
, 0, 32);
3631 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3632 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3636 if (s390_is_imm16 (ins
->inst_imm
)) {
3637 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3638 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3640 s390_basr (code
, s390_r13
, 0);
3642 s390_llong(code
, ins
->inst_imm
);
3643 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3644 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3646 s390_srda (code
, s390_r0
, 0, 32);
3647 s390_dr (code
, s390_r0
, ins
->sreg2
);
3648 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3652 if (ins
->sreg1
== ins
->dreg
) {
3653 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
3656 if (ins
->sreg2
== ins
->dreg
) {
3657 s390_ogr (code
, ins
->dreg
, ins
->sreg1
);
3660 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3661 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
3667 if (s390_is_imm16 (ins
->inst_imm
)) {
3668 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3669 if (ins
->dreg
!= ins
->sreg1
) {
3670 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3672 s390_ogr (code
, ins
->dreg
, s390_r0
);
3674 s390_bras (code
, s390_r13
, 4);
3675 s390_llong(code
, ins
->inst_imm
);
3676 if (ins
->dreg
!= ins
->sreg1
) {
3677 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3679 s390_og (code
, ins
->dreg
, 0, s390_r13
, 0);
3684 if (ins
->sreg1
== ins
->dreg
) {
3685 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
3688 if (ins
->sreg2
== ins
->dreg
) {
3689 s390_xgr (code
, ins
->dreg
, ins
->sreg1
);
3692 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3693 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
3699 if (s390_is_imm16 (ins
->inst_imm
)) {
3700 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3701 if (ins
->dreg
!= ins
->sreg1
) {
3702 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3704 s390_xgr (code
, ins
->dreg
, s390_r0
);
3706 s390_basr (code
, s390_r13
, 0);
3708 s390_llong(code
, ins
->inst_imm
);
3709 if (ins
->dreg
!= ins
->sreg1
) {
3710 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3712 s390_xg (code
, ins
->dreg
, 0, s390_r13
, 4);
3718 if (ins
->sreg1
!= ins
->dreg
) {
3719 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3721 s390_sllg (code
, ins
->dreg
, ins
->dreg
, ins
->sreg2
, 0);
3726 if (ins
->sreg1
!= ins
->dreg
) {
3727 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3729 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0,
3730 (ins
->inst_imm
& 0x1f));
3735 if (ins
->sreg1
!= ins
->dreg
) {
3736 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3738 s390_srag (code
, ins
->dreg
, ins
->dreg
, ins
->sreg2
, 0);
3743 if (ins
->sreg1
!= ins
->dreg
) {
3744 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3746 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0,
3747 (ins
->inst_imm
& 0x1f));
3751 case OP_LSHR_UN_IMM
: {
3752 if (ins
->sreg1
!= ins
->dreg
) {
3753 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3755 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0,
3756 (ins
->inst_imm
& 0x1f));
3761 if (ins
->sreg1
!= ins
->dreg
) {
3762 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3764 s390_srlg (code
, ins
->dreg
, ins
->dreg
, ins
->sreg2
, 0);
3768 if (ins
->sreg1
!= ins
->dreg
) {
3769 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3771 s390_lghi (code
, s390_r0
, -1);
3772 s390_xgr (code
, ins
->dreg
, s390_r0
);
3776 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
3780 if (ins
->sreg1
== ins
->dreg
) {
3781 s390_msgr (code
, ins
->dreg
, ins
->sreg2
);
3784 if (ins
->sreg2
== ins
->dreg
) {
3785 s390_msgr (code
, ins
->dreg
, ins
->sreg1
);
3788 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3789 s390_msgr (code
, ins
->dreg
, ins
->sreg2
);
3795 if (s390_is_imm16 (ins
->inst_imm
)) {
3796 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3798 s390_basr (code
, s390_r13
, 0);
3800 s390_llong(code
, ins
->inst_imm
);
3801 if (ins
->dreg
!= ins
->sreg1
) {
3802 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3804 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
3806 s390_msgr (code
, ins
->dreg
, s390_r13
);
3811 s390_ltgr (code
, s390_r1
, ins
->sreg1
);
3812 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3813 s390_ltgr (code
, s390_r0
, ins
->sreg2
);
3815 s390_lghi (code
, s390_r1
, 0);
3816 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3817 s390_xgr (code
, s390_r0
, s390_r1
);
3818 s390_msgr (code
, s390_r1
, ins
->sreg2
);
3819 s390_xgr (code
, s390_r0
, s390_r1
);
3820 s390_srlg (code
, s390_r0
, s390_r0
, 0, 64);
3821 s390_ltgr (code
, s390_r0
, s390_r0
);
3822 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3823 PTRSLOT (code
, o
[0]);
3824 PTRSLOT (code
, o
[1]);
3825 s390_lgr (code
, ins
->dreg
, s390_r1
);
3828 case CEE_MUL_OVF_UN
: {
3829 s390_lghi (code
, s390_r0
, 0);
3830 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3831 s390_mlgr (code
, s390_r0
, ins
->sreg2
);
3832 s390_ltgr (code
, s390_r0
, s390_r0
);
3833 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3834 s390_lgr (code
, ins
->dreg
, s390_r1
);
3838 if (ins
->dreg
!= ins
->sreg1
) {
3839 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3841 s390_alr (code
, ins
->dreg
, ins
->sreg2
);
3845 if (ins
->dreg
!= ins
->sreg1
) {
3846 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3848 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
3852 if (ins
->dreg
!= ins
->sreg1
) {
3853 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3855 s390_alcr (code
, ins
->dreg
, ins
->sreg2
);
3860 (ins
->next
->opcode
== OP_ADC_IMM
)) {
3861 s390_basr (code
, s390_r13
, 0);
3863 s390_word (code
, ins
->inst_imm
);
3864 if (ins
->dreg
!= ins
->sreg1
) {
3865 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3867 s390_al (code
, ins
->dreg
, 0, s390_r13
, 4);
3869 if (s390_is_imm16 (ins
->inst_imm
)) {
3870 if (ins
->dreg
!= ins
->sreg1
) {
3871 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3873 s390_ahi (code
, ins
->dreg
, ins
->inst_imm
);
3875 s390_basr (code
, s390_r13
, 0);
3877 s390_word (code
, ins
->inst_imm
);
3878 if (ins
->dreg
!= ins
->sreg1
) {
3879 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3881 s390_a (code
, ins
->dreg
, 0, s390_r13
, 4);
3887 if (s390_is_imm16 (ins
->inst_imm
)) {
3888 if (ins
->dreg
!= ins
->sreg1
) {
3889 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3891 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3892 s390_alcr (code
, ins
->dreg
, s390_r0
);
3894 s390_basr (code
, s390_r13
, 0);
3896 s390_word (code
, ins
->inst_imm
);
3897 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
3898 s390_alcr (code
, ins
->dreg
, s390_r13
);
3903 if (ins
->dreg
!= ins
->sreg1
) {
3904 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3906 s390_slr (code
, ins
->dreg
, ins
->sreg2
);
3910 if (ins
->dreg
!= ins
->sreg1
) {
3911 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3913 s390_sr (code
, ins
->dreg
, ins
->sreg2
);
3917 if (ins
->dreg
!= ins
->sreg1
) {
3918 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3920 s390_slbr (code
, ins
->dreg
, ins
->sreg2
);
3924 if (s390_is_imm16 (-ins
->inst_imm
)) {
3925 if (ins
->dreg
!= ins
->sreg1
) {
3926 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3928 s390_ahi (code
, ins
->dreg
, -ins
->inst_imm
);
3930 s390_basr (code
, s390_r13
, 0);
3932 s390_word (code
, ins
->inst_imm
);
3933 if (ins
->dreg
!= ins
->sreg1
) {
3934 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3936 s390_s (code
, ins
->dreg
, 0, s390_r13
, 4);
3941 s390_basr (code
, s390_r13
, 0);
3943 s390_word (code
, ins
->inst_imm
);
3944 s390_sl (code
, ins
->dreg
, 0, s390_r13
, 4);
3948 if (ins
->sreg1
== ins
->dreg
) {
3949 s390_nr (code
, ins
->dreg
, ins
->sreg2
);
3952 if (ins
->sreg2
== ins
->dreg
) {
3953 s390_nr (code
, ins
->dreg
, ins
->sreg1
);
3956 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3957 s390_nr (code
, ins
->dreg
, ins
->sreg2
);
3963 if (s390_is_imm16 (ins
->inst_imm
)) {
3964 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
3965 if (ins
->dreg
!= ins
->sreg1
) {
3966 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3968 s390_nr (code
, ins
->dreg
, s390_r0
);
3970 s390_basr (code
, s390_r13
, 0);
3972 s390_word (code
, ins
->inst_imm
);
3973 if (ins
->dreg
!= ins
->sreg1
) {
3974 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
3976 s390_n (code
, ins
->dreg
, 0, s390_r13
, 4);
3981 s390_lr (code
, s390_r0
, ins
->sreg1
);
3982 s390_srda (code
, s390_r0
, 0, 32);
3983 s390_dr (code
, s390_r0
, ins
->sreg2
);
3984 s390_lr (code
, ins
->dreg
, s390_r1
);
3988 s390_lr (code
, s390_r0
, ins
->sreg1
);
3989 s390_srdl (code
, s390_r0
, 0, 32);
3990 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3991 s390_lr (code
, ins
->dreg
, s390_r1
);
3995 if (s390_is_imm16 (ins
->inst_imm
)) {
3996 s390_lhi (code
, s390_r13
, ins
->inst_imm
);
3997 s390_lr (code
, s390_r0
, ins
->sreg1
);
3999 s390_basr (code
, s390_r13
, 0);
4001 s390_word (code
, ins
->inst_imm
);
4002 s390_lr (code
, s390_r0
, ins
->sreg1
);
4003 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4005 s390_srda (code
, s390_r0
, 0, 32);
4006 s390_dr (code
, s390_r0
, ins
->sreg2
);
4007 s390_lr (code
, ins
->dreg
, s390_r1
);
4011 s390_lr (code
, s390_r0
, ins
->sreg1
);
4012 s390_srda (code
, s390_r0
, 0, 32);
4013 s390_dr (code
, s390_r0
, ins
->sreg2
);
4014 s390_lr (code
, ins
->dreg
, s390_r0
);
4017 s390_lr (code
, s390_r0
, ins
->sreg1
);
4018 s390_srdl (code
, s390_r0
, 0, 32);
4019 s390_dlr (code
, s390_r0
, ins
->sreg2
);
4020 s390_lr (code
, ins
->dreg
, s390_r0
);
4024 if (s390_is_imm16 (ins
->inst_imm
)) {
4025 s390_lhi (code
, s390_r13
, ins
->inst_imm
);
4026 s390_lr (code
, s390_r0
, ins
->sreg1
);
4028 s390_basr (code
, s390_r13
, 0);
4030 s390_word (code
, ins
->inst_imm
);
4031 s390_lr (code
, s390_r0
, ins
->sreg1
);
4032 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4034 s390_srda (code
, s390_r0
, 0, 32);
4035 s390_dr (code
, s390_r0
, ins
->sreg2
);
4036 s390_lr (code
, ins
->dreg
, s390_r0
);
4040 if (ins
->sreg1
== ins
->dreg
) {
4041 s390_or (code
, ins
->dreg
, ins
->sreg2
);
4044 if (ins
->sreg2
== ins
->dreg
) {
4045 s390_or (code
, ins
->dreg
, ins
->sreg1
);
4048 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4049 s390_or (code
, ins
->dreg
, ins
->sreg2
);
4055 if (s390_is_imm16 (ins
->inst_imm
)) {
4056 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
4057 if (ins
->dreg
!= ins
->sreg1
) {
4058 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4060 s390_or (code
, ins
->dreg
, s390_r0
);
4062 s390_bras (code
, s390_r13
, 4);
4063 s390_word (code
, ins
->inst_imm
);
4064 if (ins
->dreg
!= ins
->sreg1
) {
4065 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4067 s390_o (code
, ins
->dreg
, 0, s390_r13
, 0);
4072 if (ins
->sreg1
== ins
->dreg
) {
4073 s390_xr (code
, ins
->dreg
, ins
->sreg2
);
4076 if (ins
->sreg2
== ins
->dreg
) {
4077 s390_xr (code
, ins
->dreg
, ins
->sreg1
);
4080 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4081 s390_xr (code
, ins
->dreg
, ins
->sreg2
);
4087 if (s390_is_imm16 (ins
->inst_imm
)) {
4088 s390_lhi (code
, s390_r0
, ins
->inst_imm
);
4089 if (ins
->dreg
!= ins
->sreg1
) {
4090 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4092 s390_xr (code
, ins
->dreg
, s390_r0
);
4094 s390_basr (code
, s390_r13
, 0);
4096 s390_word (code
, ins
->inst_imm
);
4097 if (ins
->dreg
!= ins
->sreg1
) {
4098 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4100 s390_x (code
, ins
->dreg
, 0, s390_r13
, 4);
4105 if (ins
->sreg1
!= ins
->dreg
) {
4106 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4108 s390_sll (code
, ins
->dreg
, ins
->sreg2
, 0);
4112 if (ins
->sreg1
!= ins
->dreg
) {
4113 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4115 s390_sll (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
4119 if (ins
->sreg1
!= ins
->dreg
) {
4120 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4122 s390_sra (code
, ins
->dreg
, ins
->sreg2
, 0);
4126 if (ins
->sreg1
!= ins
->dreg
) {
4127 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4129 s390_sra (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
4132 case OP_ISHR_UN_IMM
: {
4133 if (ins
->sreg1
!= ins
->dreg
) {
4134 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4136 s390_srl (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
4140 if (ins
->sreg1
!= ins
->dreg
) {
4141 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4143 s390_srl (code
, ins
->dreg
, ins
->sreg2
, 0);
4147 if (ins
->sreg1
!= ins
->dreg
) {
4148 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4150 s390_lhi (code
, s390_r0
, -1);
4151 s390_xr (code
, ins
->dreg
, s390_r0
);
4155 s390_lcr (code
, ins
->dreg
, ins
->sreg1
);
4159 if (ins
->sreg1
== ins
->dreg
) {
4160 s390_msr (code
, ins
->dreg
, ins
->sreg2
);
4163 if (ins
->sreg2
== ins
->dreg
) {
4164 s390_msr (code
, ins
->dreg
, ins
->sreg1
);
4167 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4168 s390_msr (code
, ins
->dreg
, ins
->sreg2
);
4174 if (s390_is_imm16 (ins
->inst_imm
)) {
4175 s390_lhi (code
, s390_r13
, ins
->inst_imm
);
4177 s390_basr (code
, s390_r13
, 0);
4179 s390_word (code
, ins
->inst_imm
);
4180 if (ins
->dreg
!= ins
->sreg1
) {
4181 s390_lr (code
, ins
->dreg
, ins
->sreg1
);
4183 s390_l (code
, s390_r13
, 0, s390_r13
, 4);
4185 s390_msr (code
, ins
->dreg
, s390_r13
);
4190 s390_ltr (code
, s390_r1
, ins
->sreg1
);
4191 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
4192 s390_ltr (code
, s390_r0
, ins
->sreg2
);
4194 s390_lhi (code
, s390_r1
, 0);
4195 s390_j (code
, 0); CODEPTR(code
, o
[1]);
4196 s390_xr (code
, s390_r0
, s390_r1
);
4197 s390_msr (code
, s390_r1
, ins
->sreg2
);
4198 s390_xr (code
, s390_r0
, s390_r1
);
4199 s390_srl (code
, s390_r0
, 0, 31);
4200 s390_ltr (code
, s390_r0
, s390_r0
);
4201 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
4202 PTRSLOT (code
, o
[0]);
4203 PTRSLOT (code
, o
[1]);
4204 s390_lr (code
, ins
->dreg
, s390_r1
);
4207 case OP_IMUL_OVF_UN
: {
4208 s390_lhi (code
, s390_r0
, 0);
4209 s390_lr (code
, s390_r1
, ins
->sreg1
);
4210 s390_mlr (code
, s390_r0
, ins
->sreg2
);
4211 s390_ltr (code
, s390_r0
, s390_r0
);
4212 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
4213 s390_lr (code
, ins
->dreg
, s390_r1
);
4218 case OP_SETREGIMM
: {
4219 if (s390_is_imm16(ins
->inst_c0
)) {
4220 s390_lghi (code
, ins
->dreg
, ins
->inst_c0
);
4222 s390_basr (code
, s390_r13
, 0);
4224 s390_llong(code
, ins
->inst_c0
);
4225 s390_lg (code
, ins
->dreg
, 0, s390_r13
, 4);
4230 s390_basr (code
, s390_r13
, 0);
4232 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4233 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
4234 s390_llong(code
, 0);
4235 s390_lg (code
,ins
->dreg
, 0, s390_r13
, 4);
4244 if (ins
->dreg
!= ins
->sreg1
) {
4245 s390_lgr(code
, ins
->dreg
, ins
->sreg1
);
4251 if (ins
->dreg
!= ins
->sreg1
) {
4252 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4256 case OP_S390_SETF4RET
: {
4257 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
4260 case OP_FCONV_TO_R4
: {
4262 (ins
->next
->opcode
!= OP_STORER4_MEMBASE_REG
))
4263 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
4268 if (cfg
->method
->save_lmf
)
4269 code
= restoreLMF(cfg
, code
);
4271 if (cfg
->flags
& MONO_CFG_HAS_TAIL
) {
4272 s390_lmg(code
, s390_r2
, s390_r5
, STK_BASE
,
4273 S390_PARM_SAVE_OFFSET
);
4274 for (fParm
= 0; fParm
< 4; fParm
++)
4275 s390_ld (code
, fParm
, 0, STK_BASE
,
4276 S390_FLOAT_SAVE_OFFSET
+fParm
*sizeof(double));
4279 code
= backUpStackPtr(cfg
, code
);
4280 s390_lg (code
, s390_r14
, 0, STK_BASE
, S390_RET_ADDR_OFFSET
);
4281 s390_basr (code
, s390_r10
, 0);
4283 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4284 MONO_PATCH_INFO_METHOD_JUMP
,
4286 s390_llong(code
, 0);
4287 s390_lg (code
, s390_r1
, 0, s390_r10
, 4);
4288 s390_basr (code
, s390_r0
, s390_r1
);
4291 case OP_CHECK_THIS
: {
4292 /* ensure ins->sreg1 is not NULL */
4293 s390_lg (code
, s390_r0
, 0, ins
->sreg1
, 0);
4294 s390_ltgr (code
, s390_r0
, s390_r0
);
4298 s390_basr (code
, s390_r10
, 0);
4300 call
= (MonoCallInst
*)ins
;
4301 if (ins
->flags
& MONO_INST_HAS_METHOD
)
4302 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4303 MONO_PATCH_INFO_METHOD
,
4306 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4307 MONO_PATCH_INFO_ABS
,
4309 s390_llong(code
, 0);
4310 s390_lg (code
, s390_r1
, 0, s390_r10
, 4);
4311 s390_basr (code
, s390_r14
, s390_r1
);
4312 if (call
->signature
->ret
->type
== MONO_TYPE_R4
)
4313 s390_ldebr (code
, s390_f0
, s390_f0
);
4320 s390_basr (code
, s390_r10
, 0);
4322 call
= (MonoCallInst
*)ins
;
4323 if (ins
->flags
& MONO_INST_HAS_METHOD
)
4324 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4325 MONO_PATCH_INFO_METHOD
,
4328 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4329 MONO_PATCH_INFO_ABS
,
4331 s390_llong(code
, 0);
4332 s390_lg (code
, s390_r1
, 0, s390_r10
, 4);
4333 s390_basr (code
, s390_r14
, s390_r1
);
4336 case OP_FCALL_REG
: {
4337 call
= (MonoCallInst
*)ins
;
4338 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4339 s390_basr (code
, s390_r14
, s390_r1
);
4340 if (call
->signature
->ret
->type
== MONO_TYPE_R4
)
4341 s390_ldebr (code
, s390_f0
, s390_f0
);
4346 case OP_VOIDCALL_REG
:
4348 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4349 s390_basr (code
, s390_r14
, s390_r1
);
4352 case OP_FCALL_MEMBASE
: {
4353 call
= (MonoCallInst
*)ins
;
4354 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
4355 s390_basr (code
, s390_r14
, s390_r1
);
4356 if (call
->signature
->ret
->type
== MONO_TYPE_R4
)
4357 s390_ldebr (code
, s390_f0
, s390_f0
);
4360 case OP_LCALL_MEMBASE
:
4361 case OP_VCALL_MEMBASE
:
4362 case OP_VOIDCALL_MEMBASE
:
4363 case OP_CALL_MEMBASE
: {
4364 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
4365 s390_basr (code
, s390_r14
, s390_r1
);
4369 g_assert_not_reached ();
4372 int alloca_skip
= S390_MINIMAL_STACK_SIZE
+ cfg
->param_area
+
4373 S390_STACK_ALIGNMENT
- 1;
4374 int area_offset
= S390_ALIGN(alloca_skip
, S390_STACK_ALIGNMENT
);
4375 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4376 s390_aghi (code
, s390_r1
, 14);
4377 s390_srlg (code
, s390_r1
, s390_r1
, 0, 3);
4378 s390_sllg (code
, s390_r1
, s390_r1
, 0, 3);
4379 s390_lg (code
, s390_r13
, 0, STK_BASE
, 0);
4380 s390_lcgr (code
, s390_r1
, s390_r1
);
4381 s390_la (code
, STK_BASE
, STK_BASE
, s390_r1
, 0);
4382 s390_stg (code
, s390_r13
, 0, STK_BASE
, 0);
4383 s390_la (code
, ins
->dreg
, 0, STK_BASE
, area_offset
);
4384 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
4385 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
4389 s390_br (code
, s390_r14
);
4393 s390_lgr (code
, s390_r2
, ins
->sreg1
);
4394 s390_basr (code
, s390_r13
, 0);
4396 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_INTERNAL_METHOD
,
4397 (gpointer
)"mono_arch_throw_exception");
4398 s390_llong(code
, 0);
4399 s390_lg (code
, s390_r1
, 0, s390_r13
, 4);
4400 s390_basr (code
, s390_r14
, s390_r1
);
4403 case OP_START_HANDLER
: {
4404 if (s390_is_uimm12 (ins
->inst_left
->inst_offset
)) {
4405 s390_stg (code
, s390_r14
, 0,
4406 ins
->inst_left
->inst_basereg
,
4407 ins
->inst_left
->inst_offset
);
4409 s390_basr (code
, s390_r13
, 0);
4411 s390_llong(code
, ins
->inst_left
->inst_offset
);
4412 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4413 s390_stg (code
, s390_r14
, s390_r13
,
4414 ins
->inst_left
->inst_basereg
, 0);
4418 case OP_ENDFILTER
: {
4419 if (ins
->sreg1
!= s390_r2
)
4420 s390_lgr(code
, s390_r2
, ins
->sreg1
);
4421 if (s390_is_uimm12 (ins
->inst_left
->inst_offset
)) {
4422 s390_l (code
, s390_r14
, 0, ins
->inst_left
->inst_basereg
,
4423 ins
->inst_left
->inst_offset
);
4425 s390_basr (code
, s390_r13
, 0);
4427 s390_llong(code
, ins
->inst_left
->inst_offset
);
4428 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4429 s390_lg (code
, s390_r14
, s390_r13
,
4430 ins
->inst_left
->inst_basereg
, 0);
4432 s390_br (code
, s390_r14
);
4435 case CEE_ENDFINALLY
: {
4436 if (s390_is_uimm12 (ins
->inst_left
->inst_offset
)) {
4437 s390_lg (code
, s390_r14
, 0, ins
->inst_left
->inst_basereg
,
4438 ins
->inst_left
->inst_offset
);
4440 s390_basr (code
, s390_r13
, 0);
4442 s390_llong(code
, ins
->inst_left
->inst_offset
);
4443 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4444 s390_lg (code
, s390_r14
, s390_r13
,
4445 ins
->inst_left
->inst_basereg
, 0);
4447 s390_br (code
, s390_r14
);
4450 case OP_CALL_HANDLER
: {
4451 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4452 MONO_PATCH_INFO_BB
, ins
->inst_target_bb
);
4453 s390_brasl (code
, s390_r14
, 0);
4457 ins
->inst_c0
= code
- cfg
->native_code
;
4461 EMIT_UNCOND_BRANCH(ins
);
4464 s390_br (code
, ins
->sreg1
);
4469 s390_lghi(code
, ins
->dreg
, 1);
4471 s390_lghi(code
, ins
->dreg
, 0);
4476 s390_lghi(code
, ins
->dreg
, 1);
4478 s390_lghi(code
, ins
->dreg
, 0);
4483 s390_lghi(code
, ins
->dreg
, 1);
4485 s390_lghi(code
, ins
->dreg
, 0);
4490 s390_lghi(code
, ins
->dreg
, 1);
4492 s390_lghi(code
, ins
->dreg
, 0);
4497 s390_lghi(code
, ins
->dreg
, 1);
4499 s390_lghi(code
, ins
->dreg
, 0);
4502 case OP_COND_EXC_EQ
:
4503 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ
, ins
->inst_p1
);
4505 case OP_COND_EXC_NE_UN
:
4506 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE
, ins
->inst_p1
);
4508 case OP_COND_EXC_LT
:
4509 case OP_COND_EXC_LT_UN
:
4510 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, ins
->inst_p1
);
4512 case OP_COND_EXC_GT
:
4513 case OP_COND_EXC_GT_UN
:
4514 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, ins
->inst_p1
);
4516 case OP_COND_EXC_GE
:
4517 case OP_COND_EXC_GE_UN
:
4518 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE
, ins
->inst_p1
);
4520 case OP_COND_EXC_LE
:
4521 case OP_COND_EXC_LE_UN
:
4522 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE
, ins
->inst_p1
);
4524 case OP_COND_EXC_OV
:
4525 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, ins
->inst_p1
);
4527 case OP_COND_EXC_NO
:
4528 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO
, ins
->inst_p1
);
4531 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, ins
->inst_p1
);
4533 case OP_COND_EXC_NC
:
4534 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, ins
->inst_p1
);
4538 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
4542 EMIT_COND_BRANCH (ins
, S390_CC_NE
);
4548 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4554 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4560 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4566 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4569 /* floating point opcodes */
4571 if (*((float *) ins
->inst_p0
) == 0) {
4572 s390_lzdr (code
, ins
->dreg
);
4574 s390_basr (code
, s390_r13
, 0);
4576 s390_llong (code
, ins
->inst_p0
);
4577 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4578 s390_ld (code
, ins
->dreg
, 0, s390_r13
, 0);
4583 if (*((float *) ins
->inst_p0
) == 0) {
4584 s390_lzdr (code
, ins
->dreg
);
4586 s390_basr (code
, s390_r13
, 0);
4588 s390_llong(code
, ins
->inst_p0
);
4589 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4590 s390_ldeb (code
, ins
->dreg
, 0, s390_r13
, 0);
4594 case OP_STORER8_MEMBASE_REG
: {
4595 if (s390_is_uimm12(ins
->inst_offset
)) {
4596 s390_std (code
, ins
->sreg1
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
4598 s390_basr (code
, s390_r13
, 0);
4600 s390_llong(code
, ins
->inst_offset
);
4601 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4602 s390_std (code
, ins
->sreg1
, s390_r13
, ins
->inst_destbasereg
, 0);
4606 case OP_LOADR8_MEMBASE
: {
4607 if (s390_is_uimm12(ins
->inst_offset
)) {
4608 s390_ld (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4610 s390_basr (code
, s390_r13
, 0);
4612 s390_llong(code
, ins
->inst_offset
);
4613 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4614 s390_ld (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
4618 case OP_STORER4_MEMBASE_REG
: {
4619 if (s390_is_uimm12(ins
->inst_offset
)) {
4620 s390_ledbr(code
, s390_f15
, ins
->sreg1
);
4621 s390_ste (code
, s390_f15
, 0, ins
->inst_destbasereg
, ins
->inst_offset
);
4623 s390_basr (code
, s390_r13
, 0);
4625 s390_llong(code
, ins
->inst_offset
);
4626 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4627 s390_ledbr(code
, s390_f15
, ins
->sreg1
);
4628 s390_ste (code
, s390_f15
, s390_r13
, ins
->inst_destbasereg
, 0);
4632 case OP_LOADR4_MEMBASE
: {
4633 if (s390_is_uimm12(ins
->inst_offset
)) {
4634 s390_ldeb (code
, ins
->dreg
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4636 s390_basr (code
, s390_r13
, 0);
4638 s390_llong(code
, ins
->inst_offset
);
4639 s390_lg (code
, s390_r13
, 0, s390_r13
, 4);
4640 s390_ldeb (code
, ins
->dreg
, s390_r13
, ins
->inst_basereg
, 0);
4644 case CEE_CONV_R_UN
: {
4645 s390_cdfbr (code
, ins
->dreg
, ins
->sreg1
);
4646 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4647 s390_jnl (code
, 12);
4648 s390_basr (code
, s390_r13
, 0);
4650 s390_word (code
, 0x41f00000);
4651 s390_word (code
, 0);
4652 s390_adb (code
, ins
->dreg
, 0, s390_r13
, 4);
4656 s390_cdfbr (code
, ins
->dreg
, ins
->sreg1
);
4660 s390_cdfbr (code
, ins
->dreg
, ins
->sreg1
);
4663 case OP_FCONV_TO_I1
:
4664 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, TRUE
);
4666 case OP_FCONV_TO_U1
:
4667 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4669 case OP_FCONV_TO_I2
:
4670 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, TRUE
);
4672 case OP_FCONV_TO_U2
:
4673 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4675 case OP_FCONV_TO_I4
:
4677 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, TRUE
);
4679 case OP_FCONV_TO_U4
:
4681 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4683 case OP_FCONV_TO_I8
:
4684 case OP_FCONV_TO_U8
:
4685 g_assert_not_reached ();
4686 /* Implemented as helper calls */
4688 case OP_LCONV_TO_R_UN
:
4689 g_assert_not_reached ();
4690 /* Implemented as helper calls */
4692 case OP_LCONV_TO_OVF_I
: {
4693 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4695 s390_ltgr (code
, ins
->sreg2
, ins
->sreg2
);
4696 s390_jnl (code
, 0); CODEPTR(code
, o
[0]);
4697 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4698 s390_jnl (code
, 0); CODEPTR(code
, o
[1]);
4699 s390_lhi (code
, s390_r13
, -1);
4700 s390_cgr (code
, ins
->sreg1
, s390_r13
);
4701 s390_jnz (code
, 0); CODEPTR(code
, o
[2]);
4702 if (ins
->dreg
!= ins
->sreg2
)
4703 s390_lgr (code
, ins
->dreg
, ins
->sreg2
);
4704 s390_j (code
, 0); CODEPTR(code
, o
[3]);
4705 PTRSLOT(code
, o
[0]);
4706 s390_jz (code
, 0); CODEPTR(code
, o
[4]);
4707 PTRSLOT(code
, o
[1]);
4708 PTRSLOT(code
, o
[2]);
4709 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4710 MONO_PATCH_INFO_EXC
, "OverflowException");
4711 s390_brasl (code
, s390_r14
, 0);
4712 PTRSLOT(code
, o
[3]);
4713 PTRSLOT(code
, o
[4]);
4717 s390_sqdbr (code
, ins
->dreg
, ins
->sreg1
);
4721 if (ins
->dreg
== ins
->sreg1
)
4722 s390_adbr (code
, ins
->dreg
, ins
->sreg2
);
4724 if (ins
->dreg
== ins
->sreg2
)
4725 s390_adbr (code
, ins
->dreg
, ins
->sreg1
);
4727 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4728 s390_adbr (code
, ins
->dreg
, ins
->sreg2
);
4734 if (ins
->dreg
== ins
->sreg1
)
4735 s390_sdbr (code
, ins
->dreg
, ins
->sreg2
);
4737 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4738 s390_sdbr (code
, ins
->dreg
, ins
->sreg2
);
4743 if (ins
->dreg
== ins
->sreg1
)
4744 s390_mdbr (code
, ins
->dreg
, ins
->sreg2
);
4746 if (ins
->dreg
== ins
->sreg2
)
4747 s390_mdbr (code
, ins
->dreg
, ins
->sreg1
);
4749 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4750 s390_mdbr (code
, ins
->dreg
, ins
->sreg2
);
4756 if (ins
->dreg
== ins
->sreg1
)
4757 s390_ddbr (code
, ins
->dreg
, ins
->sreg2
);
4759 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4760 s390_ddbr (code
, ins
->dreg
, ins
->sreg2
);
4765 s390_lcdbr (code
, ins
->dreg
, ins
->sreg1
);
4769 if (ins
->dreg
!= ins
->sreg1
) {
4770 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4772 s390_didbr (code
, ins
->dreg
, ins
->sreg2
, 5, s390_f15
);
4776 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4780 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4781 s390_lghi (code
, ins
->dreg
, 1);
4783 s390_lghi (code
, ins
->dreg
, 0);
4787 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4788 s390_lghi (code
, ins
->dreg
, 1);
4790 s390_lghi (code
, ins
->dreg
, 0);
4794 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4795 s390_lghi (code
, ins
->dreg
, 1);
4797 s390_lghi (code
, ins
->dreg
, 0);
4801 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4802 s390_lghi (code
, ins
->dreg
, 1);
4804 s390_lghi (code
, ins
->dreg
, 0);
4808 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4809 s390_lghi (code
, ins
->dreg
, 1);
4811 s390_lghi (code
, ins
->dreg
, 0);
4815 EMIT_COND_BRANCH (ins
, S390_CC_EQ
|S390_CC_OV
);
4818 EMIT_COND_BRANCH (ins
, S390_CC_NE
|S390_CC_OV
);
4821 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4824 EMIT_COND_BRANCH (ins
, S390_CC_LT
|S390_CC_OV
);
4827 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4830 EMIT_COND_BRANCH (ins
, S390_CC_GT
|S390_CC_OV
);
4833 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4836 EMIT_COND_BRANCH (ins
, S390_CC_GE
|S390_CC_OV
);
4839 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4842 EMIT_COND_BRANCH (ins
, S390_CC_LE
|S390_CC_OV
);
4844 case CEE_CKFINITE
: {
4846 s390_lhi (code
, s390_r13
, 0x7f);
4847 s390_tcdb (code
, ins
->sreg1
, 0, s390_r13
, 0);
4848 s390_jz (code
, 0); CODEPTR(code
, o
);
4849 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4850 MONO_PATCH_INFO_EXC
, "ArithmeticException");
4851 s390_brasl (code
, s390_r14
,0);
4855 case OP_S390_MOVE
: {
4856 if (ins
->unused
> 0) {
4857 if (ins
->unused
<= 256) {
4858 s390_mvc (code
, ins
->unused
, ins
->dreg
,
4859 ins
->inst_offset
, ins
->sreg1
, ins
->inst_imm
);
4861 s390_lr (code
, s390_r0
, ins
->dreg
);
4862 if (s390_is_imm16 (ins
->inst_offset
)) {
4863 s390_aghi (code
, s390_r0
, ins
->inst_offset
);
4865 s390_basr (code
, s390_r13
, 0);
4867 s390_llong(code
, ins
->inst_offset
);
4868 s390_a (code
, s390_r0
, 0, s390_r13
, 4);
4870 s390_lr (code
, s390_r12
, ins
->sreg1
);
4871 if (s390_is_imm16 (ins
->inst_imm
)) {
4872 s390_aghi (code
, s390_r12
, ins
->inst_imm
);
4874 s390_basr (code
, s390_r13
, 0);
4876 s390_llong(code
, ins
->inst_imm
);
4877 s390_ag (code
, s390_r12
, 0, s390_r13
, 4);
4879 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4880 s390_lgr (code
, s390_r13
, s390_r1
);
4881 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
4888 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins
->opcode
), __FUNCTION__
);
4889 g_assert_not_reached ();
4892 if ((cfg
->opt
& MONO_OPT_BRANCH
) && ((code
- cfg
->native_code
- offset
) > max_len
)) {
4893 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %d)",
4894 mono_inst_name (ins
->opcode
), max_len
, code
- cfg
->native_code
- offset
);
4895 // g_assert_not_reached ();
4901 last_offset
= offset
;
4906 cfg
->code_len
= code
- cfg
->native_code
;
4909 /*========================= End of Function ========================*/
4911 /*------------------------------------------------------------------*/
4913 /* Name - mono_arch_register_lowlevel_calls */
4915 /* Function - Register routines to help with --trace operation. */
4917 /*------------------------------------------------------------------*/
4920 mono_arch_register_lowlevel_calls (void)
4922 mono_register_jit_icall (enter_method
, "mono_enter_method", NULL
, TRUE
);
4923 mono_register_jit_icall (leave_method
, "mono_leave_method", NULL
, TRUE
);
4926 /*========================= End of Function ========================*/
4928 /*------------------------------------------------------------------*/
4930 /* Name - mono_arch_patch_code */
4932 /* Function - Process the patch data created during the */
4933 /* instruction build process. This resolves jumps, */
4934 /* calls, variables etc. */
4936 /*------------------------------------------------------------------*/
4939 mono_arch_patch_code (MonoMethod
*method
, MonoDomain
*domain
, guint8
*code
, MonoJumpInfo
*ji
, gboolean run_cctors
)
4941 MonoJumpInfo
*patch_info
;
4943 for (patch_info
= ji
; patch_info
; patch_info
= patch_info
->next
) {
4944 unsigned char *ip
= patch_info
->ip
.i
+ code
;
4947 switch (patch_info
->type
) {
4948 case MONO_PATCH_INFO_BB
:
4949 target
= S390_RELATIVE((patch_info
->data
.bb
->native_offset
+code
),
4951 ip
+= 2; /* Skip over op-code */
4953 case MONO_PATCH_INFO_ABS
:
4954 *((gpointer
*)(ip
)) = patch_info
->data
.target
;
4956 case MONO_PATCH_INFO_LABEL
:
4957 target
= S390_RELATIVE((patch_info
->data
.inst
->inst_c0
+code
),ip
);
4958 ip
+= 2; /* Skip over op-code */
4960 case MONO_PATCH_INFO_IP
:
4963 case MONO_PATCH_INFO_METHOD_REL
:
4964 g_assert_not_reached ();
4965 *((gpointer
*)(ip
)) = code
+ patch_info
->data
.offset
;
4967 case MONO_PATCH_INFO_INTERNAL_METHOD
: {
4968 MonoJitICallInfo
*mi
= mono_find_jit_icall_by_name (patch_info
->data
.name
);
4970 g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info
->data
.name
);
4971 g_assert_not_reached ();
4973 *((gpointer
*)(ip
)) = mono_icall_get_wrapper (mi
);
4976 case MONO_PATCH_INFO_METHOD_JUMP
: {
4979 /*------------------------------------------------------*/
4980 /* get the trampoline to the method from the domain */
4981 /*------------------------------------------------------*/
4982 *((gpointer
*)(ip
)) = mono_create_jump_trampoline (
4984 patch_info
->data
.method
,
4988 list
= g_hash_table_lookup (domain
->jump_target_hash
,
4989 patch_info
->data
.method
);
4990 list
= g_slist_prepend (list
, ip
);
4991 g_hash_table_insert (domain
->jump_target_hash
,
4992 patch_info
->data
.method
, list
);
4995 case MONO_PATCH_INFO_METHOD
:
4996 if (patch_info
->data
.method
== method
) {
4997 *((gpointer
*)(ip
)) = code
;
4999 /* get the trampoline to the method from the domain */
5000 *((gpointer
*)(ip
)) = mono_arch_create_jit_trampoline(patch_info
->data
.method
);
5003 case MONO_PATCH_INFO_SWITCH
: {
5004 gpointer
*table
= (gpointer
*)patch_info
->data
.target
;
5006 /*------------------------------------------------------*/
5007 /* ip is pointing at the basr r13,0/j +4 instruction */
5008 /* the vtable value follows this (i.e. ip+6) */
5009 /*------------------------------------------------------*/
5010 *((gconstpointer
*)(ip
+6)) = table
;
5012 for (i
= 0; i
< patch_info
->table_size
; i
++) {
5013 table
[i
] = (int)patch_info
->data
.table
[i
] + code
;
5017 case MONO_PATCH_INFO_METHODCONST
:
5018 case MONO_PATCH_INFO_CLASS
:
5019 case MONO_PATCH_INFO_IMAGE
:
5020 case MONO_PATCH_INFO_FIELD
:
5021 target
= S390_RELATIVE(patch_info
->data
.target
, ip
);
5023 case MONO_PATCH_INFO_R4
:
5024 case MONO_PATCH_INFO_R8
:
5025 g_assert_not_reached ();
5026 *((gconstpointer
*)(ip
+ 2)) = patch_info
->data
.target
;
5028 case MONO_PATCH_INFO_IID
:
5029 mono_class_init (patch_info
->data
.klass
);
5030 target
= S390_RELATIVE(patch_info
->data
.klass
->interface_id
, ip
);
5032 case MONO_PATCH_INFO_VTABLE
:
5033 target
= S390_RELATIVE(mono_class_vtable (domain
, patch_info
->data
.klass
),ip
);
5036 case MONO_PATCH_INFO_CLASS_INIT
:
5037 target
= S390_RELATIVE(mono_create_class_init_trampoline (mono_class_vtable (domain
, patch_info
->data
.klass
)), ip
);
5040 case MONO_PATCH_INFO_SFLDA
: {
5041 MonoVTable
*vtable
= mono_class_vtable (domain
, patch_info
->data
.field
->parent
);
5042 if (!vtable
->initialized
&& !(vtable
->klass
->flags
& TYPE_ATTRIBUTE_BEFORE_FIELD_INIT
) && mono_class_needs_cctor_run (vtable
->klass
, method
))
5043 /* Done by the generated code */
5047 mono_runtime_class_init (vtable
);
5049 target
= S390_RELATIVE((char*)vtable
->data
+ patch_info
->data
.field
->offset
, ip
);
5053 case MONO_PATCH_INFO_EXC_NAME
:
5054 *((gconstpointer
*)(ip
)) = patch_info
->data
.name
;
5056 case MONO_PATCH_INFO_LDSTR
:
5057 target
= mono_ldstr (domain
, patch_info
->data
.token
->image
,
5058 mono_metadata_token_index (patch_info
->data
.token
->token
));
5060 case MONO_PATCH_INFO_TYPE_FROM_HANDLE
: {
5062 MonoClass
*handle_class
;
5064 handle
= mono_ldtoken (patch_info
->data
.token
->image
,
5065 patch_info
->data
.token
->token
,
5066 &handle_class
, NULL
);
5067 mono_class_init (handle_class
);
5068 mono_class_init (mono_class_from_mono_type (handle
));
5073 case MONO_PATCH_INFO_LDTOKEN
: {
5075 MonoClass
*handle_class
;
5077 handle
= mono_ldtoken (patch_info
->data
.token
->image
,
5078 patch_info
->data
.token
->token
,
5079 &handle_class
, NULL
);
5080 mono_class_init (handle_class
);
5085 case MONO_PATCH_INFO_EXC
:
5086 /* everything is dealt with at epilog output time */
5089 g_assert_not_reached ();
5091 s390_patch (ip
, target
);
5095 /*========================= End of Function ========================*/
5097 /*------------------------------------------------------------------*/
5099 /* Name - mono_arch_max_epilog_size */
5101 /* Function - Determine the maximum size of the epilog code. */
5103 /*------------------------------------------------------------------*/
5106 mono_arch_max_epilog_size (MonoCompile
*cfg
)
5108 int max_epilog_size
= 96;
5109 MonoJumpInfo
*patch_info
;
5111 if (cfg
->method
->save_lmf
)
5112 max_epilog_size
+= 128;
5114 if (mono_jit_trace_calls
!= NULL
)
5115 max_epilog_size
+= 128;
5117 if (cfg
->prof_options
& MONO_PROFILE_ENTER_LEAVE
)
5118 max_epilog_size
+= 128;
5120 /* count the number of exception infos */
5122 for (patch_info
= cfg
->patch_info
;
5124 patch_info
= patch_info
->next
) {
5125 if (patch_info
->type
== MONO_PATCH_INFO_EXC
)
5126 max_epilog_size
+= 26;
5129 return max_epilog_size
;
5132 /*========================= End of Function ========================*/
5134 /*------------------------------------------------------------------*/
5136 /* Name - mono_arch_emit_prolog */
5138 /* Function - Create the instruction sequence for a function */
5141 /*------------------------------------------------------------------*/
5144 mono_arch_emit_prolog (MonoCompile
*cfg
)
5146 MonoMethod
*method
= cfg
->method
;
5148 MonoMethodSignature
*sig
;
5150 int alloc_size
, pos
, max_offset
, i
, lmfOffset
;
5156 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (method
))
5159 cfg
->code_size
= 384;
5160 cfg
->native_code
= code
= g_malloc (cfg
->code_size
);
5162 if (cfg
->flags
& MONO_CFG_HAS_TAIL
) {
5163 s390_stmg (code
, s390_r2
, s390_r14
, STK_BASE
, S390_PARM_SAVE_OFFSET
);
5164 for (pos
= 0; pos
< 4; pos
++)
5165 s390_std (code
, pos
*2, 0, STK_BASE
,
5166 S390_FLOAT_SAVE_OFFSET
+pos
*sizeof(double));
5168 s390_stmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5171 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
5172 cfg
->used_int_regs
|= 1 << 11;
5175 alloc_size
= cfg
->stack_offset
;
5177 cfg
->stack_usage
= alloc_size
;
5178 s390_lgr (code
, s390_r11
, STK_BASE
);
5179 if (s390_is_imm16 (-alloc_size
)) {
5180 s390_aghi (code
, STK_BASE
, -alloc_size
);
5182 int stackSize
= alloc_size
;
5183 while (stackSize
> 32767) {
5184 s390_aghi (code
, STK_BASE
, -32767);
5187 s390_aghi (code
, STK_BASE
, -stackSize
);
5189 s390_stg (code
, s390_r11
, 0, STK_BASE
, 0);
5191 if (cfg
->frame_reg
!= STK_BASE
)
5192 s390_lgr (code
, s390_r11
, STK_BASE
);
5194 /* compute max_offset in order to use short forward jumps
5195 * we always do it on s390 because the immediate displacement
5196 * for jumps is too small
5199 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
5200 MonoInst
*ins
= bb
->code
;
5201 bb
->max_offset
= max_offset
;
5203 if (cfg
->prof_options
& MONO_PROFILE_COVERAGE
)
5207 max_offset
+= ((guint8
*)ins_spec
[ins
->opcode
])[MONO_INST_LEN
];
5212 /* load arguments allocated to register from the stack */
5213 sig
= method
->signature
;
5216 cinfo
= calculate_sizes (sig
, &sz
, sig
->pinvoke
);
5218 if (cinfo
->struct_ret
) {
5219 ArgInfo
*ainfo
= &cinfo
->ret
;
5221 inst
->unused
= ainfo
->vtsize
;
5222 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5225 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
5226 ArgInfo
*ainfo
= cinfo
->args
+ i
;
5227 inst
= cfg
->varinfo
[pos
];
5229 if (inst
->opcode
== OP_REGVAR
) {
5230 if (ainfo
->regtype
== RegTypeGeneral
)
5231 s390_lgr (code
, inst
->dreg
, ainfo
->reg
);
5232 else if (ainfo
->regtype
== RegTypeFP
) {
5233 if (inst
->dreg
!= ainfo
->reg
) {
5234 if (ainfo
->size
== 4) {
5235 s390_ledbr (code
, inst
->dreg
, ainfo
->reg
);
5237 s390_ldr (code
, inst
->dreg
, ainfo
->reg
);
5241 else if (ainfo
->regtype
== RegTypeBase
) {
5242 s390_lgr (code
, s390_r13
, STK_BASE
);
5243 s390_aghi(code
, s390_r13
, alloc_size
);
5244 s390_lg (code
, inst
->dreg
, 0, s390_r13
, ainfo
->offset
);
5246 g_assert_not_reached ();
5248 if (cfg
->verbose_level
> 2)
5249 g_print ("Argument %d assigned to register %s\n",
5250 pos
, mono_arch_regname (inst
->dreg
));
5252 if (ainfo
->regtype
== RegTypeGeneral
) {
5253 if (!((ainfo
->reg
>= 2) && (ainfo
->reg
<= 6)))
5254 g_assert_not_reached();
5255 switch (ainfo
->size
) {
5257 s390_stc (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5260 s390_sth (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5263 s390_stg (code
, ainfo
->reg
, 0,
5264 inst
->inst_basereg
, inst
->inst_offset
);
5267 s390_st (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5269 } else if (ainfo
->regtype
== RegTypeBase
) {
5270 } else if (ainfo
->regtype
== RegTypeFP
) {
5271 if (ainfo
->size
== 8)
5272 s390_std (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5273 else if (ainfo
->size
== 4)
5274 s390_ste (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5276 g_assert_not_reached ();
5277 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
5278 int doffset
= inst
->inst_offset
;
5280 if (ainfo
->reg
!= STK_BASE
)
5284 s390_lgr (code
, s390_r13
, STK_BASE
);
5285 s390_aghi(code
, s390_r13
, alloc_size
);
5287 switch (ainfo
->size
) {
5289 if (ainfo
->reg
== STK_BASE
)
5290 s390_ic (code
, reg
, 0, s390_r13
, ainfo
->offset
+3);
5291 s390_stc (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5294 if (ainfo
->reg
== STK_BASE
)
5295 s390_lh (code
, reg
, 0, s390_r13
, ainfo
->offset
+2);
5296 s390_sth (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5299 if (ainfo
->reg
== STK_BASE
)
5300 s390_l (code
, reg
, 0, s390_r13
, ainfo
->offset
);
5301 s390_st (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5304 if (ainfo
->reg
== STK_BASE
)
5305 s390_lg (code
, s390_r0
, 0, s390_r13
, ainfo
->offset
);
5306 s390_stg (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5309 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
5310 if (ainfo
->reg
== STK_BASE
) {
5311 s390_lgr (code
, s390_r13
, ainfo
->reg
);
5312 s390_aghi(code
, s390_r13
, alloc_size
);
5313 s390_lg (code
, s390_r13
, 0, s390_r13
,
5314 ainfo
->offparm
+ S390_MINIMAL_STACK_SIZE
);
5315 code
= emit_memcpy (code
, abs(ainfo
->vtsize
),
5317 inst
->inst_offset
, s390_r13
, 0);
5319 code
= emit_memcpy (code
, abs(ainfo
->vtsize
),
5325 g_assert_not_reached ();
5330 if (method
->save_lmf
) {
5331 /*---------------------------------------------------------------*/
5332 /* Preserve the parameter registers while we fix up the lmf */
5333 /*---------------------------------------------------------------*/
5334 s390_lgr (code
, s390_r7
, s390_r2
);
5335 s390_lgr (code
, s390_r8
, s390_r3
);
5336 s390_lgr (code
, s390_r9
, s390_r4
);
5337 s390_lgr (code
, s390_r10
, s390_r5
);
5339 /*---------------------------------------------------------------*/
5340 /* On return from this call r2 have the address of the &lmf */
5341 /*---------------------------------------------------------------*/
5342 s390_basr(code
, s390_r13
, 0);
5344 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5345 MONO_PATCH_INFO_INTERNAL_METHOD
,
5346 (gpointer
)"mono_get_lmf_addr");
5347 s390_llong(code
, 0);
5348 s390_lg (code
, s390_r1
, 0, s390_r13
, 4);
5349 s390_basr (code
, s390_r14
, s390_r1
);
5351 /*---------------------------------------------------------------*/
5352 /* we build the MonoLMF structure on the stack - see mini-s390.h */
5353 /*---------------------------------------------------------------*/
5354 lmfOffset
= alloc_size
- sizeof(MonoLMF
);
5356 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
5357 s390_aghi (code
, s390_r13
, lmfOffset
);
5359 /*---------------------------------------------------------------*/
5360 /* Set lmf.lmf_addr = jit_tls->lmf */
5361 /*---------------------------------------------------------------*/
5362 s390_stg (code
, s390_r2
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
5364 /*---------------------------------------------------------------*/
5365 /* Get current lmf */
5366 /*---------------------------------------------------------------*/
5367 s390_lg (code
, s390_r0
, 0, s390_r2
, 0);
5369 /*---------------------------------------------------------------*/
5370 /* Set our lmf as the current lmf */
5371 /*---------------------------------------------------------------*/
5372 s390_stg (code
, s390_r13
, 0, s390_r2
, 0);
5374 /*---------------------------------------------------------------*/
5375 /* Have our lmf.previous_lmf point to the last lmf */
5376 /*---------------------------------------------------------------*/
5377 s390_stg (code
, s390_r0
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
5379 /*---------------------------------------------------------------*/
5380 /* save method info */
5381 /*---------------------------------------------------------------*/
5382 s390_basr (code
, s390_r1
, 0);
5384 s390_llong (code
, method
);
5385 s390_lg (code
, s390_r1
, 0, s390_r1
, 4);
5386 s390_stg (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, method
));
5388 /*---------------------------------------------------------------*/
5389 /* save the current IP */
5390 /*---------------------------------------------------------------*/
5391 s390_lgr (code
, s390_r1
, cfg
->frame_reg
);
5392 s390_stg (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, ebp
));
5393 s390_lg (code
, s390_r1
, 0, s390_r1
, S390_RET_ADDR_OFFSET
);
5394 s390_la (code
, s390_r1
, 0, s390_r1
, 0);
5395 s390_stg (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, eip
));
5397 /*---------------------------------------------------------------*/
5398 /* Save general and floating point registers */
5399 /*---------------------------------------------------------------*/
5400 s390_stmg (code
, s390_r2
, s390_r12
, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, gregs
[2]));
5401 for (i
= 0; i
< 16; i
++) {
5402 s390_std (code
, i
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, fregs
[i
]));
5405 /*---------------------------------------------------------------*/
5406 /* Restore the parameter registers now that we've set up the lmf */
5407 /*---------------------------------------------------------------*/
5408 s390_lgr (code
, s390_r2
, s390_r7
);
5409 s390_lgr (code
, s390_r3
, s390_r8
);
5410 s390_lgr (code
, s390_r4
, s390_r9
);
5411 s390_lgr (code
, s390_r5
, s390_r10
);
5415 code
= mono_arch_instrument_prolog (cfg
, enter_method
, code
, TRUE
);
5417 cfg
->code_len
= code
- cfg
->native_code
;
5419 g_assert(cfg
->code_len
< cfg
->code_size
);
5425 /*========================= End of Function ========================*/
5427 /*------------------------------------------------------------------*/
5429 /* Name - mono_arch_emit_epilog */
5431 /* Function - Emit the instructions for a function epilog. */
5433 /*------------------------------------------------------------------*/
5436 mono_arch_emit_epilog (MonoCompile
*cfg
)
5438 MonoJumpInfo
*patch_info
;
5439 MonoMethod
*method
= cfg
->method
;
5440 MonoMethodSignature
*sig
= method
->signature
;
5445 code
= cfg
->native_code
+ cfg
->code_len
;
5447 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (method
)) {
5448 code
= mono_arch_instrument_epilog (cfg
, leave_method
, code
, TRUE
);
5452 if (method
->save_lmf
)
5453 code
= restoreLMF(cfg
, code
);
5455 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
)
5456 s390_lg (code
, STK_BASE
, 0, STK_BASE
, 0);
5458 code
= backUpStackPtr(cfg
, code
);
5460 s390_lmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5461 s390_br (code
, s390_r14
);
5463 /* add code to raise exceptions */
5464 for (patch_info
= cfg
->patch_info
; patch_info
; patch_info
= patch_info
->next
) {
5465 switch (patch_info
->type
) {
5466 case MONO_PATCH_INFO_EXC
: {
5467 /*---------------------------------------------*/
5468 /* Patch the branch in epilog to come here */
5469 /*---------------------------------------------*/
5470 s390_patch (patch_info
->ip
.i
+cfg
->native_code
+2,
5471 S390_RELATIVE(code
,patch_info
->ip
.i
+cfg
->native_code
));
5472 /*---------------------------------------------*/
5473 /* Patch the parameter passed to the handler */
5474 /*---------------------------------------------*/
5475 s390_basr (code
, s390_r13
, 0);
5477 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5478 MONO_PATCH_INFO_EXC_NAME
,
5479 patch_info
->data
.target
);
5480 s390_llong(code
, 0);
5481 /*-----------------------------------------------------*/
5482 /* Load the return address and the parameter register */
5483 /*-----------------------------------------------------*/
5484 s390_larl (code
, s390_r14
, S390_RELATIVE((patch_info
->ip
.i
+
5485 cfg
->native_code
+ 8), code
));
5486 s390_lg (code
, s390_r2
, 0, s390_r13
, 4);
5487 /*-----------------------------------------------------*/
5488 /* Reuse the current patch to set the jump */
5489 /*-----------------------------------------------------*/
5490 s390_basr (code
, s390_r13
, 0);
5492 patch_info
->type
= MONO_PATCH_INFO_INTERNAL_METHOD
;
5493 patch_info
->data
.name
= "mono_arch_throw_exception_by_name";
5494 patch_info
->ip
.i
= code
- cfg
->native_code
;
5495 s390_llong(code
, 0);
5496 s390_lg (code
, s390_r1
, 0, s390_r13
, 4);
5497 s390_br (code
, s390_r1
);
5506 cfg
->code_len
= code
- cfg
->native_code
;
5508 g_assert (cfg
->code_len
< cfg
->code_size
);
5512 /*========================= End of Function ========================*/
5514 /*------------------------------------------------------------------*/
5516 /* Name - mono_arch_setup_jit_tls_data */
5518 /* Function - Setup the JIT's Thread Level Specific Data. */
5520 /*------------------------------------------------------------------*/
5523 mono_arch_setup_jit_tls_data (MonoJitTlsData
*tls
)
5527 /*========================= End of Function ========================*/
5529 /*------------------------------------------------------------------*/
5531 /* Name - mono_arch_free_jit_tls_data */
5533 /* Function - Free tls data. */
5535 /*------------------------------------------------------------------*/
5538 mono_arch_free_jit_tls_data (MonoJitTlsData
*tls
)
5542 /*========================= End of Function ========================*/
5544 /*------------------------------------------------------------------*/
5546 /* Name - mono_arch_emit_this_vret_args */
5550 /*------------------------------------------------------------------*/
5553 mono_arch_emit_this_vret_args (MonoCompile
*cfg
, MonoCallInst
*inst
, int this_reg
, int this_type
, int vt_reg
)
5555 int this_dreg
= s390_r2
;
5558 this_dreg
= s390_r3
;
5560 /* add the this argument */
5561 if (this_reg
!= -1) {
5563 MONO_INST_NEW (cfg
, this, OP_SETREG
);
5564 this->type
= this_type
;
5565 this->sreg1
= this_reg
;
5566 this->dreg
= this_dreg
;
5567 mono_bblock_add_inst (cfg
->cbb
, this);
5572 MONO_INST_NEW (cfg
, vtarg
, OP_SETREG
);
5573 vtarg
->type
= STACK_MP
;
5574 vtarg
->sreg1
= vt_reg
;
5575 vtarg
->dreg
= s390_r2
;
5576 mono_bblock_add_inst (cfg
->cbb
, vtarg
);
5580 /*========================= End of Function ========================*/
5582 /*------------------------------------------------------------------*/
5584 /* Name - mono_arch_get_opcode_for_method */
5586 /* Function - Check for opcodes we can handle directly in */
5589 /*------------------------------------------------------------------*/
5592 mono_arch_get_opcode_for_method (MonoCompile
*cfg
, MonoMethod
*cmethod
, MonoMethodSignature
*fsig
, MonoInst
**args
)
5594 if (cmethod
->klass
== mono_defaults
.math_class
) {
5595 if (strcmp (cmethod
->name
, "Sqrt") == 0)
5601 /*========================= End of Function ========================*/
5603 /*------------------------------------------------------------------*/
5605 /* Name - mono_arch_print_tree */
5607 /* Function - Print platform-specific opcode details. */
5609 /* Returns - 1 - opcode details have been printed */
5610 /* 0 - opcode details have not been printed */
5612 /*------------------------------------------------------------------*/
5615 mono_arch_print_tree (MonoInst
*tree
, int arity
)
5619 switch (tree
->opcode
) {
5620 case OP_S390_LOADARG
:
5621 case OP_S390_ARGPTR
:
5622 case OP_S390_STKARG
:
5623 printf ("[0x%x(%s)]", tree
->inst_offset
,
5624 mono_arch_regname (tree
->inst_basereg
));
5628 printf ("[0x%x(%d,%s),0x%x(%s)]",
5629 tree
->inst_offset
, tree
->unused
,
5630 tree
->dreg
, tree
->inst_imm
,
5634 case OP_S390_SETF4RET
:
5635 printf ("[f%d,f%d]",
5636 mono_arch_regname (tree
->dreg
),
5637 mono_arch_regname (tree
->sreg1
));
5644 /*========================= End of Function ========================*/
5646 /*------------------------------------------------------------------*/
5648 /* Name - mono_arch_regalloc_cost */
5650 /* Function - Determine the cost, in the number of memory */
5651 /* references, of the action of allocating the var- */
5652 /* iable VMV into a register during global register */
5655 /* Returns - Cost */
5657 /*------------------------------------------------------------------*/
5660 mono_arch_regalloc_cost (MonoCompile
*cfg
, MonoMethodVar
*vmv
)
5666 /*========================= End of Function ========================*/