3 * Function - S/390 backend for the Mono code generator.
5 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Derivation - From mini-x86 & mini-ppc by -
10 * Paolo Molaro (lupus@ximian.com)
11 * Dietmar Maurer (dietmar@ximian.com)
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 #define MAX_ARCH_DELEGATE_PARAMS 7
21 #define EMIT_COND_BRANCH(ins,cond) \
23 if (ins->inst_true_bb->native_offset) { \
25 displace = ((cfg->native_code + \
26 ins->inst_true_bb->native_offset) - code) / 2; \
27 if (s390_is_imm16(displace)) { \
28 s390_brc (code, cond, displace); \
30 s390_jcl (code, cond, displace); \
33 mono_add_patch_info (cfg, code - cfg->native_code, \
34 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
35 s390_jcl (code, cond, 0); \
39 #define EMIT_UNCOND_BRANCH(ins) \
41 if (ins->inst_target_bb->native_offset) { \
43 displace = ((cfg->native_code + \
44 ins->inst_target_bb->native_offset) - code) / 2; \
45 if (s390_is_imm16(displace)) { \
46 s390_brc (code, S390_CC_UN, displace); \
48 s390_jcl (code, S390_CC_UN, displace); \
51 mono_add_patch_info (cfg, code - cfg->native_code, \
52 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
53 s390_jcl (code, S390_CC_UN, 0); \
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
59 mono_add_patch_info (cfg, code - cfg->native_code, \
60 MONO_PATCH_INFO_EXC, exc_name); \
61 s390_jcl (code, cond, 0); \
64 #define EMIT_COMP_AND_BRANCH(ins, cab, cmp) \
66 if (ins->inst_true_bb->native_offset) { \
68 displace = ((cfg->native_code + \
69 ins->inst_true_bb->native_offset) - code) / 2; \
70 if (s390_is_imm16(displace)) { \
71 s390_##cab (code, ins->sreg1, ins->sreg2, \
72 ins->sreg3, displace); \
74 s390_##cmp (code, ins->sreg1, ins->sreg2); \
75 displace = ((cfg->native_code + \
76 ins->inst_true_bb->native_offset) - code) / 2; \
77 s390_jcl (code, ins->sreg3, displace); \
80 s390_##cmp (code, ins->sreg1, ins->sreg2); \
81 mono_add_patch_info (cfg, code - cfg->native_code, \
82 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
83 s390_jcl (code, ins->sreg3, 0); \
87 #define EMIT_COMP_AND_BRANCH_IMM(ins, cab, cmp, lat, logical) \
89 if (ins->inst_true_bb->native_offset) { \
91 if ((ins->backend.data == 0) && (!logical)) { \
92 s390_##lat (code, ins->sreg1, ins->sreg1); \
93 displace = ((cfg->native_code + \
94 ins->inst_true_bb->native_offset) - code) / 2; \
95 if (s390_is_imm16(displace)) { \
96 s390_brc (code, ins->sreg3, displace); \
98 s390_jcl (code, ins->sreg3, displace); \
101 S390_SET (code, s390_r0, ins->backend.data); \
102 displace = ((cfg->native_code + \
103 ins->inst_true_bb->native_offset) - code) / 2; \
104 if (s390_is_imm16(displace)) { \
105 s390_##cab (code, ins->sreg1, s390_r0, \
106 ins->sreg3, displace); \
108 s390_##cmp (code, ins->sreg1, s390_r0); \
109 displace = ((cfg->native_code + \
110 ins->inst_true_bb->native_offset) - code) / 2; \
111 s390_jcl (code, ins->sreg3, displace); \
115 if ((ins->backend.data == 0) && (!logical)) { \
116 s390_##lat (code, ins->sreg1, ins->sreg1); \
118 S390_SET (code, s390_r0, ins->backend.data); \
119 s390_##cmp (code, ins->sreg1, s390_r0); \
121 mono_add_patch_info (cfg, code - cfg->native_code, \
122 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
123 s390_jcl (code, ins->sreg3, 0); \
127 #define CHECK_SRCDST_COM \
128 if (ins->dreg == ins->sreg2) { \
132 if (ins->dreg != ins->sreg1) { \
133 s390_lgr (code, ins->dreg, ins->sreg1); \
137 #define CHECK_SRCDST_NCOM \
138 if (ins->dreg == ins->sreg2) { \
140 s390_lgr (code, s390_r13, ins->sreg2); \
144 if (ins->dreg != ins->sreg1) { \
145 s390_lgr (code, ins->dreg, ins->sreg1); \
148 #define CHECK_SRCDST_COM_I \
149 if (ins->dreg == ins->sreg2) { \
153 if (ins->dreg != ins->sreg1) { \
154 s390_lgfr (code, ins->dreg, ins->sreg1); \
158 #define CHECK_SRCDST_NCOM_I \
159 if (ins->dreg == ins->sreg2) { \
161 s390_lgfr (code, s390_r13, ins->sreg2); \
165 if (ins->dreg != ins->sreg1) { \
166 s390_lgfr (code, ins->dreg, ins->sreg1); \
169 #define CHECK_SRCDST_COM_F \
170 if (ins->dreg == ins->sreg2) { \
174 if (ins->dreg != ins->sreg1) { \
175 s390_ldr (code, ins->dreg, ins->sreg1); \
179 #define CHECK_SRCDST_NCOM_F \
180 if (ins->dreg == ins->sreg2) { \
182 s390_ldr (code, s390_r13, ins->sreg2); \
186 if (ins->dreg != ins->sreg1) { \
187 s390_ldr (code, ins->dreg, ins->sreg1); \
190 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
193 MONO_INST_NEW (cfg, inst, OP_NOP); \
196 inst->inst_offset = offset; \
198 inst->inst_imm = imm; \
200 if (s390_is_uimm12(offset)) { \
202 inst->inst_offset = offset; \
204 dReg = mono_alloc_preg (cfg); \
205 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
206 dReg, dest, offset); \
208 inst->inst_offset = 0; \
210 if (s390_is_uimm12(imm)) { \
212 inst->inst_imm = imm; \
214 sReg = mono_alloc_preg (cfg); \
215 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
217 inst->sreg1 = sReg; \
218 inst->inst_imm = 0; \
221 inst->opcode = OP_S390_MOVE; \
222 inst->backend.size = size; \
223 MONO_ADD_INS (cfg->cbb, inst); \
226 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
227 int reg = mono_alloc_preg (cfg); \
230 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
233 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
237 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
241 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
245 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
249 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
252 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
256 tmpr = mono_alloc_preg (cfg); \
257 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
258 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
262 tmpr = mono_alloc_preg (cfg); \
263 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
265 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
269 tmpr = mono_alloc_preg (cfg); \
270 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
272 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
276 tmpr = mono_alloc_preg (cfg); \
277 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
279 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
283 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
289 #define DEBUG(a) if (cfg->verbose_level > 1) a
293 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
295 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
296 #define S390X_NOP_SIZE sizeof(RR_Format)
298 #define MAX(a, b) ((a) > (b) ? (a) : (b))
301 * imt trampoline size values
304 #define LOADCON_SIZE 20
308 #define ENABLE_WRONG_METHOD_CHECK 0
310 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
311 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
313 /*========================= End of Defines =========================*/
315 /*------------------------------------------------------------------*/
316 /* I n c l u d e s */
317 /*------------------------------------------------------------------*/
321 #include <sys/types.h>
324 #include <mono/metadata/abi-details.h>
325 #include <mono/metadata/appdomain.h>
326 #include <mono/metadata/debug-helpers.h>
327 #include <mono/metadata/profiler-private.h>
328 #include <mono/utils/mono-error.h>
329 #include <mono/utils/mono-error-internals.h>
330 #include <mono/utils/mono-math.h>
331 #include <mono/utils/mono-mmap.h>
332 #include <mono/utils/mono-hwcap.h>
333 #include <mono/utils/mono-threads.h>
334 #include <mono/utils/unlocked.h>
336 #include "mini-s390x.h"
337 #include "cpu-s390x.h"
338 #include "support-s390x.h"
339 #include "jit-icalls.h"
343 #include "aot-runtime.h"
344 #include "mini-runtime.h"
346 /*========================= End of Includes ========================*/
348 /*------------------------------------------------------------------*/
349 /* T y p e d e f s */
350 /*------------------------------------------------------------------*/
362 /*------------------------------------------------------------------*/
363 /* Used by the instrument_emit_epilog */
364 /*------------------------------------------------------------------*/
375 typedef struct InstList InstList
;
389 RegTypeStructByValInFP
,
391 RegTypeStructByAddrOnStack
395 gint32 offset
; /* offset from caller's stack */
396 gint32 offparm
; /* offset from callee's stack */
397 guint16 vtsize
; /* in param area */
400 guint32 size
; /* Size of structure used by RegTypeStructByVal */
401 gint32 type
; /* Data type of argument */
413 MonoMethodSignature
*sig
;
418 gint64 gr
[5]; /* R2-R6 */
419 gdouble fp
[3]; /* F0-F2 */
420 } __attribute__ ((__packed__
)) RegParm
;
428 } __attribute__ ((__packed__
)) breakpoint_t
;
430 /*========================= End of Typedefs ========================*/
432 /*------------------------------------------------------------------*/
433 /* P r o t o t y p e s */
434 /*------------------------------------------------------------------*/
436 static void indent (int);
437 static guint8
* backUpStackPtr(MonoCompile
*, guint8
*);
438 static void decodeParm (MonoType
*, void *, int);
439 static void enter_method (MonoMethod
*, RegParm
*, char *);
440 static void leave_method (MonoMethod
*, ...);
441 static inline void add_general (guint
*, size_data
*, ArgInfo
*);
442 static inline void add_stackParm (guint
*, size_data
*, ArgInfo
*, gint
);
443 static inline void add_float (guint
*, size_data
*, ArgInfo
*, gboolean
);
444 static CallInfo
* get_call_info (MonoMemPool
*, MonoMethodSignature
*);
445 static guchar
* emit_float_to_int (MonoCompile
*, guchar
*, int, int, int, gboolean
);
446 static __inline__
void emit_unwind_regs(MonoCompile
*, guint8
*, int, int, long);
447 static void compare_and_branch(MonoBasicBlock
*, MonoInst
*, int, gboolean
);
449 /*========================= End of Prototypes ======================*/
451 /*------------------------------------------------------------------*/
452 /* G l o b a l V a r i a b l e s */
453 /*------------------------------------------------------------------*/
455 __thread
int indent_level
= 0;
456 __thread
FILE *trFd
= NULL
;
460 * The code generated for sequence points reads from this location,
461 * which is made read-only when single stepping is enabled.
463 static gpointer ss_trigger_page
;
466 * Enabled breakpoints read from this trigger page
468 static gpointer bp_trigger_page
;
470 breakpoint_t breakpointCode
;
472 static mono_mutex_t mini_arch_mutex
;
474 static const char * grNames
[] = {
475 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
476 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
477 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
481 static const char * fpNames
[] = {
482 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
483 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
484 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
488 static const char * vrNames
[] = {
489 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
490 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
491 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
492 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
495 /*====================== End of Global Variables ===================*/
497 /*------------------------------------------------------------------*/
499 /* Name - mono_arch_regname */
501 /* Function - Returns the name of the register specified by */
502 /* the input parameter. */
504 /*------------------------------------------------------------------*/
507 mono_arch_regname (int reg
)
509 if (reg
>= 0 && reg
< 16)
510 return grNames
[reg
];
515 /*========================= End of Function ========================*/
517 /*------------------------------------------------------------------*/
519 /* Name - mono_arch_fregname */
521 /* Function - Returns the name of the register specified by */
522 /* the input parameter. */
524 /*------------------------------------------------------------------*/
527 mono_arch_fregname (int reg
)
529 if (reg
>= 0 && reg
< 16)
530 return fpNames
[reg
];
535 /*========================= End of Function ========================*/
537 /*------------------------------------------------------------------*/
539 /* Name - mono_arch_xregname */
541 /* Function - Returns the name of the register specified by */
542 /* the input parameter. */
544 /*------------------------------------------------------------------*/
547 mono_arch_xregname (int reg
)
549 if (reg
< s390_VR_NREG
)
550 return vrNames
[reg
];
555 /*========================= End of Function ========================*/
557 /*------------------------------------------------------------------*/
559 /* Name - arch_get_argument_info */
561 /* Function - Gathers information on parameters such as size, */
562 /* alignment, and padding. arg_info should be large */
563 /* enough to hold param_count + 1 entries. */
565 /* Parameters - @csig - Method signature */
566 /* @param_count - No. of parameters to consider */
567 /* @arg_info - An array to store the result info */
569 /* Returns - Size of the activation frame */
571 /*------------------------------------------------------------------*/
574 mono_arch_get_argument_info (MonoMethodSignature
*csig
,
576 MonoJitArgumentInfo
*arg_info
)
578 int k
, frame_size
= 0;
579 int size
, align
, pad
;
582 if (MONO_TYPE_ISSTRUCT (csig
->ret
)) {
583 frame_size
+= sizeof (gpointer
);
587 arg_info
[0].offset
= offset
;
590 frame_size
+= sizeof (gpointer
);
594 arg_info
[0].size
= frame_size
;
596 for (k
= 0; k
< param_count
; k
++) {
599 size
= mono_type_native_stack_size (csig
->params
[k
], (guint32
*) &align
);
601 size
= mini_type_stack_size (csig
->params
[k
], &align
);
603 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
604 arg_info
[k
].pad
= pad
;
606 arg_info
[k
+ 1].pad
= 0;
607 arg_info
[k
+ 1].size
= size
;
609 arg_info
[k
+ 1].offset
= offset
;
613 align
= MONO_ARCH_FRAME_ALIGNMENT
;
614 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
615 arg_info
[k
].pad
= pad
;
620 /*========================= End of Function ========================*/
622 /*------------------------------------------------------------------*/
624 /* Name - emit_unwind_regs. */
626 /* Function - Emit unwind information for a range of registers. */
628 /*------------------------------------------------------------------*/
630 static void __inline__
631 emit_unwind_regs(MonoCompile
*cfg
, guint8
*code
, int start
, int end
, long offset
)
635 for (i
= start
; i
< end
; i
++) {
636 mono_emit_unwind_op_offset (cfg
, code
, i
, offset
);
637 mini_gc_set_slot_type_from_cfa (cfg
, offset
, SLOT_NOREF
);
638 offset
+= sizeof(gulong
);
642 /*========================= End of Function ========================*/
644 /*------------------------------------------------------------------*/
646 /* Name - retFitsInReg. */
648 /* Function - Determines if a value can be returned in one or */
651 /*------------------------------------------------------------------*/
653 static inline gboolean
654 retFitsInReg(guint32 size
)
669 /*========================= End of Function ========================*/
671 /*------------------------------------------------------------------*/
673 /* Name - backStackPtr. */
675 /* Function - Restore Stack Pointer to previous frame. */
677 /*------------------------------------------------------------------*/
679 static inline guint8
*
680 backUpStackPtr(MonoCompile
*cfg
, guint8
*code
)
682 int stackSize
= cfg
->stack_usage
;
684 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
685 s390_lg (code
, STK_BASE
, 0, STK_BASE
, 0);
687 if (cfg
->frame_reg
!= STK_BASE
)
688 s390_lgr (code
, STK_BASE
, cfg
->frame_reg
);
690 if (s390_is_imm16 (stackSize
)) {
691 s390_aghi (code
, STK_BASE
, stackSize
);
693 while (stackSize
> 32767) {
694 s390_aghi (code
, STK_BASE
, 32767);
697 s390_aghi (code
, STK_BASE
, stackSize
);
704 /*========================= End of Function ========================*/
706 /*------------------------------------------------------------------*/
710 /* Function - Perform nice indenting to current level */
712 /*------------------------------------------------------------------*/
718 indent_level
+= diff
;
720 fprintf (trFd
, "%p [%3d] ",(void *)pthread_self(),v
);
722 fprintf (trFd
, ". ");
725 indent_level
+= diff
;
728 /*========================= End of Function ========================*/
730 /*------------------------------------------------------------------*/
732 /* Name - cvtMonoType */
734 /* Function - Convert a mono-type to a string. */
736 /*------------------------------------------------------------------*/
739 cvtMonoType(MonoTypeEnum t
)
744 return "MONO_TYPE_END";
746 return "MONO_TYPE_VOID";
747 case MONO_TYPE_BOOLEAN
:
748 return "MONO_TYPE_BOOLEAN";
750 return "MONO_TYPE_CHAR";
752 return "MONO_TYPE_I1";
754 return "MONO_TYPE_U1";
756 return "MONO_TYPE_I2";
758 return "MONO_TYPE_U2";
760 return "MONO_TYPE_I4";
762 return "MONO_TYPE_U4";
764 return "MONO_TYPE_I8";
766 return "MONO_TYPE_U8";
768 return "MONO_TYPE_R4";
770 return "MONO_TYPE_R8";
771 case MONO_TYPE_STRING
:
772 return "MONO_TYPE_STRING";
774 return "MONO_TYPE_PTR";
775 case MONO_TYPE_BYREF
:
776 return "MONO_TYPE_BYREF";
777 case MONO_TYPE_VALUETYPE
:
778 return "MONO_TYPE_VALUETYPE";
779 case MONO_TYPE_CLASS
:
780 return "MONO_TYPE_CLASS";
782 return "MONO_TYPE_VAR";
783 case MONO_TYPE_ARRAY
:
784 return "MONO_TYPE_ARRAY";
785 case MONO_TYPE_GENERICINST
:
786 return "MONO_TYPE_GENERICINST";
787 case MONO_TYPE_TYPEDBYREF
:
788 return "MONO_TYPE_TYPEDBYREF";
790 return "MONO_TYPE_I";
792 return "MONO_TYPE_U";
793 case MONO_TYPE_FNPTR
:
794 return "MONO_TYPE_FNPTR";
795 case MONO_TYPE_OBJECT
:
796 return "MONO_TYPE_OBJECT";
797 case MONO_TYPE_SZARRAY
:
798 return "MONO_TYPE_SZARRAY";
800 return "MONO_TYPE_MVAR";
801 case MONO_TYPE_CMOD_REQD
:
802 return "MONO_TYPE_CMOD_REQD";
803 case MONO_TYPE_CMOD_OPT
:
804 return "MONO_TYPE_CMOD_OPT";
805 case MONO_TYPE_INTERNAL
:
806 return "MONO_TYPE_INTERNAL";
807 case MONO_TYPE_MODIFIER
:
808 return "MONO_TYPE_MODIFIER";
809 case MONO_TYPE_SENTINEL
:
810 return "MONO_TYPE_SENTINEL";
811 case MONO_TYPE_PINNED
:
812 return "MONO_TYPE_PINNED";
819 /*========================= End of Function ========================*/
821 /*------------------------------------------------------------------*/
823 /* Name - decodeParmString */
825 /* Function - Decode a parameter string for the trace. */
827 /*------------------------------------------------------------------*/
830 decodeParmString (MonoString
*s
)
833 char *str
= mono_string_to_utf8_checked(s
, error
);
835 fprintf (trFd
, "[STRING:%p:%s], ", s
, str
);
838 mono_error_cleanup (error
);
839 fprintf (trFd
, "[STRING:%p:], ", s
);
843 /*========================= End of Function ========================*/
845 /*------------------------------------------------------------------*/
847 /* Name - decodeParm */
849 /* Function - Decode a parameter for the trace. */
851 /*------------------------------------------------------------------*/
855 decodeParm(MonoType
*type
, void *curParm
, int size
)
860 fprintf (trFd
, "[BYREF:%p], ", *((char **) curParm
));
862 simpleType
= mini_get_underlying_type(type
)->type
;
864 switch (simpleType
) {
866 fprintf (trFd
, "[INTPTR:%p], ", *((int **) curParm
));
869 fprintf (trFd
, "[UINTPTR:%p], ", *((int **) curParm
));
871 case MONO_TYPE_BOOLEAN
:
872 fprintf (trFd
, "[BOOL:%ld], ", *((gint64
*) curParm
));
874 case MONO_TYPE_CHAR
:
875 fprintf (trFd
, "[CHAR:%c], ", *((int *) curParm
));
878 fprintf (trFd
, "[INT1:%ld], ", *((gint64
*) curParm
));
881 fprintf (trFd
, "[INT2:%ld], ", *((gint64
*) curParm
));
884 fprintf (trFd
, "[INT4:%ld], ", *((gint64
*) curParm
));
887 fprintf (trFd
, "[UINT1:%lu], ", *((guint64
*) curParm
));
890 fprintf (trFd
, "[UINT2:%lu], ", *((guint64
*) curParm
));
893 fprintf (trFd
, "[UINT4:%lu], ", *((guint64
*) curParm
));
896 fprintf (trFd
, "[UINT8:%lu], ", *((guint64
*) curParm
));
898 case MONO_TYPE_STRING
: {
899 MonoString
*s
= *((MonoString
**) curParm
);
901 g_assert (((MonoObject
*) s
)->vtable
->klass
== mono_defaults
.string_class
);
902 decodeParmString (s
);
904 fprintf (trFd
, "[STRING:null], ");
908 case MONO_TYPE_CLASS
:
909 case MONO_TYPE_OBJECT
: {
910 MonoObject
*obj
= *((MonoObject
**) curParm
);
912 if ((obj
) && (obj
->vtable
)) {
913 fprintf (trFd
, "[CLASS/OBJ:");
914 klass
= obj
->vtable
->klass
;
915 fprintf (trFd
, "%p [%p] ",obj
,curParm
);
916 if (klass
== mono_defaults
.string_class
) {
917 decodeParmString ((MonoString
*)obj
);
918 } else if (klass
== mono_defaults
.int32_class
) {
919 fprintf (trFd
, "[INT32:%p:%d]",
920 obj
, *(gint32
*)((char *)obj
+ sizeof (MonoObject
)));
922 fprintf (trFd
, "[%s.%s:%p]",
923 m_class_get_name_space (klass
), m_class_get_name (klass
), obj
);
924 fprintf (trFd
, "], ");
926 fprintf (trFd
, "[OBJECT:null], ");
931 fprintf (trFd
, "[PTR:%p], ", *((gpointer
**) (curParm
)));
933 case MONO_TYPE_FNPTR
:
934 fprintf (trFd
, "[FNPTR:%p], ", *((gpointer
**) (curParm
)));
936 case MONO_TYPE_ARRAY
:
937 fprintf (trFd
, "[ARRAY:%p], ", *((gpointer
**) (curParm
)));
939 case MONO_TYPE_SZARRAY
:
940 fprintf (trFd
, "[SZARRAY:%p], ", *((gpointer
**) (curParm
)));
943 fprintf (trFd
, "[INT8:%ld], ", *((gint64
*) (curParm
)));
946 fprintf (trFd
, "[FLOAT4:%g], ", *((float *) (curParm
)));
949 fprintf (trFd
, "[FLOAT8:%g], ", *((double *) (curParm
)));
951 case MONO_TYPE_VALUETYPE
: {
953 MonoMarshalType
*info
;
955 if (m_class_is_enumtype (type
->data
.klass
)) {
956 simpleType
= mono_class_enum_basetype (type
->data
.klass
)->type
;
957 fprintf (trFd
, "{VALUETYPE} - ");
961 info
= mono_marshal_load_type_info (type
->data
.klass
);
963 if ((info
->native_size
== sizeof(float)) &&
964 (info
->num_fields
== 1) &&
965 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R4
)) {
966 fprintf (trFd
, "[FLOAT4:%f], ", *((float *) (curParm
)));
970 if ((info
->native_size
== sizeof(double)) &&
971 (info
->num_fields
== 1) &&
972 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R8
)) {
973 fprintf (trFd
, "[FLOAT8:%g], ", *((double *) (curParm
)));
977 fprintf (trFd
, "[VALUETYPE:");
978 for (i
= 0; i
< size
; i
++)
979 fprintf (trFd
, "%02x,", *((guint8
*)curParm
+i
));
980 fprintf (trFd
, "], ");
983 case MONO_TYPE_TYPEDBYREF
: {
985 fprintf (trFd
, "[TYPEDBYREF:");
986 for (i
= 0; i
< size
; i
++)
987 fprintf (trFd
, "%02x,", *((guint8
*)curParm
+i
));
992 fprintf (trFd
, "[%s], ",cvtMonoType(simpleType
));
997 /*========================= End of Function ========================*/
999 /*------------------------------------------------------------------*/
1001 /* Name - enter_method */
1003 /* Function - Perform tracing of the entry to the current */
1006 /*------------------------------------------------------------------*/
1009 enter_method (MonoMethod
*method
, RegParm
*rParm
, char *sp
)
1011 int i
, oParm
= 0, iParm
= 0;
1014 MonoMethodSignature
*sig
;
1023 sprintf(buf
, "/tmp/mono.%d.trc.%d", getpid(), curThreadNo
++);
1024 trFd
= fopen(buf
, "w");
1026 fname
= mono_method_full_name (method
, TRUE
);
1028 fprintf (trFd
, "ENTER: %s ", fname
);
1031 ip
= (*(guint64
*) (sp
+S390_RET_ADDR_OFFSET
));
1032 fprintf (trFd
, "ip: %p sp: %p - ", (gpointer
) ip
, sp
);
1037 sig
= mono_method_signature (method
);
1039 cinfo
= get_call_info (NULL
, sig
);
1041 if (cinfo
->struct_ret
) {
1042 fprintf (trFd
, "[STRUCTRET:%p], ", (gpointer
) rParm
->gr
[0]);
1047 gpointer
*this_arg
= (gpointer
*) rParm
->gr
[iParm
];
1048 obj
= (MonoObject
*) this_arg
;
1049 switch(m_class_get_this_arg (method
->klass
)->type
) {
1050 case MONO_TYPE_VALUETYPE
:
1052 guint64
*value
= (guint64
*) ((uintptr_t)this_arg
+ sizeof(MonoObject
));
1053 fprintf (trFd
, "this:[value:%p:%016lx], ", this_arg
, *value
);
1055 fprintf (trFd
, "this:[NULL], ");
1057 case MONO_TYPE_STRING
:
1060 klass
= obj
->vtable
->klass
;
1061 if (klass
== mono_defaults
.string_class
) {
1062 fprintf (trFd
, "this:");
1063 decodeParmString((MonoString
*)obj
);
1065 fprintf (trFd
, "this:%p[%s.%s], ",
1066 obj
, m_class_get_name_space (klass
), m_class_get_name (klass
));
1069 fprintf (trFd
, "vtable:[NULL], ");
1071 fprintf (trFd
, "this:[NULL], ");
1074 fprintf (trFd
, "this[%s]: %p, ",cvtMonoType(m_class_get_this_arg (method
->klass
)->type
),this_arg
);
1079 for (i
= 0; i
< sig
->param_count
; ++i
) {
1080 ainfo
= &cinfo
->args
[i
+ oParm
];
1081 switch (ainfo
->regtype
) {
1082 case RegTypeGeneral
:
1083 decodeParm(sig
->params
[i
], &(rParm
->gr
[ainfo
->reg
-2]), ainfo
->size
);
1087 decodeParm(sig
->params
[i
], &(rParm
->fp
[ainfo
->reg
]), ainfo
->size
);
1090 decodeParm(sig
->params
[i
], sp
+ainfo
->offset
, ainfo
->size
);
1092 case RegTypeStructByVal
:
1093 if (ainfo
->reg
!= STK_BASE
) {
1094 int offset
= sizeof(glong
) - ainfo
->size
;
1095 curParm
= &(rParm
->gr
[ainfo
->reg
-2])+offset
;
1098 curParm
= sp
+ainfo
->offset
;
1100 if (retFitsInReg (ainfo
->vtsize
))
1101 decodeParm(sig
->params
[i
],
1105 decodeParm(sig
->params
[i
],
1106 *((char **) curParm
),
1109 case RegTypeStructByAddr
:
1110 if (ainfo
->reg
!= STK_BASE
)
1111 curParm
= &(rParm
->gr
[ainfo
->reg
-2]);
1113 curParm
= sp
+ainfo
->offset
;
1115 decodeParm(sig
->params
[i
],
1116 *((char **) curParm
),
1121 fprintf (trFd
, "???, ");
1124 fprintf (trFd
, "\n");
1128 /*========================= End of Function ========================*/
1130 /*------------------------------------------------------------------*/
1132 /* Name - leave_method */
1136 /*------------------------------------------------------------------*/
1139 leave_method (MonoMethod
*method
, ...)
1146 va_start(ap
, method
);
1148 fname
= mono_method_full_name (method
, TRUE
);
1150 fprintf (trFd
, "LEAVE: %s", fname
);
1153 type
= mono_method_signature (method
)->ret
;
1156 switch (type
->type
) {
1157 case MONO_TYPE_VOID
:
1159 case MONO_TYPE_BOOLEAN
: {
1160 int val
= va_arg (ap
, int);
1162 fprintf (trFd
, "[TRUE:%d]", val
);
1164 fprintf (trFd
, "[FALSE]");
1168 case MONO_TYPE_CHAR
: {
1169 int val
= va_arg (ap
, int);
1170 fprintf (trFd
, "[CHAR:%d]", val
);
1173 case MONO_TYPE_I1
: {
1174 int val
= va_arg (ap
, int);
1175 fprintf (trFd
, "[INT1:%d]", val
);
1178 case MONO_TYPE_U1
: {
1179 int val
= va_arg (ap
, int);
1180 fprintf (trFd
, "[UINT1:%d]", val
);
1183 case MONO_TYPE_I2
: {
1184 int val
= va_arg (ap
, int);
1185 fprintf (trFd
, "[INT2:%d]", val
);
1188 case MONO_TYPE_U2
: {
1189 int val
= va_arg (ap
, int);
1190 fprintf (trFd
, "[UINT2:%d]", val
);
1193 case MONO_TYPE_I4
: {
1194 int val
= va_arg (ap
, int);
1195 fprintf (trFd
, "[INT4:%d]", val
);
1198 case MONO_TYPE_U4
: {
1199 int val
= va_arg (ap
, int);
1200 fprintf (trFd
, "[UINT4:%d]", val
);
1204 gint64 val
= va_arg (ap
, gint64
);
1205 fprintf (trFd
, "[INT:%ld]", val
);
1206 fprintf (trFd
, "]");
1210 gint64 val
= va_arg (ap
, gint64
);
1211 fprintf (trFd
, "[UINT:%lu]", val
);
1212 fprintf (trFd
, "]");
1215 case MONO_TYPE_STRING
: {
1216 MonoString
*s
= va_arg (ap
, MonoString
*);
1219 g_assert (((MonoObject
*)s
)->vtable
->klass
== mono_defaults
.string_class
);
1220 decodeParmString (s
);
1222 fprintf (trFd
, "[STRING:null], ");
1225 case MONO_TYPE_CLASS
:
1226 case MONO_TYPE_OBJECT
: {
1227 MonoObject
*o
= va_arg (ap
, MonoObject
*);
1229 if ((o
) && (o
->vtable
)) {
1230 if (o
->vtable
->klass
== mono_defaults
.boolean_class
) {
1231 fprintf (trFd
, "[BOOLEAN:%p:%d]", o
, *((guint8
*)o
+ sizeof (MonoObject
)));
1232 } else if (o
->vtable
->klass
== mono_defaults
.int32_class
) {
1233 fprintf (trFd
, "[INT32:%p:%d]", o
, *((gint32
*)((char *)o
+ sizeof (MonoObject
))));
1234 } else if (o
->vtable
->klass
== mono_defaults
.int64_class
) {
1235 fprintf (trFd
, "[INT64:%p:%ld]", o
, *((gint64
*)((char *)o
+ sizeof (MonoObject
))));
1237 fprintf (trFd
, "[%s.%s:%p]", m_class_get_name_space (o
->vtable
->klass
), m_class_get_name (o
->vtable
->klass
), o
);
1239 fprintf (trFd
, "[OBJECT:%p]", o
);
1244 case MONO_TYPE_FNPTR
:
1245 case MONO_TYPE_ARRAY
:
1246 case MONO_TYPE_SZARRAY
: {
1247 gpointer p
= va_arg (ap
, gpointer
);
1248 fprintf (trFd
, "[result=%p]", p
);
1251 case MONO_TYPE_I8
: {
1252 gint64 l
= va_arg (ap
, gint64
);
1253 fprintf (trFd
, "[LONG:%ld]", l
);
1256 case MONO_TYPE_U8
: {
1257 guint64 l
= va_arg (ap
, guint64
);
1258 fprintf (trFd
, "[ULONG:%lu]", l
);
1261 case MONO_TYPE_R4
: {
1262 double f
= va_arg (ap
, double);
1263 fprintf (trFd
, "[FLOAT4:%g]\n", f
);
1266 case MONO_TYPE_R8
: {
1267 double f
= va_arg (ap
, double);
1268 fprintf (trFd
, "[FLOAT8:%g]\n", f
);
1271 case MONO_TYPE_VALUETYPE
: {
1272 MonoMarshalType
*info
;
1273 if (m_class_is_enumtype (type
->data
.klass
)) {
1274 type
= mono_class_enum_basetype (type
->data
.klass
);
1279 info
= mono_marshal_load_type_info (type
->data
.klass
);
1281 if ((info
->native_size
== sizeof(float)) &&
1282 (info
->num_fields
== 1) &&
1283 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R4
)) {
1284 double f
= va_arg (ap
, double);
1285 fprintf (trFd
, "[FLOAT4:%g]\n", (double) f
);
1289 if ((info
->native_size
== sizeof(double)) &&
1290 (info
->num_fields
== 1) &&
1291 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R8
)) {
1292 double f
= va_arg (ap
, double);
1293 fprintf (trFd
, "[FLOAT8:%g]\n", f
);
1297 size
= mono_type_size (type
, &align
);
1300 guint32 p
= va_arg (ap
, guint32
);
1301 fprintf (trFd
, "[%02x]\n",p
);
1305 guint32 p
= va_arg (ap
, guint32
);
1306 fprintf (trFd
, "[%04x]\n",p
);
1310 guint32 p
= va_arg (ap
, guint32
);
1311 fprintf (trFd
, "[%08x]\n",p
);
1315 guint64 p
= va_arg (ap
, guint64
);
1316 fprintf (trFd
, "[%016lx]\n",p
);
1320 gpointer p
= va_arg (ap
, gpointer
);
1321 fprintf (trFd
, "[VALUETYPE] %p\n",p
);
1327 case MONO_TYPE_TYPEDBYREF
: {
1328 guint8
*p
= va_arg (ap
, gpointer
);
1330 size
= mono_type_size (type
, &align
);
1336 fprintf (trFd
, "[");
1337 for (j
= 0; p
&& j
< size
; j
++)
1338 fprintf (trFd
, "%02x,", p
[j
]);
1339 fprintf (trFd
, "]\n");
1342 fprintf (trFd
, "[TYPEDBYREF]\n");
1346 case MONO_TYPE_GENERICINST
: {
1347 fprintf (trFd
, "[GENERICINST]\n");
1350 case MONO_TYPE_MVAR
: {
1351 fprintf (trFd
, "[MVAR]\n");
1354 case MONO_TYPE_CMOD_REQD
: {
1355 fprintf (trFd
, "[CMOD_REQD]\n");
1358 case MONO_TYPE_CMOD_OPT
: {
1359 fprintf (trFd
, "[CMOD_OPT]\n");
1362 case MONO_TYPE_INTERNAL
: {
1363 fprintf (trFd
, "[INTERNAL]\n");
1367 fprintf (trFd
, "(unknown return type %x)",
1368 mono_method_signature (method
)->ret
->type
);
1371 ip
= ((gint64
) __builtin_extract_return_addr (__builtin_return_address (0)));
1372 fprintf (trFd
, " ip: %p\n", (gpointer
) ip
);
1376 /*========================= End of Function ========================*/
1378 /*------------------------------------------------------------------*/
1380 /* Name - mono_arch_cpu_init */
1382 /* Function - Perform CPU specific initialization to execute */
1385 /*------------------------------------------------------------------*/
1388 mono_arch_cpu_init (void)
1392 /*========================= End of Function ========================*/
1394 /*------------------------------------------------------------------*/
1396 /* Name - mono_arch_init. */
1398 /* Function - Initialize architecture specific code. */
1400 /*------------------------------------------------------------------*/
1403 mono_arch_init (void)
1407 mono_set_partial_sharing_supported (FALSE
);
1408 mono_os_mutex_init_recursive (&mini_arch_mutex
);
1410 ss_trigger_page
= mono_valloc (NULL
, mono_pagesize (), MONO_MMAP_READ
, MONO_MEM_ACCOUNT_OTHER
);
1411 bp_trigger_page
= mono_valloc (NULL
, mono_pagesize (), MONO_MMAP_READ
, MONO_MEM_ACCOUNT_OTHER
);
1412 mono_mprotect (bp_trigger_page
, mono_pagesize (), 0);
1414 code
= (guint8
*) &breakpointCode
;
1415 s390_basr(code
, s390_r13
, 0);
1417 s390_llong(code
, 0);
1418 s390_lg(code
, s390_r13
, 0, s390_r13
, 4);
1419 s390_lg(code
, s390_r0
, 0, s390_r13
, 0);
1422 /*========================= End of Function ========================*/
1424 /*------------------------------------------------------------------*/
1426 /* Name - mono_arch_cleanup. */
1428 /* Function - Cleanup architecture specific code . */
1430 /*------------------------------------------------------------------*/
1433 mono_arch_cleanup (void)
1435 if (ss_trigger_page
)
1436 mono_vfree (ss_trigger_page
, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER
);
1437 if (bp_trigger_page
)
1438 mono_vfree (bp_trigger_page
, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER
);
1439 mono_os_mutex_destroy (&mini_arch_mutex
);
1442 /*========================= End of Function ========================*/
1444 /*------------------------------------------------------------------*/
1446 /* Name - mono_arch_have_fast_tls */
1448 /* Function - Returns whether we use fast inlined thread local */
1449 /* storage managed access, instead of falling back */
1450 /* to native code. */
1452 /*------------------------------------------------------------------*/
1455 mono_arch_have_fast_tls (void)
1460 /*========================= End of Function ========================*/
1462 /*------------------------------------------------------------------*/
1464 /* Name - mono_arch_cpu_optimizations */
1466 /* Function - Returns the optimizations supported on this CPU */
1468 /*------------------------------------------------------------------*/
1471 mono_arch_cpu_optimizations (guint32
*exclude_mask
)
1475 /*----------------------------------------------------------*/
1476 /* No s390-specific optimizations yet */
1477 /*----------------------------------------------------------*/
1478 *exclude_mask
= MONO_OPT_LINEARS
;
1482 /*========================= End of Function ========================*/
1484 /*------------------------------------------------------------------*/
1486 /* Name - mono_arch_get_allocatable_int_vars */
1490 /*------------------------------------------------------------------*/
1493 mono_arch_get_allocatable_int_vars (MonoCompile
*cfg
)
1498 for (i
= 0; i
< cfg
->num_varinfo
; i
++) {
1499 MonoInst
*ins
= cfg
->varinfo
[i
];
1500 MonoMethodVar
*vmv
= MONO_VARINFO (cfg
, i
);
1503 if (vmv
->range
.first_use
.abs_pos
>= vmv
->range
.last_use
.abs_pos
)
1506 if (ins
->flags
& (MONO_INST_VOLATILE
|MONO_INST_INDIRECT
) ||
1507 (ins
->opcode
!= OP_LOCAL
&& ins
->opcode
!= OP_ARG
))
1510 /* we can only allocate 32 bit values */
1511 if (mono_is_regsize_var(ins
->inst_vtype
)) {
1512 g_assert (MONO_VARINFO (cfg
, i
)->reg
== -1);
1513 g_assert (i
== vmv
->idx
);
1514 vars
= mono_varlist_insert_sorted (cfg
, vars
, vmv
, FALSE
);
1521 /*========================= End of Function ========================*/
1523 /*------------------------------------------------------------------*/
1525 /* Name - mono_arch_global_int_regs */
1527 /* Function - Return a list of usable integer registers. */
1529 /*------------------------------------------------------------------*/
1532 mono_arch_get_global_int_regs (MonoCompile
*cfg
)
1535 MonoMethodHeader
*header
;
1538 header
= cfg
->header
;
1539 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
1540 cfg
->frame_reg
= s390_r11
;
1543 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1545 for (i
= 8; i
< top
; ++i
) {
1546 if ((cfg
->frame_reg
!= i
) &&
1547 //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
1548 (i
!= MONO_ARCH_IMT_REG
))
1549 regs
= g_list_prepend (regs
, GUINT_TO_POINTER (i
));
1555 /*========================= End of Function ========================*/
1557 /*------------------------------------------------------------------*/
1559 /* Name - mono_arch_flush_icache */
1561 /* Function - Flush the CPU icache. */
1563 /*------------------------------------------------------------------*/
1566 mono_arch_flush_icache (guint8
*code
, gint size
)
1570 /*========================= End of Function ========================*/
1572 /*------------------------------------------------------------------*/
1574 /* Name - add_general */
1576 /* Function - Determine code and stack size incremements for a */
1579 /*------------------------------------------------------------------*/
1582 add_general (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
)
1584 if (*gr
> S390_LAST_ARG_REG
) {
1585 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1586 ainfo
->offset
= sz
->stack_size
;
1587 ainfo
->reg
= STK_BASE
;
1588 ainfo
->regtype
= RegTypeBase
;
1589 sz
->stack_size
+= sizeof(long);
1590 sz
->local_size
+= sizeof(long);
1591 sz
->offStruct
+= sizeof(long);
1592 sz
->code_size
+= 12;
1600 /*========================= End of Function ========================*/
1602 /*------------------------------------------------------------------*/
1604 /* Name - add_stackParm */
1606 /* Function - Determine code and stack size incremements for a */
1609 /*------------------------------------------------------------------*/
1612 add_stackParm (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
, gint size
)
1614 if (*gr
> S390_LAST_ARG_REG
) {
1615 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1616 ainfo
->reg
= STK_BASE
;
1617 ainfo
->offset
= sz
->stack_size
;
1618 ainfo
->regtype
= RegTypeStructByAddrOnStack
;
1619 sz
->stack_size
+= sizeof (gpointer
);
1620 sz
->parm_size
+= sizeof(gpointer
);
1621 sz
->offStruct
+= sizeof(gpointer
);
1624 ainfo
->offset
= sz
->stack_size
;
1625 ainfo
->regtype
= RegTypeStructByAddr
;
1628 ainfo
->offparm
= sz
->offset
;
1629 sz
->offset
= S390_ALIGN(sz
->offset
+size
, sizeof(long));
1631 ainfo
->vtsize
= size
;
1632 sz
->parm_size
+= size
;
1635 /*========================= End of Function ========================*/
1637 /*------------------------------------------------------------------*/
1639 /* Name - add_float */
1641 /* Function - Determine code and stack size incremements for a */
1642 /* float parameter. */
1644 /*------------------------------------------------------------------*/
1647 add_float (guint
*fr
, size_data
*sz
, ArgInfo
*ainfo
, gboolean isDouble
)
1649 if ((*fr
) <= S390_LAST_FPARG_REG
) {
1651 ainfo
->regtype
= RegTypeFP
;
1653 ainfo
->regtype
= RegTypeFPR4
;
1659 ainfo
->offset
= sz
->stack_size
;
1660 ainfo
->reg
= STK_BASE
;
1662 sz
->stack_size
+= sizeof(double);
1663 sz
->local_size
+= sizeof(double);
1664 sz
->offStruct
+= sizeof(double);
1665 ainfo
->regtype
= RegTypeBase
;
1669 /*========================= End of Function ========================*/
1671 /*------------------------------------------------------------------*/
1673 /* Name - get_call_info */
1675 /* Function - Determine the amount of space required for code */
1676 /* and stack. In addition determine starting points */
1677 /* for stack-based parameters, and area for struct- */
1678 /* ures being returned on the stack. */
1680 /*------------------------------------------------------------------*/
1683 get_call_info (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1685 guint i
, fr
, gr
, size
, pstart
;
1686 int nParm
= sig
->hasthis
+ sig
->param_count
;
1688 guint32 simpleType
, align
;
1689 gboolean is_pinvoke
= sig
->pinvoke
;
1694 cinfo
= mono_mempool_alloc0 (mp
, sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1696 cinfo
= g_malloc0 (sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1701 cinfo
->struct_ret
= 0;
1706 sz
->offStruct
= S390_MINIMAL_STACK_SIZE
;
1707 sz
->stack_size
= S390_MINIMAL_STACK_SIZE
;
1714 /*----------------------------------------------------------*/
1715 /* We determine the size of the return code/stack in case we*/
1716 /* need to reserve a register to be used to address a stack */
1717 /* area that the callee will use. */
1718 /*----------------------------------------------------------*/
1720 ret_type
= mini_get_underlying_type (sig
->ret
);
1721 simpleType
= ret_type
->type
;
1723 switch (simpleType
) {
1732 case MONO_TYPE_OBJECT
:
1734 case MONO_TYPE_FNPTR
:
1735 cinfo
->ret
.reg
= s390_r2
;
1740 cinfo
->ret
.reg
= s390_f0
;
1745 cinfo
->ret
.reg
= s390_r2
;
1748 case MONO_TYPE_GENERICINST
:
1749 if (!mono_type_generic_inst_is_valuetype (sig
->ret
)) {
1750 cinfo
->ret
.reg
= s390_r2
;
1755 case MONO_TYPE_VALUETYPE
: {
1756 MonoClass
*klass
= mono_class_from_mono_type (sig
->ret
);
1757 if (m_class_is_enumtype (klass
)) {
1758 simpleType
= mono_class_enum_basetype (klass
)->type
;
1761 size
= mini_type_stack_size_full (m_class_get_byval_arg (klass
), NULL
, sig
->pinvoke
);
1763 cinfo
->struct_ret
= 1;
1764 cinfo
->ret
.size
= size
;
1765 cinfo
->ret
.vtsize
= size
;
1768 case MONO_TYPE_TYPEDBYREF
:
1769 size
= sizeof (MonoTypedRef
);
1770 cinfo
->struct_ret
= 1;
1771 cinfo
->ret
.size
= size
;
1772 cinfo
->ret
.vtsize
= size
;
1774 case MONO_TYPE_VOID
:
1777 g_error ("Can't handle as return value 0x%x", sig
->ret
->type
);
1783 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1784 * the first argument, allowing 'this' to be always passed in the first arg reg.
1785 * Also do this if the first argument is a reference type, since virtual calls
1786 * are sometimes made using calli without sig->hasthis set, like in the delegate
1789 if (cinfo
->struct_ret
&& !is_pinvoke
&&
1791 (sig
->param_count
> 0 &&
1792 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig
->params
[0]))))) {
1794 cinfo
->args
[nParm
].size
= sizeof (gpointer
);
1795 add_general (&gr
, sz
, cinfo
->args
+ nParm
);
1797 cinfo
->args
[nParm
].size
= sizeof (gpointer
);
1798 add_general (&gr
, sz
, &cinfo
->args
[sig
->hasthis
+ nParm
]);
1802 cinfo
->vret_arg_index
= 1;
1803 cinfo
->ret
.reg
= gr
;
1808 cinfo
->args
[nParm
].size
= sizeof (gpointer
);
1809 add_general (&gr
, sz
, cinfo
->args
+ nParm
);
1813 if (cinfo
->struct_ret
) {
1814 cinfo
->ret
.reg
= gr
;
1819 if ((sig
->call_convention
== MONO_CALL_VARARG
) && (sig
->param_count
== 0)) {
1820 gr
= S390_LAST_ARG_REG
+ 1;
1821 fr
= S390_LAST_FPARG_REG
+ 1;
1823 /* Emit the signature cookie just before the implicit arguments */
1824 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1827 /*----------------------------------------------------------*/
1828 /* We determine the size of the parameter code and stack */
1829 /* requirements by checking the types and sizes of the */
1831 /*----------------------------------------------------------*/
1833 for (i
= pstart
; i
< sig
->param_count
; ++i
) {
1836 /*--------------------------------------------------*/
1837 /* Handle vararg type calls. All args are put on */
1839 /*--------------------------------------------------*/
1840 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1841 (i
== sig
->sentinelpos
)) {
1842 gr
= S390_LAST_ARG_REG
+ 1;
1843 fr
= S390_LAST_FPARG_REG
+ 1;
1844 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1847 if (sig
->params
[i
]->byref
) {
1848 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1849 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1854 ptype
= mini_get_underlying_type (sig
->params
[i
]);
1855 simpleType
= ptype
->type
;
1856 cinfo
->args
[nParm
].type
= simpleType
;
1857 switch (simpleType
) {
1860 cinfo
->args
[nParm
].size
= sizeof(char);
1861 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1866 cinfo
->args
[nParm
].size
= sizeof(short);
1867 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1872 cinfo
->args
[nParm
].size
= sizeof(int);
1873 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1879 case MONO_TYPE_FNPTR
:
1880 case MONO_TYPE_OBJECT
:
1881 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1882 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1887 cinfo
->args
[nParm
].size
= sizeof(long long);
1888 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1892 cinfo
->args
[nParm
].size
= sizeof(float);
1893 add_float (&fr
, sz
, cinfo
->args
+nParm
, FALSE
);
1897 cinfo
->args
[nParm
].size
= sizeof(double);
1898 add_float (&fr
, sz
, cinfo
->args
+nParm
, TRUE
);
1901 case MONO_TYPE_GENERICINST
:
1902 if (!mono_type_generic_inst_is_valuetype (ptype
)) {
1903 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1904 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1909 case MONO_TYPE_VALUETYPE
: {
1910 MonoMarshalType
*info
;
1911 MonoClass
*klass
= mono_class_from_mono_type (ptype
);
1914 size
= mono_class_native_size(klass
, NULL
);
1916 size
= mono_class_value_size(klass
, NULL
);
1918 if (simpleType
!= MONO_TYPE_GENERICINST
) {
1919 info
= mono_marshal_load_type_info(klass
);
1921 if ((info
->native_size
== sizeof(float)) &&
1922 (info
->num_fields
== 1) &&
1923 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R4
)) {
1924 cinfo
->args
[nParm
].size
= sizeof(float);
1925 add_float(&fr
, sz
, cinfo
->args
+nParm
, FALSE
);
1930 if ((info
->native_size
== sizeof(double)) &&
1931 (info
->num_fields
== 1) &&
1932 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R8
)) {
1933 cinfo
->args
[nParm
].size
= sizeof(double);
1934 add_float(&fr
, sz
, cinfo
->args
+nParm
, TRUE
);
1940 cinfo
->args
[nParm
].vtsize
= 0;
1941 cinfo
->args
[nParm
].size
= 0;
1944 /*----------------------------------*/
1945 /* On S/390, structures of size 1, */
1946 /* 2, 4, and 8 bytes are passed in */
1947 /* (a) register(s). */
1948 /*----------------------------------*/
1954 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1955 cinfo
->args
[nParm
].size
= size
;
1956 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1958 sz
->local_size
+= sizeof(long);
1961 add_stackParm(&gr
, sz
, cinfo
->args
+nParm
, size
);
1966 case MONO_TYPE_TYPEDBYREF
: {
1967 int size
= sizeof (MonoTypedRef
);
1969 cinfo
->args
[nParm
].vtsize
= 0;
1970 cinfo
->args
[nParm
].size
= 0;
1973 /*----------------------------------*/
1974 /* On S/390, structures of size 1, */
1975 /* 2, 4, and 8 bytes are passed in */
1976 /* (a) register(s). */
1977 /*----------------------------------*/
1983 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1984 cinfo
->args
[nParm
].size
= size
;
1985 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1987 sz
->local_size
+= sizeof(long);
1990 add_stackParm(&gr
, sz
, cinfo
->args
+nParm
, size
);
1996 g_error ("Can't trampoline 0x%x", ptype
);
2000 /*----------------------------------------------------------*/
2001 /* Handle the case where there are no implicit arguments */
2002 /*----------------------------------------------------------*/
2003 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
2006 (sig
->param_count
== sig
->sentinelpos
)) {
2007 gr
= S390_LAST_ARG_REG
+ 1;
2008 fr
= S390_LAST_FPARG_REG
+ 1;
2009 add_general (&gr
, sz
, &cinfo
->sigCookie
);
2012 /*----------------------------------------------------------*/
2013 /* If we are passing a structure back then if it won't be */
2014 /* in a register(s) then we make room at the end of the */
2015 /* parameters that may have been placed on the stack */
2016 /*----------------------------------------------------------*/
2017 if (cinfo
->struct_ret
) {
2018 cinfo
->ret
.offset
= sz
->stack_size
;
2019 switch (cinfo
->ret
.size
) {
2027 sz
->stack_size
+= S390_ALIGN(cinfo
->ret
.size
, align
);
2032 sz
->stack_size
= sz
->stack_size
+ sz
->local_size
+ sz
->parm_size
+
2034 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
2039 /*========================= End of Function ========================*/
2041 /*------------------------------------------------------------------*/
2043 /* Name - mono_arch_allocate_vars */
2045 /* Function - Set var information according to the calling */
2046 /* convention for S/390. The local var stuff should */
2047 /* most likely be split in another method. */
2049 /* Parameter - @m - Compile unit. */
2051 /*------------------------------------------------------------------*/
2054 mono_arch_allocate_vars (MonoCompile
*cfg
)
2056 MonoMethodSignature
*sig
;
2057 MonoMethodHeader
*header
;
2060 int iParm
, iVar
, offset
, align
, size
, curinst
;
2061 int frame_reg
= STK_BASE
;
2064 header
= cfg
->header
;
2066 cfg
->flags
|= MONO_CFG_HAS_SPILLUP
;
2068 /*---------------------------------------------------------*/
2069 /* We use the frame register also for any method that has */
2070 /* filter clauses. This way, when the handlers are called, */
2071 /* the code will reference local variables using the frame */
2072 /* reg instead of the stack pointer: if we had to restore */
2073 /* the stack pointer, we'd corrupt the method frames that */
2074 /* are already on the stack (since filters get called */
2075 /* before stack unwinding happens) when the filter code */
2076 /* would call any method. */
2077 /*---------------------------------------------------------*/
2078 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
2079 frame_reg
= s390_r11
;
2081 cfg
->frame_reg
= frame_reg
;
2083 cfg
->arch
.bkchain_reg
= -1;
2085 if (frame_reg
!= STK_BASE
)
2086 cfg
->used_int_regs
|= (1LL << frame_reg
);
2088 sig
= mono_method_signature (cfg
->method
);
2090 cinfo
= get_call_info (cfg
->mempool
, sig
);
2092 if (!cinfo
->struct_ret
) {
2093 switch (mini_get_underlying_type (sig
->ret
)->type
) {
2094 case MONO_TYPE_VOID
:
2097 cfg
->ret
->opcode
= OP_REGVAR
;
2098 cfg
->ret
->dreg
= s390_r2
;
2103 /*--------------------------------------------------------------*/
2104 /* local vars are at a positive offset from the stack pointer */
2105 /* also note that if the function uses alloca, we use s390_r11 */
2106 /* to point at the local variables. */
2107 /* add parameter area size for called functions */
2108 /*--------------------------------------------------------------*/
2109 if (cfg
->param_area
== 0)
2110 offset
= S390_MINIMAL_STACK_SIZE
;
2112 offset
= cfg
->param_area
;
2114 cfg
->sig_cookie
= 0;
2116 if (cinfo
->struct_ret
) {
2117 inst
= cfg
->vret_addr
;
2118 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
2119 inst
->inst_offset
= offset
;
2120 inst
->opcode
= OP_REGOFFSET
;
2121 inst
->inst_basereg
= frame_reg
;
2122 offset
+= sizeof(gpointer
);
2123 if (G_UNLIKELY (cfg
->verbose_level
> 1)) {
2124 printf ("vret_addr =");
2125 mono_print_ins (cfg
->vret_addr
);
2130 inst
= cfg
->args
[0];
2131 if (inst
->opcode
!= OP_REGVAR
) {
2132 inst
->opcode
= OP_REGOFFSET
;
2133 inst
->inst_basereg
= frame_reg
;
2134 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
2135 inst
->inst_offset
= offset
;
2136 offset
+= sizeof (gpointer
);
2143 eArg
= sig
->param_count
+ sArg
;
2145 if (sig
->call_convention
== MONO_CALL_VARARG
)
2146 cfg
->sig_cookie
+= S390_MINIMAL_STACK_SIZE
;
2148 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
2149 inst
= cfg
->args
[curinst
];
2150 if (inst
->opcode
!= OP_REGVAR
) {
2151 switch (cinfo
->args
[iParm
].regtype
) {
2152 case RegTypeStructByAddr
: {
2155 size
= sizeof (gpointer
);
2157 inst
->opcode
= OP_REGOFFSET
;
2158 inst
->inst_basereg
= frame_reg
;
2159 offset
= S390_ALIGN (offset
, sizeof (gpointer
));
2160 inst
->inst_offset
= offset
;
2162 /* Add a level of indirection */
2163 MONO_INST_NEW (cfg
, indir
, 0);
2165 inst
->opcode
= OP_VTARG_ADDR
;
2166 inst
->inst_left
= indir
;
2169 case RegTypeStructByAddrOnStack
: {
2172 size
= sizeof (gpointer
);
2174 /* Similar to the == STK_BASE case below */
2175 cfg
->arch
.bkchain_reg
= s390_r12
;
2176 cfg
->used_int_regs
|= 1 << cfg
->arch
.bkchain_reg
;
2178 inst
->opcode
= OP_REGOFFSET
;
2179 inst
->dreg
= mono_alloc_preg (cfg
);
2180 inst
->inst_basereg
= cfg
->arch
.bkchain_reg
;
2181 inst
->inst_offset
= cinfo
->args
[iParm
].offset
;
2183 /* Add a level of indirection */
2184 MONO_INST_NEW (cfg
, indir
, 0);
2186 inst
->opcode
= OP_VTARG_ADDR
;
2187 inst
->inst_left
= indir
;
2190 case RegTypeStructByVal
:
2191 size
= cinfo
->args
[iParm
].size
;
2192 offset
= S390_ALIGN(offset
, size
);
2193 inst
->opcode
= OP_REGOFFSET
;
2194 inst
->inst_basereg
= frame_reg
;
2195 inst
->inst_offset
= offset
;
2198 if (cinfo
->args
[iParm
].reg
== STK_BASE
) {
2200 * These arguments are in the previous frame, so we can't
2201 * compute their offset from the current frame pointer right
2202 * now, since cfg->stack_offset is not yet known, so dedicate a
2203 * register holding the previous frame pointer.
2205 cfg
->arch
.bkchain_reg
= s390_r12
;
2206 cfg
->used_int_regs
|= 1 << cfg
->arch
.bkchain_reg
;
2208 inst
->opcode
= OP_REGOFFSET
;
2209 inst
->inst_basereg
= cfg
->arch
.bkchain_reg
;
2210 size
= (cinfo
->args
[iParm
].size
< 8
2211 ? 8 - cinfo
->args
[iParm
].size
2213 inst
->inst_offset
= cinfo
->args
[iParm
].offset
+ size
;
2214 size
= sizeof (long);
2216 inst
->opcode
= OP_REGOFFSET
;
2217 inst
->inst_basereg
= frame_reg
;
2218 size
= (cinfo
->args
[iParm
].size
< 8
2221 offset
= S390_ALIGN(offset
, size
);
2222 if (cfg
->method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
)
2223 inst
->inst_offset
= offset
;
2225 inst
->inst_offset
= offset
+ (8 - size
);
2229 offset
+= MAX(size
, 8);
2234 cfg
->locals_min_stack_offset
= offset
;
2236 curinst
= cfg
->locals_start
;
2237 for (iVar
= curinst
; iVar
< cfg
->num_varinfo
; ++iVar
) {
2238 inst
= cfg
->varinfo
[iVar
];
2239 if ((inst
->flags
& MONO_INST_IS_DEAD
) ||
2240 (inst
->opcode
== OP_REGVAR
))
2243 /*--------------------------------------------------*/
2244 /* inst->backend.is_pinvoke indicates native sized */
2245 /* value typs this is used by the pinvoke wrappers */
2246 /* when they call functions returning structure */
2247 /*--------------------------------------------------*/
2248 if (inst
->backend
.is_pinvoke
&& MONO_TYPE_ISSTRUCT (inst
->inst_vtype
))
2249 size
= mono_class_native_size (mono_class_from_mono_type(inst
->inst_vtype
),
2250 (guint32
*) &align
);
2252 size
= mono_type_size (inst
->inst_vtype
, &align
);
2254 offset
= S390_ALIGN(offset
, align
);
2255 inst
->inst_offset
= offset
;
2256 inst
->opcode
= OP_REGOFFSET
;
2257 inst
->inst_basereg
= frame_reg
;
2259 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2260 iVar
, inst
->inst_offset
, size
));
2263 cfg
->locals_max_stack_offset
= offset
;
2265 /*------------------------------------------------------*/
2266 /* Allow space for the trace method stack area if needed*/
2267 /*------------------------------------------------------*/
2268 if ((mono_jit_trace_calls
!= NULL
&& mono_trace_eval (cfg
->method
)))
2269 offset
+= S390_TRACE_STACK_SIZE
;
2271 /*------------------------------------------------------*/
2272 /* Reserve space to save LMF and caller saved registers */
2273 /*------------------------------------------------------*/
2274 if (cfg
->method
->save_lmf
)
2275 offset
+= sizeof (MonoLMF
);
2277 /*------------------------------------------------------*/
2278 /* align the offset */
2279 /*------------------------------------------------------*/
2280 cfg
->stack_offset
= S390_ALIGN(offset
, S390_STACK_ALIGNMENT
);
2282 /*------------------------------------------------------*/
2283 /* Fix offsets for args whose value is in parent frame */
2284 /*------------------------------------------------------*/
2285 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
2286 inst
= cfg
->args
[iParm
];
2288 if (inst
->opcode
== OP_S390_STKARG
) {
2289 inst
->opcode
= OP_REGOFFSET
;
2290 inst
->inst_offset
+= cfg
->stack_offset
;
2295 /*========================= End of Function ========================*/
2297 /*------------------------------------------------------------------*/
2299 /* Name - mono_arch_create_vars */
2301 /*------------------------------------------------------------------*/
2304 mono_arch_create_vars (MonoCompile
*cfg
)
2306 MonoMethodSignature
*sig
;
2309 sig
= mono_method_signature (cfg
->method
);
2311 cinfo
= get_call_info (cfg
->mempool
, sig
);
2313 if (cinfo
->struct_ret
) {
2314 cfg
->vret_addr
= mono_compile_create_var (cfg
, mono_get_int_type (), OP_ARG
);
2315 if (G_UNLIKELY (cfg
->verbose_level
> 1)) {
2316 printf ("vret_addr = ");
2317 mono_print_ins (cfg
->vret_addr
);
2322 /*========================= End of Function ========================*/
2324 /*------------------------------------------------------------------*/
2326 /* Name - add_outarg_reg2. */
2328 /*------------------------------------------------------------------*/
2331 add_outarg_reg2 (MonoCompile
*cfg
, MonoCallInst
*call
, ArgStorage storage
, int reg
, MonoInst
*tree
)
2336 case RegTypeGeneral
:
2337 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
2338 ins
->dreg
= mono_alloc_ireg (cfg
);
2339 ins
->sreg1
= tree
->dreg
;
2340 MONO_ADD_INS (cfg
->cbb
, ins
);
2341 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, FALSE
);
2344 MONO_INST_NEW (cfg
, ins
, OP_FMOVE
);
2345 ins
->dreg
= mono_alloc_freg (cfg
);
2346 ins
->sreg1
= tree
->dreg
;
2347 MONO_ADD_INS (cfg
->cbb
, ins
);
2348 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, TRUE
);
2351 MONO_INST_NEW (cfg
, ins
, OP_S390_SETF4RET
);
2352 ins
->dreg
= mono_alloc_freg (cfg
);
2353 ins
->sreg1
= tree
->dreg
;
2354 MONO_ADD_INS (cfg
->cbb
, ins
);
2355 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, TRUE
);
2358 g_assert_not_reached ();
2362 /*========================= End of Function ========================*/
2364 /*------------------------------------------------------------------*/
2366 /* Name - emit_sig_cookie. */
2368 /*------------------------------------------------------------------*/
2371 emit_sig_cookie (MonoCompile
*cfg
, MonoCallInst
*call
, CallInfo
*cinfo
)
2373 MonoMethodSignature
*tmpSig
;
2376 cfg
->disable_aot
= TRUE
;
2378 /*----------------------------------------------------------*/
2379 /* mono_ArgIterator_Setup assumes the signature cookie is */
2380 /* passed first and all the arguments which were before it */
2381 /* passed on the stack after the signature. So compensate */
2382 /* by passing a different signature. */
2383 /*----------------------------------------------------------*/
2384 tmpSig
= mono_metadata_signature_dup (call
->signature
);
2385 tmpSig
->param_count
-= call
->signature
->sentinelpos
;
2386 tmpSig
->sentinelpos
= 0;
2387 if (tmpSig
->param_count
> 0)
2388 memcpy (tmpSig
->params
,
2389 call
->signature
->params
+ call
->signature
->sentinelpos
,
2390 tmpSig
->param_count
* sizeof(MonoType
*));
2392 MONO_INST_NEW (cfg
, sig_arg
, OP_ICONST
);
2393 sig_arg
->dreg
= mono_alloc_ireg (cfg
);
2394 sig_arg
->inst_p0
= tmpSig
;
2395 MONO_ADD_INS (cfg
->cbb
, sig_arg
);
2397 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORE_MEMBASE_REG
, STK_BASE
,
2398 cinfo
->sigCookie
.offset
, sig_arg
->dreg
);
2401 /*========================= End of Function ========================*/
2403 /*------------------------------------------------------------------*/
2405 /* Name - mono_arch_emit_call */
2407 /*------------------------------------------------------------------*/
2410 mono_arch_emit_call (MonoCompile
*cfg
, MonoCallInst
*call
)
2413 MonoMethodSignature
*sig
;
2415 int i
, n
, lParamArea
;
2417 ArgInfo
*ainfo
= NULL
;
2419 MonoMethodHeader
*header
;
2422 sig
= call
->signature
;
2423 n
= sig
->param_count
+ sig
->hasthis
;
2424 DEBUG (g_print ("Call requires: %d parameters\n",n
));
2426 cinfo
= get_call_info (cfg
->mempool
, sig
);
2428 stackSize
= cinfo
->sz
.stack_size
+ cinfo
->sz
.local_size
+
2429 cinfo
->sz
.parm_size
+ cinfo
->sz
.offset
;
2430 call
->stack_usage
= MAX(stackSize
, call
->stack_usage
);
2431 lParamArea
= MAX((call
->stack_usage
-S390_MINIMAL_STACK_SIZE
-cinfo
->sz
.parm_size
), 0);
2432 cfg
->param_area
= MAX(((signed) cfg
->param_area
), lParamArea
);
2433 cfg
->flags
|= MONO_CFG_HAS_CALLS
;
2435 if (cinfo
->struct_ret
) {
2436 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
2437 ins
->sreg1
= call
->vret_var
->dreg
;
2438 ins
->dreg
= mono_alloc_preg (cfg
);
2439 MONO_ADD_INS (cfg
->cbb
, ins
);
2440 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, cinfo
->ret
.reg
, FALSE
);
2443 header
= cfg
->header
;
2444 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
2449 for (i
= 0; i
< n
; ++i
) {
2452 ainfo
= cinfo
->args
+ i
;
2453 if (i
>= sig
->hasthis
)
2454 t
= sig
->params
[i
- sig
->hasthis
];
2456 t
= mono_get_int_type ();
2457 t
= mini_get_underlying_type (t
);
2459 in
= call
->args
[i
];
2461 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
2463 (i
== sig
->sentinelpos
)) {
2464 emit_sig_cookie (cfg
, call
, cinfo
);
2467 switch (ainfo
->regtype
) {
2468 case RegTypeGeneral
:
2469 add_outarg_reg2 (cfg
, call
, ainfo
->regtype
, ainfo
->reg
, in
);
2473 if (MONO_TYPE_ISSTRUCT (t
)) {
2474 /* Valuetype passed in one fp register */
2475 ainfo
->regtype
= RegTypeStructByValInFP
;
2478 add_outarg_reg2 (cfg
, call
, ainfo
->regtype
, ainfo
->reg
, in
);
2481 case RegTypeStructByVal
:
2482 case RegTypeStructByAddr
:
2483 case RegTypeStructByAddrOnStack
: {
2487 if (sig
->params
[i
- sig
->hasthis
]->type
== MONO_TYPE_TYPEDBYREF
) {
2488 size
= sizeof (MonoTypedRef
);
2489 align
= sizeof (gpointer
);
2493 size
= mono_type_native_stack_size (m_class_get_byval_arg (in
->klass
), &align
);
2496 * Other backends use mono_type_stack_size (), but that
2497 * aligns the size to 8, which is larger than the size of
2498 * the source, leading to reads of invalid memory if the
2499 * source is at the end of address space.
2501 size
= mono_class_value_size (in
->klass
, &align
);
2504 g_assert (in
->klass
);
2506 ainfo
->offparm
+= cinfo
->sz
.offStruct
;
2508 MONO_INST_NEW (cfg
, ins
, OP_OUTARG_VT
);
2509 ins
->sreg1
= in
->dreg
;
2510 ins
->klass
= in
->klass
;
2511 ins
->backend
.size
= ainfo
->size
;
2512 ins
->inst_p0
= call
;
2513 ins
->inst_p1
= mono_mempool_alloc (cfg
->mempool
, sizeof (ArgInfo
));
2514 memcpy (ins
->inst_p1
, ainfo
, sizeof (ArgInfo
));
2516 MONO_ADD_INS (cfg
->cbb
, ins
);
2518 if (ainfo
->regtype
== RegTypeStructByAddr
) {
2520 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2521 * use the normal OUTARG opcodes to pass the address of the location to
2524 int treg
= mono_alloc_preg (cfg
);
2525 MONO_EMIT_NEW_BIALU_IMM (cfg
, OP_ADD_IMM
, treg
,
2526 frmReg
, ainfo
->offparm
);
2527 mono_call_inst_add_outarg_reg (cfg
, call
, treg
, ainfo
->reg
, FALSE
);
2528 } else if (ainfo
->regtype
== RegTypeStructByAddrOnStack
) {
2529 /* The address of the valuetype is passed on the stack */
2530 int treg
= mono_alloc_preg (cfg
);
2531 MONO_EMIT_NEW_BIALU_IMM (cfg
, OP_ADD_IMM
, treg
,
2532 frmReg
, ainfo
->offparm
);
2533 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORE_MEMBASE_REG
,
2534 ainfo
->reg
, ainfo
->offset
, treg
);
2536 if (cfg
->compute_gc_maps
) {
2539 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg
, def
, ainfo
->offset
, t
);
2545 if (!t
->byref
&& t
->type
== MONO_TYPE_R4
) {
2546 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORER4_MEMBASE_REG
,
2547 STK_BASE
, ainfo
->offset
+ 4,
2549 } else if (!t
->byref
&& (t
->type
== MONO_TYPE_R8
)) {
2550 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORER8_MEMBASE_REG
,
2551 STK_BASE
, ainfo
->offset
,
2554 MONO_INST_NEW (cfg
, ins
, OP_STORE_MEMBASE_REG
);
2555 ins
->inst_destbasereg
= STK_BASE
;
2556 ins
->inst_offset
= ainfo
->offset
;
2557 ins
->sreg1
= in
->dreg
;
2558 MONO_ADD_INS (cfg
->cbb
, ins
);
2562 g_assert_not_reached ();
2568 * Handle the case where there are no implicit arguments
2570 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
2572 (i
== sig
->sentinelpos
)) {
2573 emit_sig_cookie (cfg
, call
, cinfo
);
2577 /*========================= End of Function ========================*/
2579 /*------------------------------------------------------------------*/
2581 /* Name - mono_arch_emit_outarg_vt */
2583 /*------------------------------------------------------------------*/
2586 mono_arch_emit_outarg_vt (MonoCompile
*cfg
, MonoInst
*ins
, MonoInst
*src
)
2588 MonoCallInst
*call
= (MonoCallInst
*)ins
->inst_p0
;
2589 ArgInfo
*ainfo
= (ArgInfo
*)ins
->inst_p1
;
2590 int size
= ins
->backend
.size
;
2592 if (ainfo
->regtype
== RegTypeStructByVal
) {
2594 arg->ins.sreg1 = ainfo->reg;
2595 arg->ins.opcode = OP_OUTARG_VT;
2596 arg->size = ainfo->size;
2597 arg->offset = ainfo->offset;
2598 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2600 if (ainfo
->reg
!= STK_BASE
) {
2601 MONO_OUTPUT_VTR (cfg
, size
, ainfo
->reg
, src
->dreg
, 0);
2603 MONO_OUTPUT_VTS (cfg
, size
, ainfo
->reg
, ainfo
->offset
,
2606 } else if (ainfo
->regtype
== RegTypeStructByValInFP
) {
2607 int dreg
= mono_alloc_freg (cfg
);
2609 if (ainfo
->size
== 4) {
2610 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg
, OP_LOADR4_MEMBASE
, dreg
, src
->dreg
, 0);
2611 MONO_EMIT_NEW_UNALU (cfg
, OP_S390_SETF4RET
, dreg
, dreg
);
2613 g_assert (ainfo
->size
== 8);
2615 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg
, OP_LOADR8_MEMBASE
, dreg
, src
->dreg
, 0);
2618 mono_call_inst_add_outarg_reg (cfg
, call
, dreg
, ainfo
->reg
, TRUE
);
2621 MonoMethodHeader
*header
;
2624 header
= mono_method_get_header_checked (cfg
->method
, error
);
2625 mono_error_assert_ok (error
); /* FIXME don't swallow the error */
2626 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
2631 MONO_EMIT_NEW_MOVE (cfg
, srcReg
, ainfo
->offparm
,
2632 src
->dreg
, 0, size
);
2634 if (cfg
->compute_gc_maps
) {
2637 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg
, def
, ainfo
->offset
, m_class_get_byval_arg (ins
->klass
));
2642 /*========================= End of Function ========================*/
2644 /*------------------------------------------------------------------*/
2646 /* Name - mono_arch_emit_setret */
2648 /*------------------------------------------------------------------*/
2651 mono_arch_emit_setret (MonoCompile
*cfg
, MonoMethod
*method
, MonoInst
*val
)
2653 MonoType
*ret
= mini_get_underlying_type (mono_method_signature (method
)->ret
);
2656 if (ret
->type
== MONO_TYPE_R4
) {
2657 MONO_EMIT_NEW_UNALU (cfg
, OP_S390_SETF4RET
, s390_f0
, val
->dreg
);
2659 } else if (ret
->type
== MONO_TYPE_R8
) {
2660 MONO_EMIT_NEW_UNALU (cfg
, OP_FMOVE
, s390_f0
, val
->dreg
);
2665 MONO_EMIT_NEW_UNALU (cfg
, OP_MOVE
, cfg
->ret
->dreg
, val
->dreg
);
2668 /*========================= End of Function ========================*/
2670 /*------------------------------------------------------------------*/
2672 /* Name - mono_arch_instrument_prolog */
2674 /* Function - Create an "instrumented" prolog. */
2676 /*------------------------------------------------------------------*/
2679 mono_arch_instrument_prolog (MonoCompile
*cfg
, void *func
, void *p
,
2680 gboolean enable_arguments
)
2687 parmOffset
= cfg
->stack_usage
- S390_TRACE_STACK_SIZE
- cfg
->arch
.fpSize
;
2688 if (cfg
->method
->save_lmf
)
2689 parmOffset
-= sizeof(MonoLMF
);
2690 fpOffset
= parmOffset
+ (5*sizeof(gpointer
));
2693 s390_stmg (code
, s390_r2
, s390_r6
, STK_BASE
, parmOffset
);
2694 s390_stdy (code
, s390_f0
, 0, STK_BASE
, fpOffset
);
2695 s390_stdy (code
, s390_f2
, 0, STK_BASE
, fpOffset
+sizeof(gdouble
));
2696 s390_stdy (code
, s390_f4
, 0, STK_BASE
, fpOffset
+2*sizeof(gdouble
));
2697 s390_stdy (code
, s390_f6
, 0, STK_BASE
, fpOffset
+3*sizeof(gdouble
));
2698 S390_SET (code
, s390_r1
, func
);
2699 S390_SET (code
, s390_r2
, cfg
->method
);
2700 s390_lay (code
, s390_r3
, 0, STK_BASE
, parmOffset
);
2701 s390_lgr (code
, s390_r4
, STK_BASE
);
2702 s390_aghi (code
, s390_r4
, cfg
->stack_usage
);
2703 s390_basr (code
, s390_r14
, s390_r1
);
2704 s390_ldy (code
, s390_f6
, 0, STK_BASE
, fpOffset
+3*sizeof(gdouble
));
2705 s390_ldy (code
, s390_f4
, 0, STK_BASE
, fpOffset
+2*sizeof(gdouble
));
2706 s390_ldy (code
, s390_f2
, 0, STK_BASE
, fpOffset
+sizeof(gdouble
));
2707 s390_ldy (code
, s390_f0
, 0, STK_BASE
, fpOffset
);
2708 s390_lmg (code
, s390_r2
, s390_r6
, STK_BASE
, parmOffset
);
2713 /*========================= End of Function ========================*/
2715 /*------------------------------------------------------------------*/
2717 /* Name - mono_arch_instrument_epilog */
2719 /* Function - Create an epilog that will handle the returned */
2720 /* values used in instrumentation. */
2722 /*------------------------------------------------------------------*/
2725 mono_arch_instrument_epilog (MonoCompile
*cfg
, void *func
, void *p
, gboolean enable_arguments
)
2728 int save_mode
= SAVE_NONE
,
2730 MonoMethod
*method
= cfg
->method
;
2731 int rtype
= mini_get_underlying_type (mono_method_signature (method
)->ret
)->type
;
2733 set_code_cursor (cfg
, code
);
2734 /*-----------------------------------------*/
2735 /* We need about 128 bytes of instructions */
2736 /*-----------------------------------------*/
2737 code
= realloc_code (cfg
, 128);
2739 saveOffset
= cfg
->stack_usage
- S390_TRACE_STACK_SIZE
- cfg
->arch
.fpSize
;
2740 if (method
->save_lmf
)
2741 saveOffset
-= sizeof(MonoLMF
);
2745 case MONO_TYPE_VOID
:
2746 /* special case string .ctor icall */
2747 if (strcmp (".ctor", method
->name
) && method
->klass
== mono_defaults
.string_class
)
2748 save_mode
= SAVE_ONE
;
2750 save_mode
= SAVE_NONE
;
2754 save_mode
= SAVE_ONE
;
2757 save_mode
= SAVE_R4
;
2760 save_mode
= SAVE_R8
;
2762 case MONO_TYPE_VALUETYPE
:
2763 if (m_class_is_enumtype (mono_method_signature (method
)->ret
->data
.klass
)) {
2764 rtype
= mono_class_enum_basetype (mono_method_signature (method
)->ret
->data
.klass
)->type
;
2767 save_mode
= SAVE_STRUCT
;
2770 save_mode
= SAVE_ONE
;
2774 switch (save_mode
) {
2776 s390_stg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
2777 if (enable_arguments
) {
2778 s390_lgr (code
, s390_r3
, s390_r2
);
2782 s390_std (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
2783 if (enable_arguments
) {
2784 s390_ldebr (code
, s390_f0
, s390_f0
);
2788 s390_std (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
2791 s390_stg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
2792 if (enable_arguments
) {
2793 s390_lg (code
, s390_r3
, 0, cfg
->frame_reg
,
2794 S390_MINIMAL_STACK_SIZE
+cfg
->param_area
);
2802 S390_SET (code
, s390_r1
, func
);
2803 S390_SET (code
, s390_r2
, cfg
->method
);
2804 s390_basr (code
, s390_r14
, s390_r1
);
2806 switch (save_mode
) {
2808 s390_lg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
2812 s390_ld (code
, s390_f0
, 0, cfg
->frame_reg
, saveOffset
);
2815 s390_lg (code
, s390_r2
, 0, cfg
->frame_reg
, saveOffset
);
2825 /*========================= End of Function ========================*/
2827 /*------------------------------------------------------------------*/
2829 /* Name - compare_and_branch */
2831 /* Function - Form a peephole pass at the code looking for */
2832 /* simple optimizations. */
2834 /*------------------------------------------------------------------*/
2837 compare_and_branch(MonoBasicBlock
*bb
, MonoInst
*ins
, int cc
, gboolean logical
)
2841 if (mono_hwcap_s390x_has_gie
) {
2842 last
= mono_inst_prev (ins
, FILTER_IL_SEQ_POINT
);
2843 ins
->sreg1
= last
->sreg1
;
2844 ins
->sreg2
= last
->sreg2
;
2846 switch(last
->opcode
) {
2849 ins
->opcode
= OP_S390_CLRJ
;
2851 ins
->opcode
= OP_S390_CRJ
;
2852 MONO_DELETE_INS(bb
, last
);
2857 ins
->opcode
= OP_S390_CLGRJ
;
2859 ins
->opcode
= OP_S390_CGRJ
;
2860 MONO_DELETE_INS(bb
, last
);
2862 case OP_ICOMPARE_IMM
:
2863 ins
->backend
.data
= (gpointer
) last
->inst_imm
;
2865 ins
->opcode
= OP_S390_CLIJ
;
2867 ins
->opcode
= OP_S390_CIJ
;
2868 MONO_DELETE_INS(bb
, last
);
2870 case OP_COMPARE_IMM
:
2871 case OP_LCOMPARE_IMM
:
2872 ins
->backend
.data
= (gpointer
) last
->inst_imm
;
2874 ins
->opcode
= OP_S390_CLGIJ
;
2876 ins
->opcode
= OP_S390_CGIJ
;
2877 MONO_DELETE_INS(bb
, last
);
2883 /*========================= End of Function ========================*/
2885 /*------------------------------------------------------------------*/
2887 /* Name - mono_arch_peephole_pass_1 */
2889 /* Function - Form a peephole pass at the code looking for */
2890 /* simple optimizations. */
2892 /*------------------------------------------------------------------*/
2895 mono_arch_peephole_pass_1 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2899 MONO_BB_FOR_EACH_INS_SAFE (bb
, n
, ins
) {
2900 switch (ins
->opcode
) {
2903 compare_and_branch(bb
, ins
, S390_CC_EQ
, FALSE
);
2907 compare_and_branch(bb
, ins
, S390_CC_NE
, TRUE
);
2911 compare_and_branch(bb
, ins
, S390_CC_LT
, FALSE
);
2915 compare_and_branch(bb
, ins
, S390_CC_LT
, TRUE
);
2919 compare_and_branch(bb
, ins
, S390_CC_GT
, FALSE
);
2923 compare_and_branch(bb
, ins
, S390_CC_GT
, TRUE
);
2927 compare_and_branch(bb
, ins
, S390_CC_GE
, FALSE
);
2931 compare_and_branch(bb
, ins
, S390_CC_GE
, TRUE
);
2935 compare_and_branch(bb
, ins
, S390_CC_LE
, FALSE
);
2939 compare_and_branch(bb
, ins
, S390_CC_LE
, TRUE
);
2943 // mono_peephole_ins (bb, ins);
2948 /*========================= End of Function ========================*/
2950 /*------------------------------------------------------------------*/
2952 /* Name - mono_arch_peephole_pass_2 */
2954 /* Function - Form a peephole pass at the code looking for */
2955 /* simple optimizations. */
2957 /*------------------------------------------------------------------*/
2960 mono_arch_peephole_pass_2 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2962 MonoInst
*ins
, *n
, *last_ins
= NULL
;
2964 MONO_BB_FOR_EACH_INS_SAFE (bb
, n
, ins
) {
2965 switch (ins
->opcode
) {
2966 case OP_LOADU4_MEMBASE
:
2967 case OP_LOADI4_MEMBASE
:
2968 if (last_ins
&& (last_ins
->opcode
== OP_STOREI4_MEMBASE_REG
) &&
2969 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
2970 ins
->inst_offset
== last_ins
->inst_offset
) {
2971 ins
->opcode
= (ins
->opcode
== OP_LOADI4_MEMBASE
) ? OP_ICONV_TO_I4
: OP_ICONV_TO_U4
;
2972 ins
->sreg1
= last_ins
->sreg1
;
2976 mono_peephole_ins (bb
, ins
);
2980 /*========================= End of Function ========================*/
2982 /*------------------------------------------------------------------*/
2984 /* Name - mono_arch_lowering_pass. */
2986 /*------------------------------------------------------------------*/
2989 mono_arch_lowering_pass (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2991 MonoInst
*ins
, *next
;
2993 MONO_BB_FOR_EACH_INS_SAFE (bb
, next
, ins
) {
2994 switch (ins
->opcode
) {
2999 case OP_IDIV_UN_IMM
:
3000 case OP_IREM_UN_IMM
:
3005 case OP_LOCALLOC_IMM
:
3006 mono_decompose_op_imm (cfg
, bb
, ins
);
3009 if (!s390_is_imm16 (ins
->inst_imm
))
3010 /* This is created by the memcpy code which ignores is_inst_imm */
3011 mono_decompose_op_imm (cfg
, bb
, ins
);
3018 bb
->max_vreg
= cfg
->next_vreg
;
3021 /*========================= End of Function ========================*/
3023 /*------------------------------------------------------------------*/
3025 /* Name - emit_float_to_int */
3027 /* Function - Create instructions which will convert a floating */
3028 /* point value to integer. */
3030 /*------------------------------------------------------------------*/
3033 emit_float_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
3035 /* sreg is a float, dreg is an integer reg. */
3037 s390_cgebr (code
, dreg
, 5, sreg
);
3040 s390_ltgr (code
, dreg
, dreg
);
3042 s390_oill (code
, dreg
, 0x80);
3043 s390_lghi (code
, s390_r0
, 0xff);
3044 s390_ngr (code
, dreg
, s390_r0
);
3047 s390_ltgr (code
, dreg
, dreg
);
3049 s390_oill (code
, dreg
, 0x8000);
3050 s390_llill(code
, s390_r0
, 0xffff);
3051 s390_ngr (code
, dreg
, s390_r0
);
3056 S390_SET (code
, s390_r13
, 0x4f000000u
);
3057 s390_ldgr (code
, s390_f14
, s390_r13
);
3058 s390_ler (code
, s390_f15
, sreg
);
3059 s390_cebr (code
, s390_f15
, s390_f14
);
3060 s390_jl (code
, 0); CODEPTR (code
, o
[0]);
3061 S390_SET (code
, s390_r13
, 0x4f800000u
);
3062 s390_ldgr (code
, s390_f14
, s390_r13
);
3063 s390_sebr (code
, s390_f15
, s390_f14
);
3064 s390_cfebr (code
, dreg
, 7, s390_f15
);
3066 PTRSLOT (code
, o
[0]);
3067 s390_cfebr (code
, dreg
, 5, sreg
);
3070 s390_lghi (code
, s390_r0
, 0xff);
3071 s390_ngr (code
, dreg
, s390_r0
);
3074 s390_llill(code
, s390_r0
, 0xffff);
3075 s390_ngr (code
, dreg
, s390_r0
);
3082 /*========================= End of Function ========================*/
3084 /*------------------------------------------------------------------*/
3086 /* Name - emit_double_to_int */
3088 /* Function - Create instructions which will convert a floating */
3089 /* point value to integer. */
3091 /*------------------------------------------------------------------*/
3094 emit_double_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
3096 /* sreg is a float, dreg is an integer reg. */
3098 s390_cgdbr (code
, dreg
, 5, sreg
);
3101 s390_ltgr (code
, dreg
, dreg
);
3103 s390_oill (code
, dreg
, 0x80);
3104 s390_lghi (code
, s390_r0
, 0xff);
3105 s390_ngr (code
, dreg
, s390_r0
);
3108 s390_ltgr (code
, dreg
, dreg
);
3110 s390_oill (code
, dreg
, 0x8000);
3111 s390_llill(code
, s390_r0
, 0xffff);
3112 s390_ngr (code
, dreg
, s390_r0
);
3117 S390_SET (code
, s390_r13
, 0x41e0000000000000llu
);
3118 s390_ldgr (code
, s390_f14
, s390_r13
);
3119 s390_ldr (code
, s390_f15
, sreg
);
3120 s390_cdbr (code
, s390_f15
, s390_f14
);
3121 s390_jl (code
, 0); CODEPTR (code
, o
[0]);
3122 S390_SET (code
, s390_r13
, 0x41f0000000000000llu
);
3123 s390_ldgr (code
, s390_f14
, s390_r13
);
3124 s390_sdbr (code
, s390_f15
, s390_f14
);
3125 s390_cfdbr (code
, dreg
, 7, s390_f15
);
3127 PTRSLOT (code
, o
[0]);
3128 s390_cfdbr (code
, dreg
, 5, sreg
);
3131 s390_lghi (code
, s390_r0
, 0xff);
3132 s390_ngr (code
, dreg
, s390_r0
);
3135 s390_llill(code
, s390_r0
, 0xffff);
3136 s390_ngr (code
, dreg
, s390_r0
);
3143 /*========================= End of Function ========================*/
3145 /*------------------------------------------------------------------*/
3147 /* Name - is_unsigned. */
3149 /* Function - Return TRUE if next opcode is checking for un- */
3152 /*------------------------------------------------------------------*/
3155 is_unsigned (MonoInst
*next
)
3158 (((next
->opcode
>= OP_IBNE_UN
) &&
3159 (next
->opcode
<= OP_IBLT_UN
)) ||
3160 ((next
->opcode
>= OP_LBNE_UN
) &&
3161 (next
->opcode
<= OP_LBLT_UN
)) ||
3162 ((next
->opcode
>= OP_COND_EXC_NE_UN
) &&
3163 (next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
3164 ((next
->opcode
>= OP_COND_EXC_INE_UN
) &&
3165 (next
->opcode
<= OP_COND_EXC_ILT_UN
)) ||
3166 ((next
->opcode
== OP_CLT_UN
) ||
3167 (next
->opcode
== OP_CGT_UN
) ||
3168 (next
->opcode
== OP_ICGE_UN
) ||
3169 (next
->opcode
== OP_ICLE_UN
)) ||
3170 ((next
->opcode
== OP_ICLT_UN
) ||
3171 (next
->opcode
== OP_ICGT_UN
) ||
3172 (next
->opcode
== OP_LCLT_UN
) ||
3173 (next
->opcode
== OP_LCGT_UN
))))
3179 /*========================= End of Function ========================*/
3181 /*------------------------------------------------------------------*/
3183 /* Name - mono_arch_output_basic_block */
3185 /* Function - Perform the "real" work of emitting instructions */
3186 /* that will do the work of in the basic block. */
3188 /*------------------------------------------------------------------*/
3191 mono_arch_output_basic_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
3195 guint8
*code
= cfg
->native_code
+ cfg
->code_len
;
3198 /* we don't align basic blocks of loops on s390 */
3200 if (cfg
->verbose_level
> 2)
3201 g_print ("Basic block %d starting at offset 0x%x\n", bb
->block_num
, bb
->native_offset
);
3203 MONO_BB_FOR_EACH_INS (bb
, ins
) {
3204 const guint offset
= code
- cfg
->native_code
;
3205 set_code_cursor (cfg
, code
);
3206 int max_len
= ins_get_size (ins
->opcode
);
3207 code
= realloc_code (cfg
, max_len
);
3209 mono_debug_record_line_number (cfg
, ins
, offset
);
3211 switch (ins
->opcode
) {
3212 case OP_STOREI1_MEMBASE_IMM
: {
3213 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3214 S390_LONG (code
, stcy
, stc
, s390_r0
, 0,
3215 ins
->inst_destbasereg
, ins
->inst_offset
);
3218 case OP_STOREI2_MEMBASE_IMM
: {
3219 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3220 S390_LONG (code
, sthy
, sth
, s390_r0
, 0,
3221 ins
->inst_destbasereg
, ins
->inst_offset
);
3224 case OP_STOREI4_MEMBASE_IMM
: {
3225 s390_lgfi (code
, s390_r0
, ins
->inst_imm
);
3226 S390_LONG (code
, sty
, st
, s390_r0
, 0,
3227 ins
->inst_destbasereg
, ins
->inst_offset
);
3230 case OP_STORE_MEMBASE_IMM
:
3231 case OP_STOREI8_MEMBASE_IMM
: {
3232 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3233 S390_LONG (code
, stg
, stg
, s390_r0
, 0,
3234 ins
->inst_destbasereg
, ins
->inst_offset
);
3237 case OP_STOREI1_MEMBASE_REG
: {
3238 S390_LONG (code
, stcy
, stc
, ins
->sreg1
, 0,
3239 ins
->inst_destbasereg
, ins
->inst_offset
);
3242 case OP_STOREI2_MEMBASE_REG
: {
3243 S390_LONG (code
, sthy
, sth
, ins
->sreg1
, 0,
3244 ins
->inst_destbasereg
, ins
->inst_offset
);
3247 case OP_STOREI4_MEMBASE_REG
: {
3248 S390_LONG (code
, sty
, st
, ins
->sreg1
, 0,
3249 ins
->inst_destbasereg
, ins
->inst_offset
);
3252 case OP_STORE_MEMBASE_REG
:
3253 case OP_STOREI8_MEMBASE_REG
: {
3254 S390_LONG (code
, stg
, stg
, ins
->sreg1
, 0,
3255 ins
->inst_destbasereg
, ins
->inst_offset
);
3259 g_assert_not_reached ();
3261 case OP_LOAD_MEMBASE
:
3262 case OP_LOADI8_MEMBASE
: {
3263 S390_LONG (code
, lg
, lg
, ins
->dreg
, 0,
3264 ins
->inst_basereg
, ins
->inst_offset
);
3267 case OP_LOADI4_MEMBASE
: {
3268 S390_LONG (code
, lgf
, lgf
, ins
->dreg
, 0,
3269 ins
->inst_basereg
, ins
->inst_offset
);
3272 case OP_LOADU4_MEMBASE
: {
3273 S390_LONG (code
, llgf
, llgf
, ins
->dreg
, 0,
3274 ins
->inst_basereg
, ins
->inst_offset
);
3277 case OP_LOADU1_MEMBASE
: {
3278 S390_LONG (code
, llgc
, llgc
, ins
->dreg
, 0,
3279 ins
->inst_basereg
, ins
->inst_offset
);
3282 case OP_LOADI1_MEMBASE
: {
3283 S390_LONG (code
, lgb
, lgb
, ins
->dreg
, 0,
3284 ins
->inst_basereg
, ins
->inst_offset
);
3287 case OP_LOADU2_MEMBASE
: {
3288 S390_LONG (code
, llgh
, llgh
, ins
->dreg
, 0,
3289 ins
->inst_basereg
, ins
->inst_offset
);
3292 case OP_LOADI2_MEMBASE
: {
3293 S390_LONG (code
, lgh
, lgh
, ins
->dreg
, 0,
3294 ins
->inst_basereg
, ins
->inst_offset
);
3297 case OP_LCONV_TO_I1
: {
3298 s390_lgbr (code
, ins
->dreg
, ins
->sreg1
);
3301 case OP_LCONV_TO_I2
: {
3302 s390_lghr (code
, ins
->dreg
, ins
->sreg1
);
3305 case OP_LCONV_TO_U1
: {
3306 s390_llgcr (code
, ins
->dreg
, ins
->sreg1
);
3309 case OP_LCONV_TO_U2
: {
3310 s390_llghr (code
, ins
->dreg
, ins
->sreg1
);
3313 case OP_ICONV_TO_I1
: {
3314 s390_lgbr (code
, ins
->dreg
, ins
->sreg1
);
3317 case OP_ICONV_TO_I2
: {
3318 s390_lghr (code
, ins
->dreg
, ins
->sreg1
);
3321 case OP_ICONV_TO_U1
: {
3322 s390_llgcr (code
, ins
->dreg
, ins
->sreg1
);
3325 case OP_ICONV_TO_U2
: {
3326 s390_llghr (code
, ins
->dreg
, ins
->sreg1
);
3329 case OP_ICONV_TO_U4
: {
3330 s390_llgfr (code
, ins
->dreg
, ins
->sreg1
);
3333 case OP_ICONV_TO_I4
: {
3334 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3339 if (is_unsigned (ins
->next
))
3340 s390_clgr (code
, ins
->sreg1
, ins
->sreg2
);
3342 s390_cgr (code
, ins
->sreg1
, ins
->sreg2
);
3346 if (is_unsigned (ins
->next
))
3347 s390_clr (code
, ins
->sreg1
, ins
->sreg2
);
3349 s390_cr (code
, ins
->sreg1
, ins
->sreg2
);
3352 case OP_COMPARE_IMM
:
3353 case OP_LCOMPARE_IMM
: {
3354 gboolean branchUn
= is_unsigned (ins
->next
);
3355 if ((ins
->inst_imm
== 0) && (!branchUn
)) {
3356 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
3358 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3360 s390_clgr (code
, ins
->sreg1
, s390_r0
);
3362 s390_cgr (code
, ins
->sreg1
, s390_r0
);
3366 case OP_ICOMPARE_IMM
: {
3367 gboolean branchUn
= is_unsigned (ins
->next
);
3368 if ((ins
->inst_imm
== 0) && (!branchUn
)) {
3369 s390_ltr (code
, ins
->sreg1
, ins
->sreg1
);
3371 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3373 s390_clr (code
, ins
->sreg1
, s390_r0
);
3375 s390_cr (code
, ins
->sreg1
, s390_r0
);
3380 mono_add_patch_info (cfg
, code
- cfg
->native_code
, MONO_PATCH_INFO_ABS
,
3382 S390_CALL_TEMPLATE (code
, s390_r14
);
3386 if (mono_hwcap_s390x_has_mlt
) {
3387 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3390 s390_agr (code
, ins
->dreg
, src2
);
3395 if (mono_hwcap_s390x_has_mlt
) {
3396 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3399 s390_agr (code
, ins
->dreg
, src2
);
3405 s390_alcgr (code
, ins
->dreg
, src2
);
3409 if (mono_hwcap_s390x_has_mlt
) {
3410 if (s390_is_imm16 (ins
->inst_imm
)) {
3411 s390_aghik(code
, ins
->dreg
, ins
->sreg1
, ins
->inst_imm
);
3413 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3414 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3417 if (ins
->dreg
!= ins
->sreg1
) {
3418 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3420 if (s390_is_imm16 (ins
->inst_imm
)) {
3421 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
3422 } else if (s390_is_imm32 (ins
->inst_imm
)) {
3423 s390_agfi (code
, ins
->dreg
, ins
->inst_imm
);
3425 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3426 s390_agr (code
, ins
->dreg
, s390_r0
);
3432 if (ins
->dreg
!= ins
->sreg1
) {
3433 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3435 if (s390_is_imm32 (ins
->inst_imm
)) {
3436 s390_agfi (code
, ins
->dreg
, ins
->inst_imm
);
3438 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3439 s390_agr (code
, ins
->dreg
, s390_r0
);
3444 if (ins
->dreg
!= ins
->sreg1
) {
3445 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3447 if (s390_is_imm16 (ins
->inst_imm
)) {
3448 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3449 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3451 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3452 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3457 case OP_S390_IADD_OVF
: {
3459 s390_ar (code
, ins
->dreg
, src2
);
3460 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3461 s390_lgfr (code
, ins
->dreg
, ins
->dreg
);
3464 case OP_IADD_OVF_UN
:
3465 case OP_S390_IADD_OVF_UN
: {
3467 s390_algr (code
, ins
->dreg
, src2
);
3468 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3469 s390_llgfr (code
, ins
->dreg
, ins
->dreg
);
3472 case OP_ADD_OVF_CARRY
: {
3474 s390_lghi (code
, s390_r0
, 0);
3475 s390_lgr (code
, s390_r1
, s390_r0
);
3476 s390_alcgr (code
, s390_r0
, s390_r1
);
3477 s390_agr (code
, ins
->dreg
, src2
);
3478 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3479 s390_agr (code
, ins
->dreg
, s390_r0
);
3480 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3483 case OP_ADD_OVF_UN_CARRY
: {
3485 s390_alcgr (code
, ins
->dreg
, src2
);
3486 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3490 if (mono_hwcap_s390x_has_mlt
) {
3491 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3494 s390_sgr (code
, ins
->dreg
, src2
);
3499 if (mono_hwcap_s390x_has_mlt
) {
3500 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3503 s390_sgr (code
, ins
->dreg
, src2
);
3509 s390_slbgr(code
, ins
->dreg
, src2
);
3513 if (ins
->dreg
!= ins
->sreg1
) {
3514 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3516 if (s390_is_imm16 (-ins
->inst_imm
)) {
3517 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
3518 } else if (s390_is_imm32 (-ins
->inst_imm
)) {
3519 s390_slgfi (code
, ins
->dreg
, ins
->inst_imm
);
3521 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3522 s390_slgr (code
, ins
->dreg
, s390_r0
);
3527 if (ins
->dreg
!= ins
->sreg1
) {
3528 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3530 if (s390_is_imm16 (-ins
->inst_imm
)) {
3531 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
3532 } else if (s390_is_imm32 (-ins
->inst_imm
)) {
3533 s390_slgfi (code
, ins
->dreg
, ins
->inst_imm
);
3535 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3536 s390_slgr (code
, ins
->dreg
, s390_r0
);
3541 if (ins
->dreg
!= ins
->sreg1
) {
3542 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3544 if (s390_is_imm16 (-ins
->inst_imm
)) {
3545 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3546 s390_slbgr (code
, ins
->dreg
, s390_r0
);
3548 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3549 s390_slbgr(code
, ins
->dreg
, s390_r0
);
3553 case OP_SUB_OVF_CARRY
: {
3555 s390_lghi (code
, s390_r0
, 0);
3556 s390_lgr (code
, s390_r1
, s390_r0
);
3557 s390_slbgr (code
, s390_r0
, s390_r1
);
3558 s390_sgr (code
, ins
->dreg
, src2
);
3559 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3560 s390_agr (code
, ins
->dreg
, s390_r0
);
3561 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3564 case OP_SUB_OVF_UN_CARRY
: {
3566 s390_slbgr (code
, ins
->dreg
, src2
);
3567 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3571 if (mono_hwcap_s390x_has_mlt
) {
3572 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3574 if (ins
->sreg1
== ins
->dreg
) {
3575 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
3577 if (ins
->sreg2
== ins
->dreg
) {
3578 s390_ngr (code
, ins
->dreg
, ins
->sreg1
);
3580 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3581 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
3588 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3589 if (mono_hwcap_s390x_has_mlt
) {
3590 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3592 if (ins
->dreg
!= ins
->sreg1
) {
3593 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3595 s390_ngr (code
, ins
->dreg
, s390_r0
);
3600 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3601 s390_dsgr (code
, s390_r0
, ins
->sreg2
);
3602 s390_lgr (code
, ins
->dreg
, s390_r1
);
3606 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3607 s390_lghi (code
, s390_r0
, 0);
3608 s390_dlgr (code
, s390_r0
, ins
->sreg2
);
3609 s390_lgr (code
, ins
->dreg
, s390_r1
);
3613 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3614 s390_dsgr (code
, s390_r0
, ins
->sreg2
);
3615 s390_lgr (code
, ins
->dreg
, s390_r0
);
3619 if (s390_is_imm16 (ins
->inst_imm
)) {
3620 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3622 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3624 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3625 s390_dsgr (code
, s390_r0
, s390_r13
);
3626 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3630 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3631 s390_lghi (code
, s390_r0
, 0);
3632 s390_dlgr (code
, s390_r0
, ins
->sreg2
);
3633 s390_lgr (code
, ins
->dreg
, s390_r0
);
3637 if (mono_hwcap_s390x_has_mlt
) {
3638 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3640 if (ins
->sreg1
== ins
->dreg
) {
3641 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
3643 if (ins
->sreg2
== ins
->dreg
) {
3644 s390_ogr (code
, ins
->dreg
, ins
->sreg1
);
3646 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3647 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
3654 S390_SET_MASK(code
, s390_r0
, ins
->inst_imm
);
3655 if (mono_hwcap_s390x_has_mlt
) {
3656 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3658 if (ins
->dreg
!= ins
->sreg1
) {
3659 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3661 s390_ogr (code
, ins
->dreg
, s390_r0
);
3666 if (mono_hwcap_s390x_has_mlt
) {
3667 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3669 if (ins
->sreg1
== ins
->dreg
) {
3670 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
3673 if (ins
->sreg2
== ins
->dreg
) {
3674 s390_xgr (code
, ins
->dreg
, ins
->sreg1
);
3677 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3678 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
3685 S390_SET_MASK(code
, s390_r0
, ins
->inst_imm
);
3686 if (mono_hwcap_s390x_has_mlt
) {
3687 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3689 if (ins
->dreg
!= ins
->sreg1
) {
3690 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3692 s390_xgr (code
, ins
->dreg
, s390_r0
);
3698 s390_sllg (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
3703 if (ins
->sreg1
!= ins
->dreg
) {
3704 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3706 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
3711 s390_srag (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
3716 if (ins
->sreg1
!= ins
->dreg
) {
3717 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3719 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
3723 case OP_LSHR_UN_IMM
: {
3724 if (ins
->sreg1
!= ins
->dreg
) {
3725 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3727 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
3732 s390_srlg (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
3736 if (ins
->sreg1
!= ins
->dreg
) {
3737 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3739 s390_lghi (code
, s390_r0
, -1);
3740 s390_xgr (code
, ins
->dreg
, s390_r0
);
3744 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
3749 s390_msgr (code
, ins
->dreg
, src2
);
3754 if (ins
->dreg
!= ins
->sreg1
) {
3755 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3757 if ((mono_hwcap_s390x_has_gie
) &&
3758 (s390_is_imm32 (ins
->inst_imm
))) {
3759 s390_msgfi (code
, ins
->dreg
, ins
->inst_imm
);
3761 if (s390_is_imm16 (ins
->inst_imm
)) {
3762 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3763 } else if (s390_is_imm32 (ins
->inst_imm
)) {
3764 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3766 S390_SET (code
, s390_r13
, ins
->inst_imm
);
3768 s390_msgr (code
, ins
->dreg
, s390_r13
);
3774 if (mono_hwcap_s390x_has_mie2
) {
3775 s390_msgrkc (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3776 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3778 s390_ltgr (code
, s390_r1
, ins
->sreg1
);
3779 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3780 s390_ltgr (code
, s390_r0
, ins
->sreg2
);
3782 s390_lghi (code
, s390_r1
, 0);
3783 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3784 s390_xgr (code
, s390_r0
, s390_r1
);
3785 s390_msgr (code
, s390_r1
, ins
->sreg2
);
3786 s390_xgr (code
, s390_r0
, s390_r1
);
3787 s390_srlg (code
, s390_r0
, s390_r0
, 0, 63);
3788 s390_ltgr (code
, s390_r0
, s390_r0
);
3789 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3790 PTRSLOT (code
, o
[0]);
3791 PTRSLOT (code
, o
[1]);
3792 s390_lgr (code
, ins
->dreg
, s390_r1
);
3796 case OP_LMUL_OVF_UN
: {
3797 s390_lghi (code
, s390_r0
, 0);
3798 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3799 s390_mlgr (code
, s390_r0
, ins
->sreg2
);
3800 s390_ltgr (code
, s390_r0
, s390_r0
);
3801 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3802 s390_lgr (code
, ins
->dreg
, s390_r1
);
3806 g_assert_not_reached ();
3808 s390_algr (code
, ins
->dreg
, src2
);
3813 s390_agr (code
, ins
->dreg
, src2
);
3817 g_assert_not_reached ();
3819 s390_alcgr (code
, ins
->dreg
, src2
);
3823 if (ins
->dreg
!= ins
->sreg1
) {
3824 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3826 if (s390_is_imm16 (ins
->inst_imm
)) {
3827 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
3829 s390_afi (code
, ins
->dreg
, ins
->inst_imm
);
3834 if (ins
->dreg
!= ins
->sreg1
) {
3835 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3837 if (s390_is_imm16 (ins
->inst_imm
)) {
3838 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3839 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3841 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3842 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3847 case OP_S390_LADD_OVF
: {
3848 if (mono_hwcap_s390x_has_mlt
) {
3849 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3852 s390_agr (code
, ins
->dreg
, src2
);
3854 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3857 case OP_LADD_OVF_UN
:
3858 case OP_S390_LADD_OVF_UN
: {
3859 if (mono_hwcap_s390x_has_mlt
) {
3860 s390_algrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3863 s390_algr (code
, ins
->dreg
, src2
);
3865 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3869 if (mono_hwcap_s390x_has_mlt
) {
3870 s390_slgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3872 CHECK_SRCDST_NCOM_I
;
3873 s390_slgr (code
, ins
->dreg
, src2
);
3878 if (mono_hwcap_s390x_has_mlt
) {
3879 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3881 CHECK_SRCDST_NCOM_I
;
3882 s390_sgr (code
, ins
->dreg
, src2
);
3887 CHECK_SRCDST_NCOM_I
;
3888 s390_slbgr (code
, ins
->dreg
, src2
);
3892 if (ins
->dreg
!= ins
->sreg1
) {
3893 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3895 if (s390_is_imm16 (-ins
->inst_imm
)) {
3896 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
3898 s390_agfi (code
, ins
->dreg
, -ins
->inst_imm
);
3903 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3904 s390_slgfr (code
, ins
->dreg
, s390_r0
);
3908 case OP_S390_ISUB_OVF
: {
3909 if (mono_hwcap_s390x_has_mlt
) {
3910 s390_srk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3911 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3914 s390_sr (code
, ins
->dreg
, src2
);
3915 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3916 s390_lgfr (code
, ins
->dreg
, ins
->dreg
);
3920 case OP_ISUB_OVF_UN
:
3921 case OP_S390_ISUB_OVF_UN
: {
3922 if (mono_hwcap_s390x_has_mlt
) {
3923 s390_slrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3926 s390_slr (code
, ins
->dreg
, src2
);
3928 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3929 s390_llgfr(code
, ins
->dreg
, ins
->dreg
);
3933 case OP_S390_LSUB_OVF
: {
3934 if (mono_hwcap_s390x_has_mlt
) {
3935 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3938 s390_sgr (code
, ins
->dreg
, src2
);
3940 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3943 case OP_LSUB_OVF_UN
:
3944 case OP_S390_LSUB_OVF_UN
: {
3946 s390_slgr (code
, ins
->dreg
, src2
);
3947 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3951 if (mono_hwcap_s390x_has_mlt
) {
3952 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3954 CHECK_SRCDST_NCOM_I
;
3955 s390_ngr (code
, ins
->dreg
, src2
);
3960 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3961 if (mono_hwcap_s390x_has_mlt
) {
3962 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3964 if (ins
->dreg
!= ins
->sreg1
) {
3965 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3967 s390_ngr (code
, ins
->dreg
, s390_r0
);
3972 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3973 s390_srda (code
, s390_r0
, 0, 32);
3974 s390_dr (code
, s390_r0
, ins
->sreg2
);
3975 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3979 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3980 s390_srdl (code
, s390_r0
, 0, 32);
3981 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3982 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3986 if (s390_is_imm16 (ins
->inst_imm
)) {
3987 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3989 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3991 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3992 s390_srda (code
, s390_r0
, 0, 32);
3993 s390_dr (code
, s390_r0
, ins
->sreg2
);
3994 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3998 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3999 s390_srda (code
, s390_r0
, 0, 32);
4000 s390_dr (code
, s390_r0
, ins
->sreg2
);
4001 s390_lgfr (code
, ins
->dreg
, s390_r0
);
4004 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
4005 s390_srdl (code
, s390_r0
, 0, 32);
4006 s390_dlr (code
, s390_r0
, ins
->sreg2
);
4007 s390_lgfr (code
, ins
->dreg
, s390_r0
);
4011 if (s390_is_imm16 (ins
->inst_imm
)) {
4012 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
4014 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
4016 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
4017 s390_srda (code
, s390_r0
, 0, 32);
4018 s390_dr (code
, s390_r0
, ins
->sreg2
);
4019 s390_lgfr (code
, ins
->dreg
, s390_r0
);
4023 if (mono_hwcap_s390x_has_mlt
) {
4024 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
4027 s390_ogr (code
, ins
->dreg
, src2
);
4032 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
4033 if (mono_hwcap_s390x_has_mlt
) {
4034 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
4036 if (ins
->dreg
!= ins
->sreg1
) {
4037 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4039 s390_ogr (code
, ins
->dreg
, s390_r0
);
4044 if (mono_hwcap_s390x_has_mlt
) {
4045 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
4048 s390_xgr (code
, ins
->dreg
, src2
);
4053 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
4054 if (mono_hwcap_s390x_has_mlt
) {
4055 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
4057 if (ins
->dreg
!= ins
->sreg1
) {
4058 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4060 s390_xgr (code
, ins
->dreg
, s390_r0
);
4066 s390_sll (code
, ins
->dreg
, src2
, 0);
4070 if (ins
->sreg1
!= ins
->dreg
) {
4071 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4073 s390_sll (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
4078 s390_sra (code
, ins
->dreg
, src2
, 0);
4082 if (ins
->sreg1
!= ins
->dreg
) {
4083 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4085 s390_sra (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
4088 case OP_ISHR_UN_IMM
: {
4089 if (ins
->sreg1
!= ins
->dreg
) {
4090 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4092 s390_srl (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
4097 s390_srl (code
, ins
->dreg
, src2
, 0);
4101 if (ins
->sreg1
!= ins
->dreg
) {
4102 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4104 s390_lghi (code
, s390_r0
, -1);
4105 s390_xgr (code
, ins
->dreg
, s390_r0
);
4109 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
4114 s390_msr (code
, ins
->dreg
, src2
);
4118 if (ins
->dreg
!= ins
->sreg1
) {
4119 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4121 if (s390_is_imm16 (ins
->inst_imm
)) {
4122 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
4124 s390_lgfi (code
, s390_r0
, ins
->inst_imm
);
4126 s390_msr (code
, ins
->dreg
, s390_r0
);
4131 s390_ltr (code
, s390_r1
, ins
->sreg1
);
4132 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
4133 s390_ltr (code
, s390_r0
, ins
->sreg2
);
4135 s390_lhi (code
, s390_r1
, 0);
4136 s390_j (code
, 0); CODEPTR(code
, o
[1]);
4137 s390_xr (code
, s390_r0
, s390_r1
);
4138 s390_msr (code
, s390_r1
, ins
->sreg2
);
4139 s390_xr (code
, s390_r0
, s390_r1
);
4140 s390_srl (code
, s390_r0
, 0, 31);
4141 s390_ltr (code
, s390_r0
, s390_r0
);
4142 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
4143 PTRSLOT (code
, o
[0]);
4144 PTRSLOT (code
, o
[1]);
4145 s390_lgfr (code
, ins
->dreg
, s390_r1
);
4148 case OP_IMUL_OVF_UN
: {
4149 s390_lhi (code
, s390_r0
, 0);
4150 s390_lr (code
, s390_r1
, ins
->sreg1
);
4151 s390_mlr (code
, s390_r0
, ins
->sreg2
);
4152 s390_ltr (code
, s390_r0
, s390_r0
);
4153 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
4154 s390_lgfr (code
, ins
->dreg
, s390_r1
);
4159 S390_SET (code
, ins
->dreg
, ins
->inst_c0
);
4163 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4164 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
4165 S390_LOAD_TEMPLATE (code
, ins
->dreg
);
4168 case OP_JUMP_TABLE
: {
4169 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4170 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
4171 S390_LOAD_TEMPLATE (code
, ins
->dreg
);
4175 if (ins
->dreg
!= ins
->sreg1
) {
4176 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
4180 case OP_LCONV_TO_I8
:
4182 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4184 case OP_LCONV_TO_I4
:
4185 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4188 case OP_LCONV_TO_U8
:
4189 case OP_LCONV_TO_U4
:
4191 s390_llgfr (code
, ins
->dreg
, ins
->sreg1
);
4193 case OP_LCONV_TO_OVF_U4
:
4194 S390_SET (code
, s390_r0
, 4294967295);
4195 s390_clgr (code
, ins
->sreg1
, s390_r0
);
4196 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, "OverflowException");
4197 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4198 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, "OverflowException");
4199 s390_llgfr(code
, ins
->dreg
, ins
->sreg1
);
4201 case OP_LCONV_TO_OVF_I4_UN
:
4202 S390_SET (code
, s390_r0
, 2147483647);
4203 s390_cgr (code
, ins
->sreg1
, s390_r0
);
4204 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, "OverflowException");
4205 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4206 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, "OverflowException");
4207 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
4210 if (ins
->dreg
!= ins
->sreg1
) {
4211 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
4214 case OP_MOVE_F_TO_I8
:
4215 s390_lgdr (code
, ins
->dreg
, ins
->sreg1
);
4217 case OP_MOVE_I8_TO_F
:
4218 s390_ldgr (code
, ins
->dreg
, ins
->sreg1
);
4220 case OP_MOVE_F_TO_I4
:
4221 s390_ledbr (code
, s390_f0
, ins
->sreg1
);
4222 s390_lgdr (code
, ins
->dreg
, s390_f0
);
4223 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0, 32);
4225 case OP_MOVE_I4_TO_F
:
4226 s390_slag (code
, s390_r0
, ins
->sreg1
, 0, 32);
4227 s390_ldgr (code
, ins
->dreg
, s390_r0
);
4229 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
4231 case OP_FCONV_TO_R4
:
4232 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
4234 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
4236 case OP_S390_SETF4RET
:
4238 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
4241 if (s390_is_imm16 (ins
->inst_offset
)) {
4242 s390_lghi (code
, s390_r13
, ins
->inst_offset
);
4243 } else if (s390_is_imm32 (ins
->inst_offset
)) {
4244 s390_lgfi (code
, s390_r13
, ins
->inst_offset
);
4246 S390_SET (code
, s390_r13
, ins
->inst_offset
);
4248 s390_ear (code
, s390_r1
, 0);
4249 s390_sllg(code
, s390_r1
, s390_r1
, 0, 32);
4250 s390_ear (code
, s390_r1
, 1);
4251 s390_lg (code
, ins
->dreg
, s390_r13
, s390_r1
, 0);
4255 if (s390_is_imm16 (ins
->inst_offset
)) {
4256 s390_lghi (code
, s390_r13
, ins
->inst_offset
);
4257 } else if (s390_is_imm32 (ins
->inst_offset
)) {
4258 s390_lgfi (code
, s390_r13
, ins
->inst_offset
);
4260 S390_SET (code
, s390_r13
, ins
->inst_offset
);
4262 s390_ear (code
, s390_r1
, 0);
4263 s390_sllg(code
, s390_r1
, s390_r1
, 0, 32);
4264 s390_ear (code
, s390_r1
, 1);
4265 s390_stg (code
, ins
->sreg1
, s390_r13
, s390_r1
, 0);
4269 case OP_TAILCALL_MEMBASE
: {
4270 MonoCallInst
*call
= (MonoCallInst
*) ins
;
4271 MonoMethod
*method
= call
->method
;
4272 MonoMethodSignature
*sig
= mono_method_signature(method
);
4273 CallInfo
*cinfo
= get_call_info (NULL
, sig
);
4274 int32_t stackUsage
= (cinfo
->sz
.stack_size
- S390_MINIMAL_STACK_SIZE
),
4275 stackOffset
= S390_MINIMAL_STACK_SIZE
;
4277 if (cfg
->method
->save_lmf
)
4278 restoreLMF(code
, cfg
->frame_reg
, cfg
->stack_usage
);
4280 s390_lgr (code
, s390_r12
, cfg
->frame_reg
);
4281 code
= backUpStackPtr(cfg
, code
);
4283 while (stackUsage
> 256) {
4284 s390_mvc (code
, 256, STK_BASE
, stackOffset
,
4285 s390_r12
, stackOffset
);
4291 s390_mvc (code
, stackUsage
, STK_BASE
, stackOffset
,
4292 s390_r12
, stackOffset
);
4294 s390_lmg (code
, s390_r6
, s390_r13
, STK_BASE
, S390_REG_SAVE_OFFSET
);
4296 if (cfg
->arch
.used_fp_regs
!= 0) {
4297 int32_t fpOffset
= sizeof(double);
4298 for (int i
=8; i
<16; i
++) {
4299 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
4300 s390_ld (code
, i
, cfg
->arch
.fpSize
, STK_BASE
, fpOffset
);
4301 fpOffset
+= sizeof(double);
4306 s390_lg (code
, s390_r14
, 0, STK_BASE
, S390_RET_ADDR_OFFSET
);
4307 if (ins
->opcode
== OP_TAILCALL_MEMBASE
) {
4308 if (mono_hwcap_s390x_has_mie2
) {
4309 s390_bi (code
, 0, ins
->sreg1
, ins
->inst_offset
);
4311 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
4312 s390_br (code
, s390_r1
);
4315 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4316 MONO_PATCH_INFO_METHOD_JUMP
,
4318 s390_jcl (code
, S390_CC_UN
, 0);
4321 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval(cfg
->method
))
4327 case OP_CHECK_THIS
: {
4328 /* ensure ins->sreg1 is not NULL */
4329 s390_lg (code
, s390_r0
, 0, ins
->sreg1
, 0);
4330 s390_ltgr (code
, s390_r0
, s390_r0
);
4331 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4335 const int offset
= cfg
->sig_cookie
+ cfg
->stack_usage
;
4337 if (s390_is_imm16 (offset
)) {
4338 s390_lghi (code
, s390_r0
, offset
);
4339 } else if (s390_is_imm32 (offset
)) {
4340 s390_lgfi (code
, s390_r0
, offset
);
4342 S390_SET (code
, s390_r0
, offset
);
4344 s390_agr (code
, s390_r0
, cfg
->frame_reg
);
4345 s390_stg (code
, s390_r0
, 0, ins
->sreg1
, 0);
4349 call
= (MonoCallInst
*)ins
;
4350 if (ins
->flags
& MONO_INST_HAS_METHOD
)
4351 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4352 MONO_PATCH_INFO_METHOD
,
4355 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4356 MONO_PATCH_INFO_ABS
,
4358 S390_CALL_TEMPLATE (code
, s390_r14
);
4359 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
4360 s390_ldebr (code
, s390_f0
, s390_f0
);
4369 call
= (MonoCallInst
*)ins
;
4370 if (ins
->flags
& MONO_INST_HAS_METHOD
)
4371 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4372 MONO_PATCH_INFO_METHOD
,
4375 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4376 MONO_PATCH_INFO_ABS
,
4378 S390_CALL_TEMPLATE (code
, s390_r14
);
4381 case OP_FCALL_REG
: {
4382 call
= (MonoCallInst
*)ins
;
4383 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4384 s390_basr (code
, s390_r14
, s390_r1
);
4385 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
4386 s390_ldebr (code
, s390_f0
, s390_f0
);
4392 case OP_VOIDCALL_REG
:
4395 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4396 s390_basr (code
, s390_r14
, s390_r1
);
4399 case OP_FCALL_MEMBASE
: {
4400 call
= (MonoCallInst
*)ins
;
4401 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
4402 s390_basr (code
, s390_r14
, s390_r1
);
4403 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
4404 s390_ldebr (code
, s390_f0
, s390_f0
);
4407 case OP_LCALL_MEMBASE
:
4408 case OP_VCALL_MEMBASE
:
4409 case OP_VCALL2_MEMBASE
:
4410 case OP_VOIDCALL_MEMBASE
:
4411 case OP_RCALL_MEMBASE
:
4412 case OP_CALL_MEMBASE
: {
4413 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
4414 s390_basr (code
, s390_r14
, s390_r1
);
4421 if (cfg
->param_area
== 0)
4422 alloca_skip
= S390_MINIMAL_STACK_SIZE
;
4424 alloca_skip
= cfg
->param_area
;
4426 area_offset
= S390_ALIGN(alloca_skip
, S390_STACK_ALIGNMENT
);
4427 s390_lgr (code
, s390_r1
, ins
->sreg1
);
4428 if (ins
->flags
& MONO_INST_INIT
)
4429 s390_lgr (code
, s390_r0
, ins
->sreg1
);
4430 s390_aghi (code
, s390_r1
, 14);
4431 s390_srlg (code
, s390_r1
, s390_r1
, 0, 3);
4432 s390_sllg (code
, s390_r1
, s390_r1
, 0, 3);
4433 if (cfg
->method
->save_lmf
) {
4434 /*----------------------------------*/
4435 /* we have to adjust lmf ebp value */
4436 /*----------------------------------*/
4437 int lmfOffset
= cfg
->stack_usage
- sizeof(MonoLMF
);
4439 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
4440 if (s390_is_imm16(lmfOffset
)) {
4441 s390_aghi (code
, s390_r13
, lmfOffset
);
4442 } else if (s390_is_imm32(lmfOffset
)) {
4443 s390_agfi (code
, s390_r13
, lmfOffset
);
4445 S390_SET (code
, s390_r13
, lmfOffset
);
4447 s390_lgr (code
, s390_r14
, STK_BASE
);
4448 s390_sgr (code
, s390_r14
, s390_r1
);
4449 s390_stg (code
, s390_r14
, 0, s390_r13
,
4450 G_STRUCT_OFFSET(MonoLMF
, ebp
));
4452 s390_lg (code
, s390_r13
, 0, STK_BASE
, 0);
4453 s390_sgr (code
, STK_BASE
, s390_r1
);
4454 s390_stg (code
, s390_r13
, 0, STK_BASE
, 0);
4455 s390_la (code
, ins
->dreg
, 0, STK_BASE
, area_offset
);
4456 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
4457 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
4458 if (ins
->flags
& MONO_INST_INIT
) {
4459 s390_lgr (code
, s390_r1
, s390_r0
);
4460 s390_lgr (code
, s390_r0
, ins
->dreg
);
4461 s390_lgr (code
, s390_r14
, s390_r12
);
4462 s390_lghi (code
, s390_r13
, 0);
4463 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
4465 s390_lgr (code
, s390_r12
, s390_r14
);
4470 s390_lgr (code
, s390_r2
, ins
->sreg1
);
4471 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_INTERNAL_METHOD
,
4472 (gpointer
) "mono_arch_throw_exception");
4473 S390_CALL_TEMPLATE(code
, s390_r14
);
4477 s390_lgr (code
, s390_r2
, ins
->sreg1
);
4478 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_INTERNAL_METHOD
,
4479 (gpointer
) "mono_arch_rethrow_exception");
4480 S390_CALL_TEMPLATE(code
, s390_r14
);
4483 case OP_START_HANDLER
: {
4484 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
4486 S390_LONG (code
, stg
, stg
, s390_r14
, 0,
4487 spvar
->inst_basereg
,
4488 spvar
->inst_offset
);
4491 case OP_ENDFILTER
: {
4492 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
4494 if (ins
->sreg1
!= s390_r2
)
4495 s390_lgr(code
, s390_r2
, ins
->sreg1
);
4496 S390_LONG (code
, lg
, lg
, s390_r14
, 0,
4497 spvar
->inst_basereg
,
4498 spvar
->inst_offset
);
4499 s390_br (code
, s390_r14
);
4502 case OP_ENDFINALLY
: {
4503 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
4505 S390_LONG (code
, lg
, lg
, s390_r14
, 0,
4506 spvar
->inst_basereg
,
4507 spvar
->inst_offset
);
4508 s390_br (code
, s390_r14
);
4511 case OP_CALL_HANDLER
: {
4512 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
4513 MONO_PATCH_INFO_BB
, ins
->inst_target_bb
);
4514 s390_brasl (code
, s390_r14
, 0);
4515 for (GList
*tmp
= ins
->inst_eh_blocks
; tmp
!= bb
->clause_holes
; tmp
= tmp
->prev
)
4516 mono_cfg_add_try_hole (cfg
, ((MonoLeaveClause
*) tmp
->data
)->clause
, code
, bb
);
4520 ins
->inst_c0
= code
- cfg
->native_code
;
4523 case OP_RELAXED_NOP
:
4526 case OP_DUMMY_ICONST
:
4527 case OP_DUMMY_I8CONST
:
4528 case OP_DUMMY_R8CONST
:
4529 case OP_DUMMY_R4CONST
:
4530 case OP_NOT_REACHED
:
4534 case OP_IL_SEQ_POINT
:
4535 mono_add_seq_point (cfg
, bb
, ins
, code
- cfg
->native_code
);
4537 case OP_SEQ_POINT
: {
4540 if (cfg
->compile_aot
)
4544 * Read from the single stepping trigger page. This will cause a
4545 * SIGSEGV when single stepping is enabled.
4546 * We do this _before_ the breakpoint, so single stepping after
4547 * a breakpoint is hit will step to the next IL offset.
4549 if (ins
->flags
& MONO_INST_SINGLE_STEP_LOC
) {
4550 breakpointCode
.pTrigger
= ss_trigger_page
;
4551 memcpy(code
, (void *) &breakpointCode
, BREAKPOINT_SIZE
);
4552 code
+= BREAKPOINT_SIZE
;
4555 mono_add_seq_point (cfg
, bb
, ins
, code
- cfg
->native_code
);
4558 * A placeholder for a possible breakpoint inserted by
4559 * mono_arch_set_breakpoint ().
4561 for (i
= 0; i
< (BREAKPOINT_SIZE
/ S390X_NOP_SIZE
); ++i
)
4565 * Add an additional nop so skipping the bp doesn't cause the ip to point
4566 * to another IL offset.
4572 case OP_GENERIC_CLASS_INIT
: {
4573 static int byte_offset
= -1;
4574 static guint8 bitmask
;
4577 g_assert (ins
->sreg1
== S390_FIRST_ARG_REG
);
4579 if (byte_offset
< 0)
4580 mono_marshal_find_bitfield_offset (MonoVTable
, initialized
, &byte_offset
, &bitmask
);
4582 s390_tm (code
, ins
->sreg1
, byte_offset
, bitmask
);
4583 s390_jo (code
, 0); CODEPTR(code
, jump
);
4585 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_INTERNAL_METHOD
,
4586 "mono_generic_class_init");
4587 S390_CALL_TEMPLATE(code
, s390_r14
);
4589 PTRSLOT (code
, jump
);
4591 ins
->flags
|= MONO_INST_GC_CALLSITE
;
4592 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
4596 EMIT_UNCOND_BRANCH(ins
);
4599 s390_br (code
, ins
->sreg1
);
4605 s390_lghi(code
, ins
->dreg
, 1);
4607 s390_lghi(code
, ins
->dreg
, 0);
4613 s390_lghi(code
, ins
->dreg
, 1);
4615 s390_lghi(code
, ins
->dreg
, 0);
4621 s390_lghi(code
, ins
->dreg
, 1);
4623 s390_lghi(code
, ins
->dreg
, 0);
4629 s390_lghi(code
, ins
->dreg
, 1);
4631 s390_lghi(code
, ins
->dreg
, 0);
4637 s390_lghi(code
, ins
->dreg
, 1);
4639 s390_lghi(code
, ins
->dreg
, 0);
4643 s390_lghi(code
, ins
->dreg
, 1);
4645 s390_lghi(code
, ins
->dreg
, 0);
4649 s390_lghi(code
, ins
->dreg
, 1);
4651 s390_lghi(code
, ins
->dreg
, 0);
4655 s390_lghi(code
, ins
->dreg
, 1);
4657 s390_lghi(code
, ins
->dreg
, 0);
4661 s390_lghi(code
, ins
->dreg
, 1);
4663 s390_lghi(code
, ins
->dreg
, 0);
4667 s390_lghi(code
, ins
->dreg
, 1);
4669 s390_lghi(code
, ins
->dreg
, 0);
4672 case OP_COND_EXC_EQ
:
4673 case OP_COND_EXC_IEQ
:
4674 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ
, ins
->inst_p1
);
4676 case OP_COND_EXC_NE_UN
:
4677 case OP_COND_EXC_INE_UN
:
4678 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE
, ins
->inst_p1
);
4680 case OP_COND_EXC_LT
:
4681 case OP_COND_EXC_ILT
:
4682 case OP_COND_EXC_LT_UN
:
4683 case OP_COND_EXC_ILT_UN
:
4684 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, ins
->inst_p1
);
4686 case OP_COND_EXC_GT
:
4687 case OP_COND_EXC_IGT
:
4688 case OP_COND_EXC_GT_UN
:
4689 case OP_COND_EXC_IGT_UN
:
4690 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, ins
->inst_p1
);
4692 case OP_COND_EXC_GE
:
4693 case OP_COND_EXC_IGE
:
4694 case OP_COND_EXC_GE_UN
:
4695 case OP_COND_EXC_IGE_UN
:
4696 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE
, ins
->inst_p1
);
4698 case OP_COND_EXC_LE
:
4699 case OP_COND_EXC_ILE
:
4700 case OP_COND_EXC_LE_UN
:
4701 case OP_COND_EXC_ILE_UN
:
4702 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE
, ins
->inst_p1
);
4704 case OP_COND_EXC_OV
:
4705 case OP_COND_EXC_IOV
:
4706 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, ins
->inst_p1
);
4708 case OP_COND_EXC_NO
:
4709 case OP_COND_EXC_INO
:
4710 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO
, ins
->inst_p1
);
4713 case OP_COND_EXC_IC
:
4714 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, ins
->inst_p1
);
4716 case OP_COND_EXC_NC
:
4717 case OP_COND_EXC_INC
:
4718 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, ins
->inst_p1
);
4722 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
4726 EMIT_COND_BRANCH (ins
, S390_CC_NE
);
4732 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4738 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4744 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4750 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4754 EMIT_COMP_AND_BRANCH(ins
, crj
, cr
);
4758 EMIT_COMP_AND_BRANCH(ins
, clrj
, clr
);
4762 EMIT_COMP_AND_BRANCH(ins
, cgrj
, cgr
);
4766 EMIT_COMP_AND_BRANCH(ins
, clgrj
, clgr
);
4770 EMIT_COMP_AND_BRANCH_IMM(ins
, crj
, cr
, ltr
, FALSE
);
4774 EMIT_COMP_AND_BRANCH_IMM(ins
, clrj
, clr
, ltr
, TRUE
);
4778 EMIT_COMP_AND_BRANCH_IMM(ins
, cgrj
, cgr
, ltgr
, FALSE
);
4782 EMIT_COMP_AND_BRANCH_IMM(ins
, clgrj
, clgr
, ltgr
, TRUE
);
4785 /* floating point opcodes */
4787 if (*((double *) ins
->inst_p0
) == 0) {
4788 s390_lzdr (code
, ins
->dreg
);
4790 S390_SET (code
, s390_r13
, ins
->inst_p0
);
4791 s390_ld (code
, ins
->dreg
, 0, s390_r13
, 0);
4796 if (*((float *) ins
->inst_p0
) == 0) {
4798 s390_lzer (code
, ins
->dreg
);
4800 s390_lzdr (code
, ins
->dreg
);
4802 S390_SET (code
, s390_r13
, ins
->inst_p0
);
4804 S390_LONG (code
, ley
, le
, ins
->dreg
, 0, s390_r13
, 0);
4806 s390_ldeb (code
, ins
->dreg
, 0, s390_r13
, 0);
4811 case OP_STORER8_MEMBASE_REG
: {
4812 S390_LONG (code
, stdy
, std
, ins
->sreg1
, 0,
4813 ins
->inst_destbasereg
, ins
->inst_offset
);
4816 case OP_LOADR8_MEMBASE
: {
4817 S390_LONG (code
, ldy
, ld
, ins
->dreg
, 0,
4818 ins
->inst_basereg
, ins
->inst_offset
);
4821 case OP_STORER4_MEMBASE_REG
: {
4823 S390_LONG (code
, stey
, ste
, ins
->sreg1
, 0,
4824 ins
->inst_destbasereg
, ins
->inst_offset
);
4826 s390_ledbr (code
, s390_f15
, ins
->sreg1
);
4827 S390_LONG (code
, stey
, ste
, s390_f15
, 0,
4828 ins
->inst_destbasereg
, ins
->inst_offset
);
4832 case OP_LOADR4_MEMBASE
: {
4834 S390_LONG (code
, ley
, le
, ins
->dreg
, 0,
4835 ins
->inst_basereg
, ins
->inst_offset
);
4837 S390_LONG (code
, ley
, le
, s390_f15
, 0,
4838 ins
->inst_basereg
, ins
->inst_offset
);
4839 s390_ldebr (code
, ins
->dreg
, s390_f15
);
4843 case OP_ICONV_TO_R_UN
: {
4844 if (mono_hwcap_s390x_has_fpe
) {
4845 s390_cdlfbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4847 s390_llgfr (code
, s390_r0
, ins
->sreg1
);
4848 s390_cdgbr (code
, ins
->dreg
, s390_r0
);
4852 case OP_LCONV_TO_R_UN
: {
4853 if (mono_hwcap_s390x_has_fpe
) {
4854 s390_cdlgbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4857 s390_cxgbr (code
, s390_f12
, ins
->sreg1
);
4858 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4859 s390_jnl (code
, 0); CODEPTR(code
, jump
);
4860 S390_SET (code
, s390_r13
, 0x403f000000000000llu
);
4861 s390_lgdr (code
, s390_f13
, s390_r13
);
4862 s390_lzdr (code
, s390_f15
);
4863 s390_axbr (code
, s390_f12
, s390_f13
);
4864 PTRSLOT(code
, jump
);
4865 s390_ldxbr (code
, s390_f13
, s390_f12
);
4866 s390_ldr (code
, ins
->dreg
, s390_f13
);
4870 case OP_LCONV_TO_R4
:
4871 case OP_ICONV_TO_R4
: {
4872 s390_cegbr (code
, ins
->dreg
, ins
->sreg1
);
4874 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
4877 case OP_LCONV_TO_R8
:
4878 case OP_ICONV_TO_R8
: {
4879 s390_cdgbr (code
, ins
->dreg
, ins
->sreg1
);
4882 case OP_FCONV_TO_I1
:
4883 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4884 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4886 s390_oill (code
, ins
->dreg
, 0x80);
4887 s390_lghi (code
, s390_r0
, 0xff);
4888 s390_ngr (code
, ins
->dreg
, s390_r0
);
4890 case OP_FCONV_TO_U1
:
4891 if (mono_hwcap_s390x_has_fpe
) {
4892 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4893 s390_lghi (code
, s390_r0
, 0xff);
4894 s390_ngr (code
, ins
->dreg
, s390_r0
);
4896 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4899 case OP_FCONV_TO_I2
:
4900 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4901 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4903 s390_oill (code
, ins
->dreg
, 0x8000);
4904 s390_llill (code
, s390_r0
, 0xffff);
4905 s390_ngr (code
, ins
->dreg
, s390_r0
);
4907 case OP_FCONV_TO_U2
:
4908 if (mono_hwcap_s390x_has_fpe
) {
4909 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4910 s390_llill (code
, s390_r0
, 0xffff);
4911 s390_ngr (code
, ins
->dreg
, s390_r0
);
4913 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4916 case OP_FCONV_TO_I4
:
4918 s390_cfdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4920 case OP_FCONV_TO_U4
:
4922 if (mono_hwcap_s390x_has_fpe
) {
4923 s390_clfdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4925 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4928 case OP_FCONV_TO_I8
:
4929 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4931 case OP_FCONV_TO_U8
:
4932 if (mono_hwcap_s390x_has_fpe
) {
4933 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4935 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 8, FALSE
);
4938 case OP_RCONV_TO_I1
:
4939 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4940 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4942 s390_oill (code
, ins
->dreg
, 0x80);
4943 s390_lghi (code
, s390_r0
, 0xff);
4944 s390_ngr (code
, ins
->dreg
, s390_r0
);
4946 case OP_RCONV_TO_U1
:
4947 if (mono_hwcap_s390x_has_fpe
) {
4948 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4949 s390_lghi (code
, s390_r0
, 0xff);
4950 s390_ngr (code
, ins
->dreg
, s390_r0
);
4952 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4955 case OP_RCONV_TO_I2
:
4956 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4957 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4959 s390_oill (code
, ins
->dreg
, 0x8000);
4960 s390_llill (code
, s390_r0
, 0xffff);
4961 s390_ngr (code
, ins
->dreg
, s390_r0
);
4963 case OP_RCONV_TO_U2
:
4964 if (mono_hwcap_s390x_has_fpe
) {
4965 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4966 s390_llill (code
, s390_r0
, 0xffff);
4967 s390_ngr (code
, ins
->dreg
, s390_r0
);
4969 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4972 case OP_RCONV_TO_I4
:
4974 s390_cfebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4976 case OP_RCONV_TO_U4
:
4977 if (mono_hwcap_s390x_has_fpe
) {
4978 s390_clfebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4980 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4983 case OP_RCONV_TO_I8
:
4984 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4986 case OP_RCONV_TO_U8
:
4987 if (mono_hwcap_s390x_has_fpe
) {
4988 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4990 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 8, FALSE
);
4993 case OP_LCONV_TO_OVF_I
: {
4994 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4996 s390_ltgr (code
, ins
->sreg2
, ins
->sreg2
);
4997 s390_jnl (code
, 0); CODEPTR(code
, o
[0]);
4998 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4999 s390_jnl (code
, 0); CODEPTR(code
, o
[1]);
5000 s390_lhi (code
, s390_r13
, -1);
5001 s390_cgr (code
, ins
->sreg1
, s390_r13
);
5002 s390_jnz (code
, 0); CODEPTR(code
, o
[2]);
5003 if (ins
->dreg
!= ins
->sreg2
)
5004 s390_lgr (code
, ins
->dreg
, ins
->sreg2
);
5005 s390_j (code
, 0); CODEPTR(code
, o
[3]);
5006 PTRSLOT(code
, o
[0]);
5007 s390_jz (code
, 0); CODEPTR(code
, o
[4]);
5008 PTRSLOT(code
, o
[1]);
5009 PTRSLOT(code
, o
[2]);
5010 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5011 MONO_PATCH_INFO_EXC
, "OverflowException");
5012 s390_brasl (code
, s390_r14
, 0);
5013 PTRSLOT(code
, o
[3]);
5014 PTRSLOT(code
, o
[4]);
5018 s390_lpdbr (code
, ins
->dreg
, ins
->sreg1
);
5022 s390_sqdbr (code
, ins
->dreg
, ins
->sreg1
);
5027 s390_adbr (code
, ins
->dreg
, src2
);
5032 s390_aebr (code
, ins
->dreg
, src2
);
5036 CHECK_SRCDST_NCOM_F
;
5037 s390_sdbr (code
, ins
->dreg
, src2
);
5041 CHECK_SRCDST_NCOM_F
;
5042 s390_sebr (code
, ins
->dreg
, src2
);
5047 s390_mdbr (code
, ins
->dreg
, src2
);
5052 s390_meer (code
, ins
->dreg
, src2
);
5056 CHECK_SRCDST_NCOM_F
;
5057 s390_ddbr (code
, ins
->dreg
, src2
);
5061 CHECK_SRCDST_NCOM_F
;
5062 s390_debr (code
, ins
->dreg
, src2
);
5066 s390_lcdbr (code
, ins
->dreg
, ins
->sreg1
);
5070 s390_lcebr (code
, ins
->dreg
, ins
->sreg1
);
5074 CHECK_SRCDST_NCOM_F
;
5075 s390_didbr (code
, ins
->dreg
, src2
, 5, s390_f15
);
5079 CHECK_SRCDST_NCOM_F
;
5080 s390_diebr (code
, ins
->dreg
, src2
, 5, s390_f15
);
5084 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5088 s390_cebr (code
, ins
->sreg1
, ins
->sreg2
);
5092 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5093 s390_lghi (code
, ins
->dreg
, 1);
5095 s390_lghi (code
, ins
->dreg
, 0);
5099 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5100 s390_lghi (code
, ins
->dreg
, 1);
5102 s390_lghi (code
, ins
->dreg
, 0);
5106 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5107 s390_lghi (code
, ins
->dreg
, 1);
5109 s390_lghi (code
, ins
->dreg
, 0);
5113 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5114 s390_lghi (code
, ins
->dreg
, 1);
5116 s390_lghi (code
, ins
->dreg
, 0);
5120 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5121 s390_lghi (code
, ins
->dreg
, 1);
5123 s390_lghi (code
, ins
->dreg
, 0);
5127 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5128 s390_lghi (code
, ins
->dreg
, 1);
5130 s390_lghi (code
, ins
->dreg
, 0);
5134 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5135 s390_lghi (code
, ins
->dreg
, 1);
5137 s390_lghi (code
, ins
->dreg
, 0);
5141 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5142 s390_lghi (code
, ins
->dreg
, 1);
5144 s390_lghi (code
, ins
->dreg
, 0);
5148 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5149 s390_lghi (code
, ins
->dreg
, 1);
5151 s390_lghi (code
, ins
->dreg
, 0);
5155 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5156 s390_lghi (code
, ins
->dreg
, 1);
5158 s390_lghi (code
, ins
->dreg
, 0);
5162 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5163 s390_lghi (code
, ins
->dreg
, 1);
5165 s390_lghi (code
, ins
->dreg
, 0);
5169 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5170 s390_lghi (code
, ins
->dreg
, 1);
5172 s390_lghi (code
, ins
->dreg
, 0);
5176 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5177 s390_lghi (code
, ins
->dreg
, 1);
5179 s390_lghi (code
, ins
->dreg
, 0);
5183 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5184 s390_lghi (code
, ins
->dreg
, 1);
5186 s390_lghi (code
, ins
->dreg
, 0);
5190 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
5191 s390_lghi (code
, ins
->dreg
, 1);
5193 s390_lghi (code
, ins
->dreg
, 0);
5197 s390_cebr (code
, ins
->sreg1
, ins
->sreg2
);
5198 s390_lghi (code
, ins
->dreg
, 1);
5200 s390_lghi (code
, ins
->dreg
, 0);
5205 s390_jo (code
, 0); CODEPTR(code
, o
);
5206 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
5211 EMIT_COND_BRANCH (ins
, S390_CC_NE
|S390_CC_OV
);
5215 s390_jo (code
, 0); CODEPTR(code
, o
);
5216 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
5221 EMIT_COND_BRANCH (ins
, S390_CC_LT
|S390_CC_OV
);
5225 s390_jo (code
, 0); CODEPTR(code
, o
);
5226 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
5231 EMIT_COND_BRANCH (ins
, S390_CC_GT
|S390_CC_OV
);
5235 s390_jo (code
, 0); CODEPTR(code
, o
);
5236 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
5241 EMIT_COND_BRANCH (ins
, S390_CC_GE
|S390_CC_OV
);
5245 s390_jo (code
, 0); CODEPTR(code
, o
);
5246 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
5251 EMIT_COND_BRANCH (ins
, S390_CC_LE
|S390_CC_OV
);
5255 s390_lhi (code
, s390_r13
, 0x7f);
5256 s390_tcdb (code
, ins
->sreg1
, 0, s390_r13
, 0);
5257 s390_jz (code
, 0); CODEPTR(code
, o
);
5258 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5259 MONO_PATCH_INFO_EXC
, "OverflowException");
5260 s390_brasl (code
, s390_r14
,0);
5264 case OP_S390_MOVE
: {
5265 if (ins
->backend
.size
> 0) {
5266 if (ins
->backend
.size
<= 256) {
5267 s390_mvc (code
, ins
->backend
.size
, ins
->dreg
,
5268 ins
->inst_offset
, ins
->sreg1
, ins
->inst_imm
);
5270 s390_lgr (code
, s390_r0
, ins
->dreg
);
5271 if (ins
->inst_offset
> 0) {
5272 if (s390_is_imm16 (ins
->inst_offset
)) {
5273 s390_aghi (code
, s390_r0
, ins
->inst_offset
);
5274 } else if (s390_is_imm32 (ins
->inst_offset
)) {
5275 s390_agfi (code
, s390_r0
, ins
->inst_offset
);
5277 S390_SET (code
, s390_r13
, ins
->inst_offset
);
5278 s390_agr (code
, s390_r0
, s390_r13
);
5281 s390_lgr (code
, s390_r12
, ins
->sreg1
);
5282 if (ins
->inst_imm
> 0) {
5283 if (s390_is_imm16 (ins
->inst_imm
)) {
5284 s390_aghi (code
, s390_r12
, ins
->inst_imm
);
5285 } else if (s390_is_imm32 (ins
->inst_imm
)) {
5286 s390_agfi (code
, s390_r12
, ins
->inst_imm
);
5288 S390_SET (code
, s390_r13
, ins
->inst_imm
);
5289 s390_agr (code
, s390_r12
, s390_r13
);
5292 if (s390_is_imm16 (ins
->backend
.size
)) {
5293 s390_lghi (code
, s390_r1
, ins
->backend
.size
);
5294 } else if (s390_is_imm32 (ins
->inst_offset
)) {
5295 s390_agfi (code
, s390_r1
, ins
->backend
.size
);
5297 S390_SET (code
, s390_r13
, ins
->backend
.size
);
5298 s390_agr (code
, s390_r1
, s390_r13
);
5300 s390_lgr (code
, s390_r13
, s390_r1
);
5301 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
5307 case OP_ATOMIC_ADD_I8
: {
5308 if (mono_hwcap_s390x_has_ia
) {
5309 s390_laag (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
5310 s390_agr (code
, ins
->dreg
, ins
->sreg2
);
5312 s390_lgr (code
, s390_r1
, ins
->sreg2
);
5313 s390_lg (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
5314 s390_agr (code
, s390_r1
, s390_r0
);
5315 s390_csg (code
, s390_r0
, s390_r1
, ins
->inst_basereg
, ins
->inst_offset
);
5316 s390_jnz (code
, -10);
5317 s390_lgr (code
, ins
->dreg
, s390_r1
);
5321 case OP_ATOMIC_EXCHANGE_I8
: {
5322 s390_lg (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
5323 s390_csg (code
, s390_r0
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
5324 s390_jnz (code
, -6);
5325 s390_lgr (code
, ins
->dreg
, s390_r0
);
5328 case OP_ATOMIC_ADD_I4
: {
5329 if (mono_hwcap_s390x_has_ia
) {
5330 s390_laa (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
5331 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
5333 s390_lgfr(code
, s390_r1
, ins
->sreg2
);
5334 s390_lgf (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
5335 s390_agr (code
, s390_r1
, s390_r0
);
5336 s390_cs (code
, s390_r0
, s390_r1
, ins
->inst_basereg
, ins
->inst_offset
);
5337 s390_jnz (code
, -9);
5338 s390_lgfr(code
, ins
->dreg
, s390_r1
);
5342 case OP_ATOMIC_EXCHANGE_I4
: {
5343 s390_l (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
5344 s390_cs (code
, s390_r0
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
5345 s390_jnz (code
, -4);
5346 s390_lgfr(code
, ins
->dreg
, s390_r0
);
5349 case OP_S390_BKCHAIN
: {
5350 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
5351 if (s390_is_imm16 (cfg
->stack_offset
)) {
5352 s390_aghi (code
, ins
->dreg
, cfg
->stack_offset
);
5353 } else if (s390_is_imm32 (cfg
->stack_offset
)) {
5354 s390_agfi (code
, ins
->dreg
, cfg
->stack_offset
);
5356 S390_SET (code
, s390_r13
, cfg
->stack_offset
);
5357 s390_agr (code
, ins
->dreg
, s390_r13
);
5361 case OP_MEMORY_BARRIER
:
5364 case OP_LIVERANGE_START
: {
5365 if (cfg
->verbose_level
> 1)
5366 printf ("R%d START=0x%x\n", MONO_VARINFO (cfg
, ins
->inst_c0
)->vreg
, (int)(code
- cfg
->native_code
));
5367 MONO_VARINFO (cfg
, ins
->inst_c0
)->live_range_start
= code
- cfg
->native_code
;
5370 case OP_LIVERANGE_END
: {
5371 if (cfg
->verbose_level
> 1)
5372 printf ("R%d END=0x%x\n", MONO_VARINFO (cfg
, ins
->inst_c0
)->vreg
, (int)(code
- cfg
->native_code
));
5373 MONO_VARINFO (cfg
, ins
->inst_c0
)->live_range_end
= code
- cfg
->native_code
;
5376 case OP_GC_SAFE_POINT
: {
5379 g_assert (mono_threads_are_safepoints_enabled ());
5381 s390_ltg (code
, s390_r0
, 0, ins
->sreg1
, 0);
5382 s390_jz (code
, 0); CODEPTR(code
, br
);
5383 mono_add_patch_info (cfg
, code
- cfg
->native_code
, MONO_PATCH_INFO_ABS
,
5384 mono_threads_state_poll
);
5385 S390_CALL_TEMPLATE (code
, s390_r14
);
5389 case OP_GC_LIVENESS_DEF
:
5390 case OP_GC_LIVENESS_USE
:
5391 case OP_GC_PARAM_SLOT_LIVENESS_DEF
:
5392 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
5394 case OP_GC_SPILL_SLOT_LIVENESS_DEF
:
5395 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
5396 bb
->spill_slot_defs
= g_slist_prepend_mempool (cfg
->mempool
, bb
->spill_slot_defs
, ins
);
5398 #ifdef MONO_ARCH_SIMD_INTRINSICS
5400 s390x_addps (code
, ins
->sreg1
, ins
->sreg2
);
5403 s390x_divps (code
, ins
->sreg1
, ins
->sreg2
);
5406 s390x_mulps (code
, ins
->sreg1
, ins
->sreg2
);
5409 s390x_subps (code
, ins
->sreg1
, ins
->sreg2
);
5412 s390x_maxps (code
, ins
->sreg1
, ins
->sreg2
);
5415 s390x_minps (code
, ins
->sreg1
, ins
->sreg2
);
5418 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 7);
5419 s390x_cmpps_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5422 s390x_andps (code
, ins
->sreg1
, ins
->sreg2
);
5425 s390x_andnps (code
, ins
->sreg1
, ins
->sreg2
);
5428 s390x_orps (code
, ins
->sreg1
, ins
->sreg2
);
5431 s390x_xorps (code
, ins
->sreg1
, ins
->sreg2
);
5434 s390x_sqrtps (code
, ins
->dreg
, ins
->sreg1
);
5437 s390x_rsqrtps (code
, ins
->dreg
, ins
->sreg1
);
5440 s390x_rcpps (code
, ins
->dreg
, ins
->sreg1
);
5443 s390x_addsubps (code
, ins
->sreg1
, ins
->sreg2
);
5446 s390x_haddps (code
, ins
->sreg1
, ins
->sreg2
);
5449 s390x_hsubps (code
, ins
->sreg1
, ins
->sreg2
);
5452 s390x_movshdup (code
, ins
->dreg
, ins
->sreg1
);
5455 s390x_movsldup (code
, ins
->dreg
, ins
->sreg1
);
5458 case OP_PSHUFLEW_HIGH
:
5459 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
5460 s390x_pshufhw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5462 case OP_PSHUFLEW_LOW
:
5463 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
5464 s390x_pshuflw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5467 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
5468 s390x_pshufd_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5471 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
5472 s390x_shufps_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5475 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0x3);
5476 s390x_shufpd_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5480 s390x_addpd (code
, ins
->sreg1
, ins
->sreg2
);
5483 s390x_divpd (code
, ins
->sreg1
, ins
->sreg2
);
5486 s390x_mulpd (code
, ins
->sreg1
, ins
->sreg2
);
5489 s390x_subpd (code
, ins
->sreg1
, ins
->sreg2
);
5492 s390x_maxpd (code
, ins
->sreg1
, ins
->sreg2
);
5495 s390x_minpd (code
, ins
->sreg1
, ins
->sreg2
);
5498 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 7);
5499 s390x_cmppd_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5502 s390x_andpd (code
, ins
->sreg1
, ins
->sreg2
);
5505 s390x_andnpd (code
, ins
->sreg1
, ins
->sreg2
);
5508 s390x_orpd (code
, ins
->sreg1
, ins
->sreg2
);
5511 s390x_xorpd (code
, ins
->sreg1
, ins
->sreg2
);
5514 s390x_sqrtpd (code
, ins
->dreg
, ins
->sreg1
);
5517 s390x_addsubpd (code
, ins
->sreg1
, ins
->sreg2
);
5520 s390x_haddpd (code
, ins
->sreg1
, ins
->sreg2
);
5523 s390x_hsubpd (code
, ins
->sreg1
, ins
->sreg2
);
5526 s390x_movddup (code
, ins
->dreg
, ins
->sreg1
);
5529 case OP_EXTRACT_MASK
:
5530 s390x_pmovmskb (code
, ins
->dreg
, ins
->sreg1
);
5534 s390x_pand (code
, ins
->sreg1
, ins
->sreg2
);
5537 s390x_por (code
, ins
->sreg1
, ins
->sreg2
);
5540 s390x_pxor (code
, ins
->sreg1
, ins
->sreg2
);
5544 s390x_paddb (code
, ins
->sreg1
, ins
->sreg2
);
5547 s390x_paddw (code
, ins
->sreg1
, ins
->sreg2
);
5550 s390x_paddd (code
, ins
->sreg1
, ins
->sreg2
);
5553 s390x_paddq (code
, ins
->sreg1
, ins
->sreg2
);
5557 s390x_psubb (code
, ins
->sreg1
, ins
->sreg2
);
5560 s390x_psubw (code
, ins
->sreg1
, ins
->sreg2
);
5563 s390x_psubd (code
, ins
->sreg1
, ins
->sreg2
);
5566 s390x_psubq (code
, ins
->sreg1
, ins
->sreg2
);
5570 s390x_pmaxub (code
, ins
->sreg1
, ins
->sreg2
);
5573 s390x_pmaxuw (code
, ins
->sreg1
, ins
->sreg2
);
5576 s390x_pmaxud (code
, ins
->sreg1
, ins
->sreg2
);
5580 s390x_pmaxsb (code
, ins
->sreg1
, ins
->sreg2
);
5583 s390x_pmaxsw (code
, ins
->sreg1
, ins
->sreg2
);
5586 s390x_pmaxsd (code
, ins
->sreg1
, ins
->sreg2
);
5590 s390x_pavgb (code
, ins
->sreg1
, ins
->sreg2
);
5593 s390x_pavgw (code
, ins
->sreg1
, ins
->sreg2
);
5597 s390x_pminub (code
, ins
->sreg1
, ins
->sreg2
);
5600 s390x_pminuw (code
, ins
->sreg1
, ins
->sreg2
);
5603 s390x_pminud (code
, ins
->sreg1
, ins
->sreg2
);
5607 s390x_pminsb (code
, ins
->sreg1
, ins
->sreg2
);
5610 s390x_pminsw (code
, ins
->sreg1
, ins
->sreg2
);
5613 s390x_pminsd (code
, ins
->sreg1
, ins
->sreg2
);
5617 s390x_pcmpeqb (code
, ins
->sreg1
, ins
->sreg2
);
5620 s390x_pcmpeqw (code
, ins
->sreg1
, ins
->sreg2
);
5623 s390x_pcmpeqd (code
, ins
->sreg1
, ins
->sreg2
);
5626 s390x_pcmpeqq (code
, ins
->sreg1
, ins
->sreg2
);
5630 s390x_pcmpgtb (code
, ins
->sreg1
, ins
->sreg2
);
5633 s390x_pcmpgtw (code
, ins
->sreg1
, ins
->sreg2
);
5636 s390x_pcmpgtd (code
, ins
->sreg1
, ins
->sreg2
);
5639 s390x_pcmpgtq (code
, ins
->sreg1
, ins
->sreg2
);
5642 case OP_PSUM_ABS_DIFF
:
5643 s390x_psadbw (code
, ins
->sreg1
, ins
->sreg2
);
5646 case OP_UNPACK_LOWB
:
5647 s390x_punpcklbw (code
, ins
->sreg1
, ins
->sreg2
);
5649 case OP_UNPACK_LOWW
:
5650 s390x_punpcklwd (code
, ins
->sreg1
, ins
->sreg2
);
5652 case OP_UNPACK_LOWD
:
5653 s390x_punpckldq (code
, ins
->sreg1
, ins
->sreg2
);
5655 case OP_UNPACK_LOWQ
:
5656 s390x_punpcklqdq (code
, ins
->sreg1
, ins
->sreg2
);
5658 case OP_UNPACK_LOWPS
:
5659 s390x_unpcklps (code
, ins
->sreg1
, ins
->sreg2
);
5661 case OP_UNPACK_LOWPD
:
5662 s390x_unpcklpd (code
, ins
->sreg1
, ins
->sreg2
);
5665 case OP_UNPACK_HIGHB
:
5666 s390x_punpckhbw (code
, ins
->sreg1
, ins
->sreg2
);
5668 case OP_UNPACK_HIGHW
:
5669 s390x_punpckhwd (code
, ins
->sreg1
, ins
->sreg2
);
5671 case OP_UNPACK_HIGHD
:
5672 s390x_punpckhdq (code
, ins
->sreg1
, ins
->sreg2
);
5674 case OP_UNPACK_HIGHQ
:
5675 s390x_punpckhqdq (code
, ins
->sreg1
, ins
->sreg2
);
5677 case OP_UNPACK_HIGHPS
:
5678 s390x_unpckhps (code
, ins
->sreg1
, ins
->sreg2
);
5680 case OP_UNPACK_HIGHPD
:
5681 s390x_unpckhpd (code
, ins
->sreg1
, ins
->sreg2
);
5685 s390x_packsswb (code
, ins
->sreg1
, ins
->sreg2
);
5688 s390x_packssdw (code
, ins
->sreg1
, ins
->sreg2
);
5691 s390x_packuswb (code
, ins
->sreg1
, ins
->sreg2
);
5694 s390x_packusdw (code
, ins
->sreg1
, ins
->sreg2
);
5697 case OP_PADDB_SAT_UN
:
5698 s390x_paddusb (code
, ins
->sreg1
, ins
->sreg2
);
5700 case OP_PSUBB_SAT_UN
:
5701 s390x_psubusb (code
, ins
->sreg1
, ins
->sreg2
);
5703 case OP_PADDW_SAT_UN
:
5704 s390x_paddusw (code
, ins
->sreg1
, ins
->sreg2
);
5706 case OP_PSUBW_SAT_UN
:
5707 s390x_psubusw (code
, ins
->sreg1
, ins
->sreg2
);
5711 s390x_paddsb (code
, ins
->sreg1
, ins
->sreg2
);
5714 s390x_psubsb (code
, ins
->sreg1
, ins
->sreg2
);
5717 s390x_paddsw (code
, ins
->sreg1
, ins
->sreg2
);
5720 s390x_psubsw (code
, ins
->sreg1
, ins
->sreg2
);
5724 s390x_pmullw (code
, ins
->sreg1
, ins
->sreg2
);
5727 s390x_pmulld (code
, ins
->sreg1
, ins
->sreg2
);
5730 s390x_pmuludq (code
, ins
->sreg1
, ins
->sreg2
);
5732 case OP_PMULW_HIGH_UN
:
5733 s390x_pmulhuw (code
, ins
->sreg1
, ins
->sreg2
);
5736 s390x_pmulhw (code
, ins
->sreg1
, ins
->sreg2
);
5740 s390x_psrlw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5743 s390x_psrlw (code
, ins
->dreg
, ins
->sreg2
);
5747 s390x_psraw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5750 s390x_psraw (code
, ins
->dreg
, ins
->sreg2
);
5754 s390x_psllw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5757 s390x_psllw (code
, ins
->dreg
, ins
->sreg2
);
5761 s390x_psrld_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5764 s390x_psrld (code
, ins
->dreg
, ins
->sreg2
);
5768 s390x_psrad_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5771 s390x_psrad (code
, ins
->dreg
, ins
->sreg2
);
5775 s390x_pslld_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5778 s390x_pslld (code
, ins
->dreg
, ins
->sreg2
);
5782 s390x_psrlq_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5785 s390x_psrlq (code
, ins
->dreg
, ins
->sreg2
);
5788 /*TODO: This is appart of the sse spec but not added
5790 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5793 s390x_psraq (code, ins->dreg, ins->sreg2);
5798 s390x_psllq_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5801 s390x_psllq (code
, ins
->dreg
, ins
->sreg2
);
5804 s390x_cvtdq2pd (code
, ins
->dreg
, ins
->sreg1
);
5807 s390x_cvtdq2ps (code
, ins
->dreg
, ins
->sreg1
);
5810 s390x_cvtpd2dq (code
, ins
->dreg
, ins
->sreg1
);
5813 s390x_cvtpd2ps (code
, ins
->dreg
, ins
->sreg1
);
5816 s390x_cvtps2dq (code
, ins
->dreg
, ins
->sreg1
);
5819 s390x_cvtps2pd (code
, ins
->dreg
, ins
->sreg1
);
5822 s390x_cvttpd2dq (code
, ins
->dreg
, ins
->sreg1
);
5825 s390x_cvttps2dq (code
, ins
->dreg
, ins
->sreg1
);
5829 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5832 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5836 amd64_movhlps (code
, MONO_ARCH_FP_SCRATCH_REG
, ins
->sreg1
);
5837 amd64_movd_reg_xreg_size (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
, 8);
5839 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 8);
5844 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5846 amd64_shift_reg_imm (code
, X86_SHR
, ins
->dreg
, ins
->inst_c0
* 8);
5847 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, ins
->opcode
== OP_EXTRACT_I1
, FALSE
);
5851 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5853 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5854 s390x_pextrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5855 amd64_widen_reg_size (code
, ins
->dreg
, ins
->dreg
, ins
->opcode
== OP_EXTRACT_I2
, TRUE
, 4);
5859 amd64_movhlps (code
, ins
->dreg
, ins
->sreg1
);
5861 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5864 s390x_pinsrw_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5866 case OP_EXTRACTX_U2
:
5867 s390x_pextrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5869 case OP_INSERTX_U1_SLOW
:
5870 /*sreg1 is the extracted ireg (scratch)
5871 /sreg2 is the to be inserted ireg (scratch)
5872 /dreg is the xreg to receive the value*/
5874 /*clear the bits from the extracted word*/
5875 amd64_alu_reg_imm (code
, X86_AND
, ins
->sreg1
, ins
->inst_c0
& 1 ? 0x00FF : 0xFF00);
5876 /*shift the value to insert if needed*/
5877 if (ins
->inst_c0
& 1)
5878 amd64_shift_reg_imm_size (code
, X86_SHL
, ins
->sreg2
, 8, 4);
5879 /*join them together*/
5880 amd64_alu (code
, X86_OR
, ins
->sreg1
, ins
->sreg2
);
5881 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
/ 2);
5883 case OP_INSERTX_I4_SLOW
:
5884 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_c0
* 2);
5885 amd64_shift_reg_imm (code
, X86_SHR
, ins
->sreg2
, 16);
5886 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_c0
* 2 + 1);
5888 case OP_INSERTX_I8_SLOW
:
5889 amd64_movd_xreg_reg_size(code
, MONO_ARCH_FP_SCRATCH_REG
, ins
->sreg2
, 8);
5891 amd64_movlhps (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
);
5893 s390x_movsd (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
);
5896 case OP_INSERTX_R4_SLOW
:
5897 switch (ins
->inst_c0
) {
5900 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5902 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5905 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(1, 0, 2, 3));
5907 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5909 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5910 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(1, 0, 2, 3));
5913 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(2, 1, 0, 3));
5915 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5917 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5918 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(2, 1, 0, 3));
5921 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(3, 1, 2, 0));
5923 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5925 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5926 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(3, 1, 2, 0));
5930 case OP_INSERTX_R8_SLOW
:
5932 amd64_movlhps (code
, ins
->dreg
, ins
->sreg2
);
5934 s390x_movsd (code
, ins
->dreg
, ins
->sreg2
);
5936 case OP_STOREX_MEMBASE_REG
:
5937 case OP_STOREX_MEMBASE
:
5938 s390x_movups_membase_reg (code
, ins
->dreg
, ins
->inst_offset
, ins
->sreg1
);
5940 case OP_LOADX_MEMBASE
:
5941 s390x_movups_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5943 case OP_LOADX_ALIGNED_MEMBASE
:
5944 s390x_movaps_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5946 case OP_STOREX_ALIGNED_MEMBASE_REG
:
5947 s390x_movaps_membase_reg (code
, ins
->dreg
, ins
->inst_offset
, ins
->sreg1
);
5949 case OP_STOREX_NTA_MEMBASE_REG
:
5950 s390x_movntps_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5952 case OP_PREFETCH_MEMBASE
:
5953 s390x_prefetch_reg_membase (code
, ins
->backend
.arg_info
, ins
->sreg1
, ins
->inst_offset
);
5957 /*FIXME the peephole pass should have killed this*/
5958 if (ins
->dreg
!= ins
->sreg1
)
5959 s390x_movaps (code
, ins
->dreg
, ins
->sreg1
);
5962 s390x_pxor (code
, ins
->dreg
, ins
->dreg
);
5964 case OP_ICONV_TO_R4_RAW
:
5965 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5968 case OP_FCONV_TO_R8_X
:
5969 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5972 case OP_XCONV_R8_TO_I4
:
5973 s390x_cvttsd2si_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5974 switch (ins
->backend
.source_opcode
) {
5975 case OP_FCONV_TO_I1
:
5976 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, TRUE
, FALSE
);
5978 case OP_FCONV_TO_U1
:
5979 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, FALSE
, FALSE
);
5981 case OP_FCONV_TO_I2
:
5982 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, TRUE
, TRUE
);
5984 case OP_FCONV_TO_U2
:
5985 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, FALSE
, TRUE
);
5991 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, 0);
5992 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, 1);
5993 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5996 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5997 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
6000 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 8);
6001 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0x44);
6005 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
6007 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
6008 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->dreg
);
6010 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
6013 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
6014 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0x44);
6018 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins
->opcode
), __FUNCTION__
);
6019 g_assert_not_reached ();
6022 if ((cfg
->opt
& MONO_OPT_BRANCH
) && ((code
- cfg
->native_code
- offset
) > max_len
)) {
6023 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
6024 mono_inst_name (ins
->opcode
), max_len
, code
- cfg
->native_code
- offset
);
6025 g_assert_not_reached ();
6029 set_code_cursor (cfg
, code
);
6032 /*========================= End of Function ========================*/
6034 /*------------------------------------------------------------------*/
6036 /* Name - mono_arch_register_lowlevel_calls */
6038 /* Function - Register routines to help with --trace operation. */
6040 /*------------------------------------------------------------------*/
6043 mono_arch_register_lowlevel_calls (void)
6047 /*========================= End of Function ========================*/
6049 /*------------------------------------------------------------------*/
6051 /* Name - mono_arch_patch_code */
6053 /* Function - Process the patch data created during the */
6054 /* instruction build process. This resolves jumps, */
6055 /* calls, variables etc. */
6057 /*------------------------------------------------------------------*/
6060 mono_arch_patch_code (MonoCompile
*cfg
, MonoMethod
*method
, MonoDomain
*domain
,
6061 guint8
*code
, MonoJumpInfo
*ji
, gboolean run_cctors
,
6064 MonoJumpInfo
*patch_info
;
6068 for (patch_info
= ji
; patch_info
; patch_info
= patch_info
->next
) {
6069 unsigned char *ip
= patch_info
->ip
.i
+ code
;
6070 gconstpointer target
= NULL
;
6072 target
= mono_resolve_patch_target (method
, domain
, code
,
6073 patch_info
, run_cctors
, error
);
6074 return_if_nok (error
);
6076 switch (patch_info
->type
) {
6077 case MONO_PATCH_INFO_IP
:
6078 case MONO_PATCH_INFO_LDSTR
:
6079 case MONO_PATCH_INFO_TYPE_FROM_HANDLE
:
6080 case MONO_PATCH_INFO_LDTOKEN
:
6081 case MONO_PATCH_INFO_EXC
:
6082 s390_patch_addr (ip
, (guint64
) target
);
6084 case MONO_PATCH_INFO_METHOD
:
6085 case MONO_PATCH_INFO_INTERNAL_METHOD
:
6086 case MONO_PATCH_INFO_JIT_ICALL_ADDR
:
6087 case MONO_PATCH_INFO_RGCTX_FETCH
:
6088 case MONO_PATCH_INFO_ABS
: {
6089 S390_EMIT_CALL (ip
, target
);
6092 case MONO_PATCH_INFO_SWITCH
:
6093 /*----------------------------------*/
6094 /* ip points at the basr r13,0/j +4 */
6095 /* instruction the vtable value */
6096 /* follows this (i.e. ip+6) */
6097 /*----------------------------------*/
6098 S390_EMIT_LOAD (ip
, target
);
6100 case MONO_PATCH_INFO_METHODCONST
:
6101 case MONO_PATCH_INFO_CLASS
:
6102 case MONO_PATCH_INFO_IMAGE
:
6103 case MONO_PATCH_INFO_FIELD
:
6104 case MONO_PATCH_INFO_IID
:
6105 case MONO_PATCH_INFO_EXC_NAME
:
6106 target
= S390_RELATIVE(target
, ip
);
6107 s390_patch_rel (ip
, (guint64
) target
);
6109 case MONO_PATCH_INFO_R4
:
6110 case MONO_PATCH_INFO_R8
:
6111 case MONO_PATCH_INFO_METHOD_REL
:
6112 g_assert_not_reached ();
6115 target
= S390_RELATIVE(target
, ip
);
6117 s390_patch_rel (ip
, (guint64
) target
);
6122 /*========================= End of Function ========================*/
6124 /*------------------------------------------------------------------*/
6126 /* Name - mono_arch_emit_prolog */
6128 /* Function - Create the instruction sequence for a function */
6131 /*------------------------------------------------------------------*/
6134 mono_arch_emit_prolog (MonoCompile
*cfg
)
6136 MonoMethod
*method
= cfg
->method
;
6138 MonoMethodSignature
*sig
;
6140 long alloc_size
, pos
, max_offset
, i
, cfa_offset
= 0;
6150 cfg
->code_size
= 512;
6152 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (method
)) {
6154 traceSize
= S390_TRACE_STACK_SIZE
;
6155 cfg
->code_size
+= 256;
6158 if (method
->save_lmf
)
6159 cfg
->code_size
+= 200;
6161 cfg
->native_code
= code
= g_malloc (cfg
->code_size
);
6163 mono_emit_unwind_op_def_cfa (cfg
, code
, STK_BASE
, 0);
6164 emit_unwind_regs(cfg
, code
, s390_r6
, s390_r14
, S390_REG_SAVE_OFFSET
);
6165 s390_stmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
6166 mono_emit_unwind_op_offset (cfg
, code
, s390_r14
, S390_RET_ADDR_OFFSET
);
6167 mini_gc_set_slot_type_from_cfa (cfg
, S390_RET_ADDR_OFFSET
, SLOT_NOREF
);
6168 if (cfg
->arch
.bkchain_reg
!= -1)
6169 s390_lgr (code
, cfg
->arch
.bkchain_reg
, STK_BASE
);
6171 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
6172 cfg
->used_int_regs
|= 1 << s390_r11
;
6175 if ((cfg
->arch
.used_fp_regs
& S390_FP_SAVE_MASK
) != 0) {
6176 for (int i
=8; i
<16; i
++) {
6177 if (cfg
->arch
.used_fp_regs
& (1 << i
))
6178 fpOffset
+= sizeof(double);
6180 fpOffset
= S390_ALIGN(fpOffset
, 16);
6182 cfg
->arch
.fpSize
= fpOffset
;
6184 alloc_size
= cfg
->stack_offset
+ fpOffset
+ traceSize
;
6186 cfg
->stack_usage
= cfa_offset
= alloc_size
;
6187 s390_lgr (code
, s390_r11
, STK_BASE
);
6188 if (s390_is_imm16 (alloc_size
)) {
6189 s390_aghi (code
, STK_BASE
, -alloc_size
);
6190 } else if (s390_is_imm32 (alloc_size
)) {
6191 s390_agfi (code
, STK_BASE
, -alloc_size
);
6193 int stackSize
= alloc_size
;
6194 while (stackSize
> INT_MAX
) {
6195 s390_agfi (code
, STK_BASE
, -INT_MAX
);
6196 stackSize
-= INT_MAX
;
6198 s390_agfi (code
, STK_BASE
, -stackSize
);
6200 s390_stg (code
, s390_r11
, 0, STK_BASE
, 0);
6205 s390_lgr (code
, s390_r1
, s390_r11
);
6206 s390_aghi (code
, s390_r1
, -fpOffset
);
6207 for (int i
=8; i
<16; i
++) {
6208 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
6209 emit_unwind_regs(cfg
, code
, 16+i
, 16+i
, stkOffset
+fpOffset
);
6210 s390_std (code
, i
, 0, s390_r1
, stkOffset
);
6211 stkOffset
+= sizeof(double);
6216 mono_emit_unwind_op_def_cfa_offset (cfg
, code
, alloc_size
);
6218 if (cfg
->frame_reg
!= STK_BASE
)
6219 s390_lgr (code
, s390_r11
, STK_BASE
);
6221 mono_emit_unwind_op_def_cfa_reg (cfg
, code
, cfg
->frame_reg
);
6223 /* store runtime generic context */
6224 if (cfg
->rgctx_var
) {
6225 g_assert (cfg
->rgctx_var
->opcode
== OP_REGOFFSET
);
6227 s390_stg (code
, MONO_ARCH_RGCTX_REG
, 0,
6228 cfg
->rgctx_var
->inst_basereg
,
6229 cfg
->rgctx_var
->inst_offset
);
6232 /* compute max_offset in order to use short forward jumps
6233 * we always do it on s390 because the immediate displacement
6234 * for jumps is too small
6237 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
6239 bb
->max_offset
= max_offset
;
6241 MONO_BB_FOR_EACH_INS (bb
, ins
)
6242 max_offset
+= ins_get_size (ins
->opcode
);
6245 /* load arguments allocated to register from the stack */
6246 sig
= mono_method_signature (method
);
6249 cinfo
= get_call_info (cfg
->mempool
, sig
);
6251 if (cinfo
->struct_ret
) {
6252 ArgInfo
*ainfo
= &cinfo
->ret
;
6253 inst
= cfg
->vret_addr
;
6254 inst
->backend
.size
= ainfo
->vtsize
;
6255 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6258 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
6259 ArgInfo
*ainfo
= cinfo
->args
+ i
;
6260 inst
= cfg
->args
[pos
];
6262 if (inst
->opcode
== OP_VTARG_ADDR
)
6263 inst
= inst
->inst_left
;
6265 if (inst
->opcode
== OP_REGVAR
) {
6266 if (ainfo
->regtype
== RegTypeGeneral
)
6267 s390_lgr (code
, inst
->dreg
, ainfo
->reg
);
6268 else if (ainfo
->regtype
== RegTypeFP
) {
6269 if (inst
->dreg
!= ainfo
->reg
) {
6270 s390_ldr (code
, inst
->dreg
, ainfo
->reg
);
6272 } else if (ainfo
->regtype
== RegTypeFPR4
) {
6274 s390_ledbr (code
, inst
->dreg
, ainfo
->reg
);
6275 } else if (ainfo
->regtype
== RegTypeBase
) {
6276 s390_lgr (code
, s390_r13
, STK_BASE
);
6277 s390_aghi (code
, s390_r13
, alloc_size
);
6278 s390_lg (code
, inst
->dreg
, 0, s390_r13
, ainfo
->offset
);
6280 g_assert_not_reached ();
6282 if (cfg
->verbose_level
> 2)
6283 g_print ("Argument %d assigned to register %s\n",
6284 pos
, mono_arch_regname (inst
->dreg
));
6286 if (ainfo
->regtype
== RegTypeGeneral
) {
6287 if (!((ainfo
->reg
>= 2) && (ainfo
->reg
<= 6)))
6288 g_assert_not_reached();
6289 switch (ainfo
->size
) {
6291 s390_stc (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6294 s390_sth (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6297 s390_st (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6300 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6303 } else if (ainfo
->regtype
== RegTypeBase
) {
6304 } else if (ainfo
->regtype
== RegTypeFP
) {
6305 s390_std (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6306 } else if (ainfo
->regtype
== RegTypeFPR4
) {
6307 s390_ste (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6308 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
6309 int doffset
= inst
->inst_offset
;
6311 if (ainfo
->reg
!= STK_BASE
)
6315 s390_lgr (code
, s390_r13
, STK_BASE
);
6316 s390_aghi (code
, s390_r13
, alloc_size
);
6319 size
= (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
6320 ? mono_class_native_size(mono_class_from_mono_type(inst
->inst_vtype
), NULL
)
6325 if (ainfo
->reg
== STK_BASE
)
6326 s390_ic (code
, reg
, 0, s390_r13
, ainfo
->offset
+7);
6327 s390_stc (code
, reg
, 0, inst
->inst_basereg
, doffset
);
6330 if (ainfo
->reg
== STK_BASE
)
6331 s390_lh (code
, reg
, 0, s390_r13
, ainfo
->offset
+6);
6332 s390_sth (code
, reg
, 0, inst
->inst_basereg
, doffset
);
6335 if (ainfo
->reg
== STK_BASE
)
6336 s390_l (code
, reg
, 0, s390_r13
, ainfo
->offset
+4);
6337 s390_st (code
, reg
, 0, inst
->inst_basereg
, doffset
);
6340 if (ainfo
->reg
== STK_BASE
)
6341 s390_lg (code
, reg
, 0, s390_r13
, ainfo
->offset
);
6342 s390_stg (code
, reg
, 0, inst
->inst_basereg
, doffset
);
6345 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
6346 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
6347 } else if (ainfo
->regtype
== RegTypeStructByAddrOnStack
) {
6349 g_assert_not_reached ();
6354 if (method
->save_lmf
) {
6355 /*---------------------------------------------------------------*/
6356 /* build the MonoLMF structure on the stack - see mini-s390x.h */
6357 /*---------------------------------------------------------------*/
6358 lmfOffset
= alloc_size
- sizeof(MonoLMF
);
6360 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
6361 s390_aghi (code
, s390_r13
, lmfOffset
);
6363 /*---------------------------------------------------------------*/
6364 /* Preserve the parameter registers while we fix up the lmf */
6365 /*---------------------------------------------------------------*/
6366 s390_stmg (code
, s390_r2
, s390_r6
, s390_r13
,
6367 G_STRUCT_OFFSET(MonoLMF
, pregs
[0]));
6369 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[0]), SLOT_NOREF
);
6370 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[1]), SLOT_NOREF
);
6371 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[2]), SLOT_NOREF
);
6372 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[3]), SLOT_NOREF
);
6373 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[4]), SLOT_NOREF
);
6375 /*---------------------------------------------------------------*/
6376 /* On return from this call r2 have the address of the &lmf */
6377 /*---------------------------------------------------------------*/
6378 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
6379 MONO_PATCH_INFO_INTERNAL_METHOD
,
6380 (gpointer
)"mono_tls_get_lmf_addr");
6381 S390_CALL_TEMPLATE(code
, s390_r1
);
6383 /*---------------------------------------------------------------*/
6384 /* Set lmf.lmf_addr = jit_tls->lmf */
6385 /*---------------------------------------------------------------*/
6386 s390_stg (code
, s390_r2
, 0, s390_r13
,
6387 G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
6388 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, lmf_addr
), SLOT_NOREF
);
6390 /*---------------------------------------------------------------*/
6391 /* Get current lmf */
6392 /*---------------------------------------------------------------*/
6393 s390_lg (code
, s390_r0
, 0, s390_r2
, 0);
6395 /*---------------------------------------------------------------*/
6396 /* Set our lmf as the current lmf */
6397 /*---------------------------------------------------------------*/
6398 s390_stg (code
, s390_r13
, 0, s390_r2
, 0);
6400 /*---------------------------------------------------------------*/
6401 /* Have our lmf.previous_lmf point to the last lmf */
6402 /*---------------------------------------------------------------*/
6403 s390_stg (code
, s390_r0
, 0, s390_r13
,
6404 G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
6405 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, previous_lmf
), SLOT_NOREF
);
6407 /*---------------------------------------------------------------*/
6408 /* save method info */
6409 /*---------------------------------------------------------------*/
6410 S390_SET (code
, s390_r1
, method
);
6411 s390_stg (code
, s390_r1
, 0, s390_r13
,
6412 G_STRUCT_OFFSET(MonoLMF
, method
));
6413 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, method
), SLOT_NOREF
);
6415 /*---------------------------------------------------------------*/
6416 /* save the current IP */
6417 /*---------------------------------------------------------------*/
6418 s390_stg (code
, STK_BASE
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, ebp
));
6419 s390_basr (code
, s390_r1
, 0);
6420 s390_stg (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, eip
));
6421 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, ebp
), SLOT_NOREF
);
6422 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, eip
), SLOT_NOREF
);
6424 /*---------------------------------------------------------------*/
6425 /* Save general and floating point registers */
6426 /*---------------------------------------------------------------*/
6427 s390_stmg (code
, s390_r2
, s390_r12
, s390_r13
,
6428 G_STRUCT_OFFSET(MonoLMF
, gregs
[2]));
6429 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[0]), SLOT_NOREF
);
6430 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[1]), SLOT_NOREF
);
6431 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[2]), SLOT_NOREF
);
6432 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[3]), SLOT_NOREF
);
6433 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[4]), SLOT_NOREF
);
6434 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[5]), SLOT_NOREF
);
6435 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[6]), SLOT_NOREF
);
6436 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[7]), SLOT_NOREF
);
6437 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[8]), SLOT_NOREF
);
6438 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[9]), SLOT_NOREF
);
6439 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[10]), SLOT_NOREF
);
6441 fpOffset
= lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, fregs
[0]);
6442 for (i
= 0; i
< 16; i
++) {
6443 s390_std (code
, i
, 0, s390_r13
,
6444 G_STRUCT_OFFSET(MonoLMF
, fregs
[i
]));
6445 mini_gc_set_slot_type_from_fp (cfg
, fpOffset
, SLOT_NOREF
);
6446 fpOffset
+= sizeof(double);
6449 /*---------------------------------------------------------------*/
6450 /* Restore the parameter registers now that we've set up the lmf */
6451 /*---------------------------------------------------------------*/
6452 s390_lmg (code
, s390_r2
, s390_r6
, s390_r13
,
6453 G_STRUCT_OFFSET(MonoLMF
, pregs
[0]));
6456 if (cfg
->method
->save_lmf
)
6457 argsClobbered
= TRUE
;
6460 argsClobbered
= TRUE
;
6461 code
= mono_arch_instrument_prolog (cfg
, enter_method
, code
, TRUE
);
6465 * Optimize the common case of the first bblock making a call with the same
6466 * arguments as the method. This works because the arguments are still in their
6467 * original argument registers.
6469 if (!argsClobbered
) {
6470 MonoBasicBlock
*first_bb
= cfg
->bb_entry
;
6472 int filter
= FILTER_IL_SEQ_POINT
;
6474 next
= mono_bb_first_inst (first_bb
, filter
);
6475 if (!next
&& first_bb
->next_bb
) {
6476 first_bb
= first_bb
->next_bb
;
6477 next
= mono_bb_first_inst (first_bb
, filter
);
6480 if (first_bb
->in_count
> 1)
6483 for (i
= 0; next
&& i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
6484 ArgInfo
*ainfo
= cinfo
->args
+ i
;
6485 gboolean match
= FALSE
;
6487 inst
= cfg
->args
[i
];
6488 if (inst
->opcode
!= OP_REGVAR
) {
6489 switch (ainfo
->regtype
) {
6490 case RegTypeGeneral
: {
6491 if (((next
->opcode
== OP_LOAD_MEMBASE
) ||
6492 (next
->opcode
== OP_LOADI4_MEMBASE
)) &&
6493 next
->inst_basereg
== inst
->inst_basereg
&&
6494 next
->inst_offset
== inst
->inst_offset
) {
6495 if (next
->dreg
== ainfo
->reg
) {
6499 next
->opcode
= OP_MOVE
;
6500 next
->sreg1
= ainfo
->reg
;
6501 /* Only continue if the instruction doesn't change argument regs */
6502 if (next
->dreg
== ainfo
->reg
)
6512 /* Argument allocated to (non-volatile) register */
6513 switch (ainfo
->regtype
) {
6514 case RegTypeGeneral
:
6515 if (next
->opcode
== OP_MOVE
&&
6516 next
->sreg1
== inst
->dreg
&&
6517 next
->dreg
== ainfo
->reg
) {
6528 next
= mono_inst_next (next
, filter
);
6535 set_code_cursor (cfg
, code
);
6540 /*========================= End of Function ========================*/
6542 /*------------------------------------------------------------------*/
6544 /* Name - mono_arch_emit_epilog */
6546 /* Function - Emit the instructions for a function epilog. */
6548 /*------------------------------------------------------------------*/
6551 mono_arch_emit_epilog (MonoCompile
*cfg
)
6553 MonoMethod
*method
= cfg
->method
;
6556 int max_epilog_size
= 96;
6559 if (cfg
->method
->save_lmf
)
6560 max_epilog_size
+= 128;
6562 if (mono_jit_trace_calls
!= NULL
)
6563 max_epilog_size
+= 128;
6565 code
= realloc_code (cfg
, max_epilog_size
);
6567 if (mono_jit_trace_calls
!= NULL
&& mono_trace_eval (method
)) {
6568 code
= mono_arch_instrument_epilog (cfg
, leave_method
, code
, TRUE
);
6572 if (method
->save_lmf
)
6573 restoreLMF(code
, cfg
->frame_reg
, cfg
->stack_usage
);
6575 code
= backUpStackPtr(cfg
, code
);
6577 if (cfg
->arch
.fpSize
!= 0) {
6578 fpOffset
= -cfg
->arch
.fpSize
;
6579 for (int i
=8; i
<16; i
++) {
6580 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
6581 s390_ldy (code
, i
, 0, STK_BASE
, fpOffset
);
6582 fpOffset
+= sizeof(double);
6587 s390_lmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
6588 s390_br (code
, s390_r14
);
6590 set_code_cursor (cfg
, code
);
6594 /*========================= End of Function ========================*/
6596 /*------------------------------------------------------------------*/
6598 /* Name - mono_arch_emit_exceptions */
6600 /* Function - Emit the blocks to handle exception conditions. */
6602 /*------------------------------------------------------------------*/
6605 mono_arch_emit_exceptions (MonoCompile
*cfg
)
6607 MonoJumpInfo
*patch_info
;
6613 MonoClass
*exc_classes
[MAX_EXC
];
6614 guint8
*exc_throw_start
[MAX_EXC
];
6616 for (patch_info
= cfg
->patch_info
;
6618 patch_info
= patch_info
->next
) {
6619 if (patch_info
->type
== MONO_PATCH_INFO_EXC
)
6623 code_size
= exc_count
* 48;
6625 code
= realloc_code (cfg
, code_size
);
6627 /*---------------------------------------------------------------------*/
6628 /* Add code to raise exceptions */
6629 /*---------------------------------------------------------------------*/
6630 for (patch_info
= cfg
->patch_info
; patch_info
; patch_info
= patch_info
->next
) {
6631 switch (patch_info
->type
) {
6632 case MONO_PATCH_INFO_EXC
: {
6633 guint8
*ip
= patch_info
->ip
.i
+ cfg
->native_code
;
6634 MonoClass
*exc_class
;
6637 /*-----------------------------------------------------*/
6638 /* Patch the branch in epilog to come here */
6639 /*-----------------------------------------------------*/
6640 s390_patch_rel (ip
+ 2, (guint64
) S390_RELATIVE(code
,ip
));
6642 exc_class
= mono_class_load_from_name (mono_defaults
.corlib
,
6644 patch_info
->data
.name
);
6645 throw_ip
= patch_info
->ip
.i
;
6647 for (iExc
= 0; iExc
< nThrows
; ++iExc
)
6648 if (exc_classes
[iExc
] == exc_class
)
6651 if (iExc
< nThrows
) {
6652 s390_jcl (code
, S390_CC_UN
,
6653 (guint64
) exc_throw_start
[iExc
]);
6654 patch_info
->type
= MONO_PATCH_INFO_NONE
;
6657 if (nThrows
< MAX_EXC
) {
6658 exc_classes
[nThrows
] = exc_class
;
6659 exc_throw_start
[nThrows
] = code
;
6662 /*---------------------------------------------*/
6663 /* Patch the parameter passed to the handler */
6664 /*---------------------------------------------*/
6665 S390_SET (code
, s390_r2
, m_class_get_type_token (exc_class
));
6666 /*---------------------------------------------*/
6667 /* Load return address & parameter register */
6668 /*---------------------------------------------*/
6669 s390_larl (code
, s390_r14
, (guint64
)S390_RELATIVE((patch_info
->ip
.i
+
6670 cfg
->native_code
+ 8), code
));
6671 /*---------------------------------------------*/
6672 /* Reuse the current patch to set the jump */
6673 /*---------------------------------------------*/
6674 patch_info
->type
= MONO_PATCH_INFO_INTERNAL_METHOD
;
6675 patch_info
->data
.name
= "mono_arch_throw_corlib_exception";
6676 patch_info
->ip
.i
= code
- cfg
->native_code
;
6677 S390_BR_TEMPLATE (code
, s390_r1
);
6686 set_code_cursor (cfg
, code
);
6689 /*========================= End of Function ========================*/
6691 /*------------------------------------------------------------------*/
6693 /* Name - mono_arch_finish_init */
6695 /* Function - Setup the JIT's Thread Level Specific Data. */
6697 /*------------------------------------------------------------------*/
6700 mono_arch_finish_init (void)
6704 /*========================= End of Function ========================*/
6706 /*------------------------------------------------------------------*/
6708 /* Name - mono_arch_free_jit_tls_data */
6710 /* Function - Free tls data. */
6712 /*------------------------------------------------------------------*/
6715 mono_arch_free_jit_tls_data (MonoJitTlsData
*tls
)
6719 /*========================= End of Function ========================*/
6721 /*------------------------------------------------------------------*/
6723 /* Name - mono_arch_emit_inst_for_method */
6725 /*------------------------------------------------------------------*/
6728 mono_arch_emit_inst_for_method (MonoCompile
*cfg
, MonoMethod
*cmethod
, MonoMethodSignature
*fsig
, MonoInst
**args
)
6733 /*========================= End of Function ========================*/
6735 /*------------------------------------------------------------------*/
6737 /* Name - mono_arch_decompose_opts */
6739 /* Function - Decompose opcode into a System z opcode. */
6741 /*------------------------------------------------------------------*/
6744 mono_arch_decompose_opts (MonoCompile
*cfg
, MonoInst
*ins
)
6747 * Have to rename these to avoid being decomposed normally, since the normal
6748 * decomposition does not work on S390.
6750 switch (ins
->opcode
) {
6752 ins
->opcode
= OP_S390_ISUB_OVF
;
6754 case OP_ISUB_OVF_UN
:
6755 ins
->opcode
= OP_S390_ISUB_OVF_UN
;
6758 ins
->opcode
= OP_S390_IADD_OVF
;
6760 case OP_IADD_OVF_UN
:
6761 ins
->opcode
= OP_S390_IADD_OVF_UN
;
6764 ins
->opcode
= OP_S390_LADD_OVF
;
6766 case OP_LADD_OVF_UN
:
6767 ins
->opcode
= OP_S390_LADD_OVF_UN
;
6770 ins
->opcode
= OP_S390_LSUB_OVF
;
6772 case OP_LSUB_OVF_UN
:
6773 ins
->opcode
= OP_S390_LSUB_OVF_UN
;
6780 /*========================= End of Function ========================*/
6782 /*------------------------------------------------------------------*/
6784 /* Name - mono_arch_regalloc_cost */
6786 /* Function - Determine the cost, in the number of memory */
6787 /* references, of the action of allocating the var- */
6788 /* iable VMV into a register during global register */
6791 /* Returns - Cost */
6793 /*------------------------------------------------------------------*/
6796 mono_arch_regalloc_cost (MonoCompile
*cfg
, MonoMethodVar
*vmv
)
6802 /*========================= End of Function ========================*/
6804 /*------------------------------------------------------------------*/
6806 /* Name - mono_arch_flush_register_windows */
6812 /*------------------------------------------------------------------*/
6815 mono_arch_flush_register_windows (void)
6819 /*========================= End of Function ========================*/
6821 /*------------------------------------------------------------------*/
6823 /* Name - mono_arch_is_inst_imm */
6825 /* Function - Determine if operand qualifies as an immediate */
6826 /* value. For s390 this is a value -32768-32768 */
6828 /* Returns - True|False - is [not] immediate value. */
6830 /*------------------------------------------------------------------*/
6833 mono_arch_is_inst_imm (int opcode
, int imm_opcode
, gint64 imm
)
6835 return s390_is_imm32 (imm
);
6838 /*========================= End of Function ========================*/
6840 /*------------------------------------------------------------------*/
6842 /* Name - mono_arch_get_patch_offset */
6844 /* Function - Dummy entry point until s390x supports aot. */
6846 /* Returns - Offset for patch. */
6848 /*------------------------------------------------------------------*/
6851 mono_arch_get_patch_offset (guint8
*code
)
6856 /*========================= End of Function ========================*/
6858 /*------------------------------------------------------------------*/
6860 /* Name - mono_arch_context_get_int_reg. */
6864 /* Returns - Return a register from the context. */
6866 /*------------------------------------------------------------------*/
6869 mono_arch_context_get_int_reg (MonoContext
*ctx
, int reg
)
6871 return ((mgreg_t
) ctx
->uc_mcontext
.gregs
[reg
]);
6874 /*========================= End of Function ========================*/
6876 /*------------------------------------------------------------------*/
6878 /* Name - mono_arch_context_set_int_reg. */
6880 /* Function - Set a value in a specified register. */
6882 /*------------------------------------------------------------------*/
6885 mono_arch_context_set_int_reg (MonoContext
*ctx
, int reg
, mgreg_t val
)
6887 ctx
->uc_mcontext
.gregs
[reg
] = val
;
6890 /*========================= End of Function ========================*/
6892 /*------------------------------------------------------------------*/
6894 /* Name - mono_arch_get_this_arg_from_call. */
6898 /*------------------------------------------------------------------*/
6901 mono_arch_get_this_arg_from_call (mgreg_t
*regs
, guint8
*code
)
6903 return (gpointer
) regs
[s390_r2
];
6906 /*========================= End of Function ========================*/
6908 /*------------------------------------------------------------------*/
6910 /* Name - get_delegate_invoke_impl. */
6914 /*------------------------------------------------------------------*/
6917 get_delegate_invoke_impl (MonoTrampInfo
**info
, gboolean has_target
, guint32 param_count
, gboolean aot
)
6919 guint8
*code
, *start
;
6924 start
= code
= mono_global_codeman_reserve (size
);
6926 /* Replace the this argument with the target */
6927 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
6928 s390_lg (code
, s390_r2
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, target
));
6929 s390_br (code
, s390_r1
);
6930 g_assert ((code
- start
) <= size
);
6932 mono_arch_flush_icache (start
, size
);
6933 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6937 size
= 32 + param_count
* 8;
6938 start
= code
= mono_global_codeman_reserve (size
);
6940 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
6941 /* slide down the arguments */
6942 for (i
= 0; i
< param_count
; ++i
) {
6943 s390_lgr (code
, (s390_r2
+ i
), (s390_r2
+ i
+ 1));
6945 s390_br (code
, s390_r1
);
6947 g_assert ((code
- start
) <= size
);
6949 mono_arch_flush_icache (start
, size
);
6950 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6954 *info
= mono_tramp_info_create ("delegate_invoke_impl_has_target", start
, code
- start
, NULL
, NULL
);
6956 char *name
= g_strdup_printf ("delegate_invoke_impl_target_%d", param_count
);
6957 *info
= mono_tramp_info_create (name
, start
, code
- start
, NULL
, NULL
);
6964 /*========================= End of Function ========================*/
6966 /*------------------------------------------------------------------*/
6968 /* Name - mono_arch_get_delegate_invoke_impls. */
6972 /*------------------------------------------------------------------*/
6975 mono_arch_get_delegate_invoke_impls (void)
6978 MonoTrampInfo
*info
;
6981 get_delegate_invoke_impl (&info
, TRUE
, 0, TRUE
);
6982 res
= g_slist_prepend (res
, info
);
6984 for (i
= 0; i
<= MAX_ARCH_DELEGATE_PARAMS
; ++i
) {
6985 get_delegate_invoke_impl (&info
, FALSE
, i
, TRUE
);
6986 res
= g_slist_prepend (res
, info
);
6992 /*========================= End of Function ========================*/
6994 /*------------------------------------------------------------------*/
6996 /* Name - mono_arch_get_delegate_invoke_impl. */
7000 /*------------------------------------------------------------------*/
7003 mono_arch_get_delegate_invoke_impl (MonoMethodSignature
*sig
, gboolean has_target
)
7005 guint8
*code
, *start
;
7007 /* FIXME: Support more cases */
7008 if (MONO_TYPE_ISSTRUCT (sig
->ret
))
7012 static guint8
* cached
= NULL
;
7017 if (mono_ee_features
.use_aot_trampolines
) {
7018 start
= mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
7020 MonoTrampInfo
*info
;
7021 start
= get_delegate_invoke_impl (&info
, TRUE
, 0, FALSE
);
7022 mono_tramp_info_register (info
, NULL
);
7025 mono_memory_barrier ();
7029 static guint8
* cache
[MAX_ARCH_DELEGATE_PARAMS
+ 1] = {NULL
};
7032 if (sig
->param_count
> MAX_ARCH_DELEGATE_PARAMS
)
7034 for (i
= 0; i
< sig
->param_count
; ++i
)
7035 if (!mono_is_regsize_var (sig
->params
[i
]))
7039 code
= cache
[sig
->param_count
];
7043 if (mono_ee_features
.use_aot_trampolines
) {
7044 char *name
= g_strdup_printf ("delegate_invoke_impl_target_%d", sig
->param_count
);
7045 start
= mono_aot_get_trampoline (name
);
7048 MonoTrampInfo
*info
;
7049 start
= get_delegate_invoke_impl (&info
, FALSE
, sig
->param_count
, FALSE
);
7050 mono_tramp_info_register (info
, NULL
);
7053 mono_memory_barrier ();
7055 cache
[sig
->param_count
] = start
;
7060 /*========================= End of Function ========================*/
7062 /*------------------------------------------------------------------*/
7064 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
7068 /*------------------------------------------------------------------*/
7071 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature
*sig
, MonoMethod
*method
,
7072 int offset
, gboolean load_imt_reg
)
7074 guint8
*code
, *start
;
7077 start
= code
= mono_global_codeman_reserve (size
);
7080 * Replace the "this" argument with the target
7082 s390_lgr (code
, s390_r1
, s390_r2
);
7083 s390_lg (code
, s390_r2
, 0, s390_r1
, MONO_STRUCT_OFFSET(MonoDelegate
, target
));
7086 * Load the IMT register, if needed
7089 s390_lg (code
, MONO_ARCH_IMT_REG
, 0, s390_r1
, MONO_STRUCT_OFFSET(MonoDelegate
, method
));
7095 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET(MonoObject
, vtable
));
7097 s390_agfi(code
, s390_r1
, offset
);
7099 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
7100 s390_br (code
, s390_r1
);
7102 mono_arch_flush_icache (start
, code
- start
);
7103 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
7108 /*========================= End of Function ========================*/
7110 /*------------------------------------------------------------------*/
7112 /* Name - mono_arch_build_imt_trampoline. */
7116 /*------------------------------------------------------------------*/
7119 mono_arch_build_imt_trampoline (MonoVTable
*vtable
, MonoDomain
*domain
,
7120 MonoIMTCheckItem
**imt_entries
, int count
,
7121 gpointer fail_tramp
)
7125 guchar
*code
, *start
;
7128 for (i
= 0; i
< count
; ++i
) {
7129 MonoIMTCheckItem
*item
= imt_entries
[i
];
7130 if (item
->is_equals
) {
7131 if (item
->check_target_idx
) {
7132 if (!item
->compare_done
)
7133 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
7134 if (item
->has_target_code
)
7135 item
->chunk_size
+= BR_SIZE
+ JUMP_SIZE
+ LOADCON_SIZE
;
7137 item
->chunk_size
+= BR_SIZE
+ JUMP_SIZE
+ LOADCON_SIZE
+
7141 item
->chunk_size
+= CMP_SIZE
+ 2 * BR_SIZE
+ JUMP_SIZE
+
7143 if (!item
->has_target_code
)
7144 item
->chunk_size
+= LOAD_SIZE
;
7146 item
->chunk_size
+= LOADCON_SIZE
+ LOAD_SIZE
+ BR_SIZE
;
7147 #if ENABLE_WRONG_METHOD_CHECK
7148 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
7153 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
7154 imt_entries
[item
->check_target_idx
]->compare_done
= TRUE
;
7156 size
+= item
->chunk_size
;
7160 code
= mono_method_alloc_generic_virtual_trampoline (domain
, size
);
7162 code
= mono_domain_code_reserve (domain
, size
);
7166 for (i
= 0; i
< count
; ++i
) {
7167 MonoIMTCheckItem
*item
= imt_entries
[i
];
7168 item
->code_target
= (guint8
*) code
;
7169 if (item
->is_equals
) {
7170 if (item
->check_target_idx
) {
7171 if (!item
->compare_done
) {
7172 S390_SET (code
, s390_r0
, item
->key
);
7173 s390_cgr (code
, s390_r0
, MONO_ARCH_IMT_REG
);
7175 item
->jmp_code
= (guint8
*) code
;
7176 s390_jcl (code
, S390_CC_NE
, 0);
7178 if (item
->has_target_code
) {
7179 S390_SET (code
, s390_r1
, item
->value
.target_code
);
7181 S390_SET (code
, s390_r1
, (&(vtable
->vtable
[item
->value
.vtable_slot
])));
7182 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
7184 s390_br (code
, s390_r1
);
7189 S390_SET (code
, s390_r0
, item
->key
);
7190 s390_cgr (code
, s390_r0
, MONO_ARCH_IMT_REG
);
7191 item
->jmp_code
= (guint8
*) code
;
7192 s390_jcl (code
, S390_CC_NE
, 0);
7193 if (item
->has_target_code
) {
7194 S390_SET (code
, s390_r1
, item
->value
.target_code
);
7197 S390_SET (code
, s390_r1
,
7198 (&(vtable
->vtable
[item
->value
.vtable_slot
])));
7199 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
7201 s390_br (code
, s390_r1
);
7202 target
= (gint64
) S390_RELATIVE(code
, item
->jmp_code
);
7203 s390_patch_rel(item
->jmp_code
+2, target
);
7204 S390_SET (code
, s390_r1
, fail_tramp
);
7205 s390_br (code
, s390_r1
);
7206 item
->jmp_code
= NULL
;
7208 /* enable the commented code to assert on wrong method */
7209 #if ENABLE_WRONG_METHOD_CHECK
7210 g_assert_not_reached ();
7212 S390_SET (code
, s390_r1
, (&(vtable
->vtable
[item
->value
.vtable_slot
])));
7213 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
7214 s390_br (code
, s390_r1
);
7218 S390_SET (code
, s390_r0
, item
->key
);
7219 s390_cgr (code
, MONO_ARCH_IMT_REG
, s390_r0
);
7220 item
->jmp_code
= (guint8
*) code
;
7221 s390_jcl (code
, S390_CC_GE
, 0);
7225 * patch the branches to get to the target items
7227 for (i
= 0; i
< count
; ++i
) {
7228 MonoIMTCheckItem
*item
= imt_entries
[i
];
7229 if (item
->jmp_code
) {
7230 if (item
->check_target_idx
) {
7232 offset
= (gint64
) S390_RELATIVE(imt_entries
[item
->check_target_idx
]->code_target
,
7234 s390_patch_rel ((guchar
*) item
->jmp_code
+ 2, (guint64
) offset
);
7239 mono_arch_flush_icache ((guint8
*)start
, (code
- start
));
7240 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE
, NULL
));
7243 UnlockedAdd (&mono_stats
.imt_trampolines_size
, code
- start
);
7245 g_assert (code
- start
<= size
);
7247 snprintf(trampName
, sizeof(trampName
), "%d_imt_trampoline", domain
->domain_id
);
7248 mono_tramp_info_register (mono_tramp_info_create (trampName
, start
, code
- start
, NULL
, NULL
), domain
);
7253 /*========================= End of Function ========================*/
7255 /*------------------------------------------------------------------*/
7257 /* Name - mono_arch_find_imt_method. */
7259 /* Function - Get the method address from MONO_ARCH_IMT_REG */
7260 /* found in the save area. */
7262 /*------------------------------------------------------------------*/
7265 mono_arch_find_imt_method (mgreg_t
*regs
, guint8
*code
)
7267 return ((MonoMethod
*) regs
[MONO_ARCH_IMT_REG
]);
7270 /*========================= End of Function ========================*/
7272 /*------------------------------------------------------------------*/
7274 /* Name - mono_arch_find_static_call_vtable */
7276 /* Function - Find the static call vtable. */
7278 /*------------------------------------------------------------------*/
7281 mono_arch_find_static_call_vtable (mgreg_t
*regs
, guint8
*code
)
7283 mgreg_t
*r
= (mgreg_t
*)regs
;
7285 return (MonoVTable
*)(gsize
) r
[MONO_ARCH_RGCTX_REG
];
7288 /*========================= End of Function ========================*/
7290 /*------------------------------------------------------------------*/
7292 /* Name - mono_arch_get_cie_program */
7294 /* Function - Find the static call vtable. */
7296 /*------------------------------------------------------------------*/
7299 mono_arch_get_cie_program (void)
7303 mono_add_unwind_op_def_cfa (l
, 0, 0, STK_BASE
, 0);
7308 /*========================= End of Function ========================*/
7310 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7312 /*------------------------------------------------------------------*/
7314 /* Name - mono_arch_set_breakpoint. */
7316 /* Function - Set a breakpoint at the native code corresponding */
7317 /* to JI at NATIVE_OFFSET. The location should */
7318 /* contain code emitted by OP_SEQ_POINT. */
7320 /*------------------------------------------------------------------*/
7323 mono_arch_set_breakpoint (MonoJitInfo
*ji
, guint8
*ip
)
7327 breakpointCode
.pTrigger
= bp_trigger_page
;
7328 memcpy(code
, (void *) &breakpointCode
, BREAKPOINT_SIZE
);
7329 code
+= BREAKPOINT_SIZE
;
7332 /*========================= End of Function ========================*/
7334 /*------------------------------------------------------------------*/
7336 /* Name - mono_arch_clear_breakpoint. */
7338 /* Function - Clear the breakpoint at IP. */
7340 /*------------------------------------------------------------------*/
7343 mono_arch_clear_breakpoint (MonoJitInfo
*ji
, guint8
*ip
)
7348 for (i
= 0; i
< (BREAKPOINT_SIZE
/ S390X_NOP_SIZE
); i
++)
7352 /*========================= End of Function ========================*/
7354 /*------------------------------------------------------------------*/
7356 /* Name - mono_arch_is_breakpoint_event. */
7360 /*------------------------------------------------------------------*/
7363 mono_arch_is_breakpoint_event (void *info
, void *sigctx
)
7365 siginfo_t
* sinfo
= (siginfo_t
*) info
;
7368 * Sometimes the address is off by 4
7370 if (sinfo
->si_addr
>= bp_trigger_page
&& (guint8
*)sinfo
->si_addr
<= (guint8
*)bp_trigger_page
+ 128)
7376 /*========================= End of Function ========================*/
7378 /*------------------------------------------------------------------*/
7380 /* Name - mono_arch_skip_breakpoint. */
7382 /* Function - Modify the CTX so the IP is placed after the */
7383 /* breakpoint instruction, so when we resume, the */
7384 /* instruction is not executed again. */
7386 /*------------------------------------------------------------------*/
7389 mono_arch_skip_breakpoint (MonoContext
*ctx
, MonoJitInfo
*ji
)
7391 MONO_CONTEXT_SET_IP (ctx
, ((guint8
*)MONO_CONTEXT_GET_IP (ctx
) + sizeof(RXY_Format
)));
7394 /*========================= End of Function ========================*/
7396 /*------------------------------------------------------------------*/
7398 /* Name - mono_arch_start_single_stepping. */
7400 /* Function - Start single stepping. */
7402 /*------------------------------------------------------------------*/
7405 mono_arch_start_single_stepping (void)
7407 mono_mprotect (ss_trigger_page
, mono_pagesize (), 0);
7410 /*========================= End of Function ========================*/
7412 /*------------------------------------------------------------------*/
7414 /* Name - mono_arch_stop_single_stepping. */
7416 /* Function - Stop single stepping. */
7418 /*------------------------------------------------------------------*/
7421 mono_arch_stop_single_stepping (void)
7423 mono_mprotect (ss_trigger_page
, mono_pagesize (), MONO_MMAP_READ
);
7426 /*========================= End of Function ========================*/
7428 /*------------------------------------------------------------------*/
7430 /* Name - mono_arch_is_single_step_event. */
7432 /* Function - Return whether the machine state in sigctx cor- */
7433 /* responds to a single step event. */
7435 /*------------------------------------------------------------------*/
7438 mono_arch_is_single_step_event (void *info
, void *sigctx
)
7440 siginfo_t
* sinfo
= (siginfo_t
*) info
;
7443 * Sometimes the address is off by 4
7445 if (sinfo
->si_addr
>= ss_trigger_page
&& (guint8
*)sinfo
->si_addr
<= (guint8
*)ss_trigger_page
+ 128)
7451 /*========================= End of Function ========================*/
7453 /*------------------------------------------------------------------*/
7455 /* Name - mono_arch_skip_single_step. */
7457 /* Function - Modify the ctx so the IP is placed after the */
7458 /* single step trigger instruction, so that the */
7459 /* instruction is not executed again. */
7461 /*------------------------------------------------------------------*/
7464 mono_arch_skip_single_step (MonoContext
*ctx
)
7466 MONO_CONTEXT_SET_IP (ctx
, (guint8
*)MONO_CONTEXT_GET_IP (ctx
) + BREAKPOINT_SIZE
);
7469 /*========================= End of Function ========================*/
7471 /*------------------------------------------------------------------*/
7473 /* Name - mono_arch_create_seq_point_info. */
7475 /* Function - Return a pointer to a data struction which is */
7476 /* used by the sequence point implementation in */
7479 /*------------------------------------------------------------------*/
7482 mono_arch_get_seq_point_info (MonoDomain
*domain
, guint8
*code
)
7488 /*========================= End of Function ========================*/
7492 /*------------------------------------------------------------------*/
7494 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7496 /* Function - If this CPU supports vector operations then it */
7497 /* supports the equivalent of SSE1-4. */
7499 /*------------------------------------------------------------------*/
7502 mono_arch_cpu_enumerate_simd_versions (void)
7504 guint32 sseOpts
= 0;
7506 if (mono_hwcap_s390x_has_vec
)
7507 sseOpts
= (SIMD_VERSION_SSE1
| SIMD_VERSION_SSE2
|
7508 SIMD_VERSION_SSE3
| SIMD_VERSION_SSSE3
|
7509 SIMD_VERSION_SSE41
| SIMD_VERSION_SSE42
|
7510 SIMD_VERSION_SSE4a
);
7515 /*========================= End of Function ========================*/
7517 /*------------------------------------------------------------------*/
7519 /* Name - mono_arch_opcode_supported. */
7521 /* Function - Check if a given op code is supported. */
7523 /*------------------------------------------------------------------*/
7526 mono_arch_opcode_supported (int opcode
)
7529 case OP_ATOMIC_ADD_I4
:
7530 case OP_ATOMIC_ADD_I8
:
7531 case OP_ATOMIC_EXCHANGE_I4
:
7532 case OP_ATOMIC_EXCHANGE_I8
:
7539 /*========================= End of Function ========================*/
7541 /*------------------------------------------------------------------*/
7543 /* Name - mono_arch_tailcall_supported. */
7545 /* Function - Check if a tailcall is supported. */
7547 /*------------------------------------------------------------------*/
7549 static const gboolean debug_tailcall
= FALSE
;
7552 is_supported_tailcall_helper (gboolean value
, const char *svalue
)
7554 if (!value
&& debug_tailcall
)
7555 g_print ("%s %s\n", __func__
, svalue
);
7559 #define IS_SUPPORTED_TAILCALL(x) (is_supported_tailcall_helper((x), #x))
7562 mono_arch_tailcall_supported (MonoCompile
*cfg
, MonoMethodSignature
*caller_sig
, MonoMethodSignature
*callee_sig
)
7564 g_assert (caller_sig
);
7565 g_assert (callee_sig
);
7567 CallInfo
*caller_info
= get_call_info (NULL
, caller_sig
);
7568 CallInfo
*callee_info
= get_call_info (NULL
, callee_sig
);
7570 gboolean res
= IS_SUPPORTED_TAILCALL (callee_info
->stack_usage
<= caller_info
->stack_usage
)
7571 && IS_SUPPORTED_TAILCALL (callee_info
->struct_ret
== caller_info
->struct_ret
)
7572 && IS_SUPPORTED_TAILCALL (memcmp (&callee_info
->ret
, &caller_info
->ret
, sizeof (caller_info
->ret
)) == 0);
7574 // valuetypes passed semantic-byvalue ABI-byref are often to a local.
7575 // FIXME ABIs vary as to if this local is in the parameter area or not,
7576 // so this check might not be needed.
7577 ArgInfo
const * const ainfo
= callee_info
->args
+ callee_sig
->hasthis
;
7578 for (int i
= 0; res
&& i
< callee_sig
->param_count
; ++i
) {
7579 res
= IS_SUPPORTED_TAILCALL (ainfo
[i
].regtype
!= RegTypeStructByAddr
)
7580 && IS_SUPPORTED_TAILCALL (ainfo
[i
].regtype
!= RegTypeStructByAddrOnStack
);
7583 g_free (caller_info
);
7584 g_free (callee_info
);
7589 /*========================= End of Function ========================*/