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"
342 #include "aot-runtime.h"
343 #include "mini-runtime.h"
345 /*========================= End of Includes ========================*/
347 /*------------------------------------------------------------------*/
348 /* T y p e d e f s */
349 /*------------------------------------------------------------------*/
361 typedef struct InstList InstList
;
375 RegTypeStructByValInFP
,
377 RegTypeStructByAddrOnStack
381 gint32 offset
; /* offset from caller's stack */
382 gint32 offparm
; /* offset from callee's stack */
383 guint16 vtsize
; /* in param area */
386 guint32 size
; /* Size of structure used by RegTypeStructByVal */
387 gint32 type
; /* Data type of argument */
399 MonoMethodSignature
*sig
;
404 gint64 gr
[5]; /* R2-R6 */
405 gdouble fp
[3]; /* F0-F2 */
406 } __attribute__ ((__packed__
)) RegParm
;
414 } __attribute__ ((__packed__
)) breakpoint_t
;
416 /*========================= End of Typedefs ========================*/
418 /*------------------------------------------------------------------*/
419 /* P r o t o t y p e s */
420 /*------------------------------------------------------------------*/
422 static void indent (int);
423 static guint8
* backUpStackPtr(MonoCompile
*, guint8
*);
424 static inline void add_general (guint
*, size_data
*, ArgInfo
*);
425 static inline void add_stackParm (guint
*, size_data
*, ArgInfo
*, gint
);
426 static inline void add_float (guint
*, size_data
*, ArgInfo
*, gboolean
);
427 static CallInfo
* get_call_info (MonoMemPool
*, MonoMethodSignature
*);
428 static guchar
* emit_float_to_int (MonoCompile
*, guchar
*, int, int, int, gboolean
);
429 static __inline__
void emit_unwind_regs(MonoCompile
*, guint8
*, int, int, long);
430 static void compare_and_branch(MonoBasicBlock
*, MonoInst
*, int, gboolean
);
432 /*========================= End of Prototypes ======================*/
434 /*------------------------------------------------------------------*/
435 /* G l o b a l V a r i a b l e s */
436 /*------------------------------------------------------------------*/
438 __thread
int indent_level
= 0;
439 __thread
FILE *trFd
= NULL
;
443 * The code generated for sequence points reads from this location,
444 * which is made read-only when single stepping is enabled.
446 static gpointer ss_trigger_page
;
449 * Enabled breakpoints read from this trigger page
451 static gpointer bp_trigger_page
;
453 breakpoint_t breakpointCode
;
455 static mono_mutex_t mini_arch_mutex
;
457 static const char * grNames
[] = {
458 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
459 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
460 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
464 static const char * fpNames
[] = {
465 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
466 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
467 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
471 static const char * vrNames
[] = {
472 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
473 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
474 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
475 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
478 /*====================== End of Global Variables ===================*/
480 /*------------------------------------------------------------------*/
482 /* Name - mono_arch_regname */
484 /* Function - Returns the name of the register specified by */
485 /* the input parameter. */
487 /*------------------------------------------------------------------*/
490 mono_arch_regname (int reg
)
492 if (reg
>= 0 && reg
< 16)
493 return grNames
[reg
];
498 /*========================= End of Function ========================*/
500 /*------------------------------------------------------------------*/
502 /* Name - mono_arch_fregname */
504 /* Function - Returns the name of the register specified by */
505 /* the input parameter. */
507 /*------------------------------------------------------------------*/
510 mono_arch_fregname (int reg
)
512 if (reg
>= 0 && reg
< 16)
513 return fpNames
[reg
];
518 /*========================= End of Function ========================*/
520 /*------------------------------------------------------------------*/
522 /* Name - mono_arch_xregname */
524 /* Function - Returns the name of the register specified by */
525 /* the input parameter. */
527 /*------------------------------------------------------------------*/
530 mono_arch_xregname (int reg
)
532 if (reg
< s390_VR_NREG
)
533 return vrNames
[reg
];
538 /*========================= End of Function ========================*/
540 /*------------------------------------------------------------------*/
542 /* Name - arch_get_argument_info */
544 /* Function - Gathers information on parameters such as size, */
545 /* alignment, and padding. arg_info should be large */
546 /* enough to hold param_count + 1 entries. */
548 /* Parameters - @csig - Method signature */
549 /* @param_count - No. of parameters to consider */
550 /* @arg_info - An array to store the result info */
552 /* Returns - Size of the activation frame */
554 /*------------------------------------------------------------------*/
557 mono_arch_get_argument_info (MonoMethodSignature
*csig
,
559 MonoJitArgumentInfo
*arg_info
)
561 int k
, frame_size
= 0;
562 int size
, align
, pad
;
565 if (MONO_TYPE_ISSTRUCT (csig
->ret
)) {
566 frame_size
+= sizeof (target_mgreg_t
);
570 arg_info
[0].offset
= offset
;
573 frame_size
+= sizeof (target_mgreg_t
);
577 arg_info
[0].size
= frame_size
;
579 for (k
= 0; k
< param_count
; k
++) {
582 size
= mono_type_native_stack_size (csig
->params
[k
], (guint32
*) &align
);
584 size
= mini_type_stack_size (csig
->params
[k
], &align
);
586 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
587 arg_info
[k
].pad
= pad
;
589 arg_info
[k
+ 1].pad
= 0;
590 arg_info
[k
+ 1].size
= size
;
592 arg_info
[k
+ 1].offset
= offset
;
596 align
= MONO_ARCH_FRAME_ALIGNMENT
;
597 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
598 arg_info
[k
].pad
= pad
;
603 /*========================= End of Function ========================*/
605 /*------------------------------------------------------------------*/
607 /* Name - emit_unwind_regs. */
609 /* Function - Emit unwind information for a range of registers. */
611 /*------------------------------------------------------------------*/
613 static void __inline__
614 emit_unwind_regs(MonoCompile
*cfg
, guint8
*code
, int start
, int end
, long offset
)
618 for (i
= start
; i
< end
; i
++) {
619 mono_emit_unwind_op_offset (cfg
, code
, i
, offset
);
620 mini_gc_set_slot_type_from_cfa (cfg
, offset
, SLOT_NOREF
);
621 offset
+= sizeof(gulong
);
625 /*========================= End of Function ========================*/
627 /*------------------------------------------------------------------*/
629 /* Name - retFitsInReg. */
631 /* Function - Determines if a value can be returned in one or */
634 /*------------------------------------------------------------------*/
636 static inline gboolean
637 retFitsInReg(guint32 size
)
652 /*========================= End of Function ========================*/
654 /*------------------------------------------------------------------*/
656 /* Name - backStackPtr. */
658 /* Function - Restore Stack Pointer to previous frame. */
660 /*------------------------------------------------------------------*/
662 static inline guint8
*
663 backUpStackPtr(MonoCompile
*cfg
, guint8
*code
)
665 int stackSize
= cfg
->stack_usage
;
667 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
668 s390_lg (code
, STK_BASE
, 0, STK_BASE
, 0);
670 if (cfg
->frame_reg
!= STK_BASE
)
671 s390_lgr (code
, STK_BASE
, cfg
->frame_reg
);
673 if (s390_is_imm16 (stackSize
)) {
674 s390_aghi (code
, STK_BASE
, stackSize
);
676 while (stackSize
> 32767) {
677 s390_aghi (code
, STK_BASE
, 32767);
680 s390_aghi (code
, STK_BASE
, stackSize
);
687 /*========================= End of Function ========================*/
689 /*------------------------------------------------------------------*/
693 /* Function - Perform nice indenting to current level */
695 /*------------------------------------------------------------------*/
701 indent_level
+= diff
;
703 fprintf (trFd
, "%p [%3d] ",(void *)pthread_self(),v
);
705 fprintf (trFd
, ". ");
708 indent_level
+= diff
;
711 /*========================= End of Function ========================*/
713 /*------------------------------------------------------------------*/
715 /* Name - cvtMonoType */
717 /* Function - Convert a mono-type to a string. */
719 /*------------------------------------------------------------------*/
722 cvtMonoType(MonoTypeEnum t
)
727 return "MONO_TYPE_END";
729 return "MONO_TYPE_VOID";
730 case MONO_TYPE_BOOLEAN
:
731 return "MONO_TYPE_BOOLEAN";
733 return "MONO_TYPE_CHAR";
735 return "MONO_TYPE_I1";
737 return "MONO_TYPE_U1";
739 return "MONO_TYPE_I2";
741 return "MONO_TYPE_U2";
743 return "MONO_TYPE_I4";
745 return "MONO_TYPE_U4";
747 return "MONO_TYPE_I8";
749 return "MONO_TYPE_U8";
751 return "MONO_TYPE_R4";
753 return "MONO_TYPE_R8";
754 case MONO_TYPE_STRING
:
755 return "MONO_TYPE_STRING";
757 return "MONO_TYPE_PTR";
758 case MONO_TYPE_BYREF
:
759 return "MONO_TYPE_BYREF";
760 case MONO_TYPE_VALUETYPE
:
761 return "MONO_TYPE_VALUETYPE";
762 case MONO_TYPE_CLASS
:
763 return "MONO_TYPE_CLASS";
765 return "MONO_TYPE_VAR";
766 case MONO_TYPE_ARRAY
:
767 return "MONO_TYPE_ARRAY";
768 case MONO_TYPE_GENERICINST
:
769 return "MONO_TYPE_GENERICINST";
770 case MONO_TYPE_TYPEDBYREF
:
771 return "MONO_TYPE_TYPEDBYREF";
773 return "MONO_TYPE_I";
775 return "MONO_TYPE_U";
776 case MONO_TYPE_FNPTR
:
777 return "MONO_TYPE_FNPTR";
778 case MONO_TYPE_OBJECT
:
779 return "MONO_TYPE_OBJECT";
780 case MONO_TYPE_SZARRAY
:
781 return "MONO_TYPE_SZARRAY";
783 return "MONO_TYPE_MVAR";
784 case MONO_TYPE_CMOD_REQD
:
785 return "MONO_TYPE_CMOD_REQD";
786 case MONO_TYPE_CMOD_OPT
:
787 return "MONO_TYPE_CMOD_OPT";
788 case MONO_TYPE_INTERNAL
:
789 return "MONO_TYPE_INTERNAL";
790 case MONO_TYPE_MODIFIER
:
791 return "MONO_TYPE_MODIFIER";
792 case MONO_TYPE_SENTINEL
:
793 return "MONO_TYPE_SENTINEL";
794 case MONO_TYPE_PINNED
:
795 return "MONO_TYPE_PINNED";
802 /*========================= End of Function ========================*/
804 /*------------------------------------------------------------------*/
806 /* Name - mono_arch_cpu_init */
808 /* Function - Perform CPU specific initialization to execute */
811 /*------------------------------------------------------------------*/
814 mono_arch_cpu_init (void)
818 /*========================= End of Function ========================*/
820 /*------------------------------------------------------------------*/
822 /* Name - mono_arch_init. */
824 /* Function - Initialize architecture specific code. */
826 /*------------------------------------------------------------------*/
829 mono_arch_init (void)
833 mono_set_partial_sharing_supported (FALSE
);
834 mono_os_mutex_init_recursive (&mini_arch_mutex
);
836 ss_trigger_page
= mono_valloc (NULL
, mono_pagesize (), MONO_MMAP_READ
, MONO_MEM_ACCOUNT_OTHER
);
837 bp_trigger_page
= mono_valloc (NULL
, mono_pagesize (), MONO_MMAP_READ
, MONO_MEM_ACCOUNT_OTHER
);
838 mono_mprotect (bp_trigger_page
, mono_pagesize (), 0);
840 code
= (guint8
*) &breakpointCode
;
841 s390_basr(code
, s390_r13
, 0);
844 s390_lg(code
, s390_r13
, 0, s390_r13
, 4);
845 s390_lg(code
, s390_r0
, 0, s390_r13
, 0);
848 /*========================= End of Function ========================*/
850 /*------------------------------------------------------------------*/
852 /* Name - mono_arch_cleanup. */
854 /* Function - Cleanup architecture specific code . */
856 /*------------------------------------------------------------------*/
859 mono_arch_cleanup (void)
862 mono_vfree (ss_trigger_page
, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER
);
864 mono_vfree (bp_trigger_page
, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER
);
865 mono_os_mutex_destroy (&mini_arch_mutex
);
868 /*========================= End of Function ========================*/
870 /*------------------------------------------------------------------*/
872 /* Name - mono_arch_have_fast_tls */
874 /* Function - Returns whether we use fast inlined thread local */
875 /* storage managed access, instead of falling back */
876 /* to native code. */
878 /*------------------------------------------------------------------*/
881 mono_arch_have_fast_tls (void)
886 /*========================= End of Function ========================*/
888 /*------------------------------------------------------------------*/
890 /* Name - mono_arch_cpu_optimizations */
892 /* Function - Returns the optimizations supported on this CPU */
894 /*------------------------------------------------------------------*/
897 mono_arch_cpu_optimizations (guint32
*exclude_mask
)
901 /*----------------------------------------------------------*/
902 /* No s390-specific optimizations yet */
903 /*----------------------------------------------------------*/
904 *exclude_mask
= MONO_OPT_LINEARS
;
908 /*========================= End of Function ========================*/
910 /*------------------------------------------------------------------*/
912 /* Name - mono_arch_get_allocatable_int_vars */
916 /*------------------------------------------------------------------*/
919 mono_arch_get_allocatable_int_vars (MonoCompile
*cfg
)
924 for (i
= 0; i
< cfg
->num_varinfo
; i
++) {
925 MonoInst
*ins
= cfg
->varinfo
[i
];
926 MonoMethodVar
*vmv
= MONO_VARINFO (cfg
, i
);
929 if (vmv
->range
.first_use
.abs_pos
>= vmv
->range
.last_use
.abs_pos
)
932 if (ins
->flags
& (MONO_INST_VOLATILE
|MONO_INST_INDIRECT
) ||
933 (ins
->opcode
!= OP_LOCAL
&& ins
->opcode
!= OP_ARG
))
936 /* we can only allocate 32 bit values */
937 if (mono_is_regsize_var(ins
->inst_vtype
)) {
938 g_assert (MONO_VARINFO (cfg
, i
)->reg
== -1);
939 g_assert (i
== vmv
->idx
);
940 vars
= mono_varlist_insert_sorted (cfg
, vars
, vmv
, FALSE
);
947 /*========================= End of Function ========================*/
949 /*------------------------------------------------------------------*/
951 /* Name - mono_arch_global_int_regs */
953 /* Function - Return a list of usable integer registers. */
955 /*------------------------------------------------------------------*/
958 mono_arch_get_global_int_regs (MonoCompile
*cfg
)
961 MonoMethodHeader
*header
;
964 header
= cfg
->header
;
965 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
966 cfg
->frame_reg
= s390_r11
;
969 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
971 for (i
= 8; i
< top
; ++i
) {
972 if ((cfg
->frame_reg
!= i
) &&
973 //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
974 (i
!= MONO_ARCH_IMT_REG
))
975 regs
= g_list_prepend (regs
, GUINT_TO_POINTER (i
));
981 /*========================= End of Function ========================*/
983 /*------------------------------------------------------------------*/
985 /* Name - mono_arch_flush_icache */
987 /* Function - Flush the CPU icache. */
989 /*------------------------------------------------------------------*/
992 mono_arch_flush_icache (guint8
*code
, gint size
)
996 /*========================= End of Function ========================*/
998 /*------------------------------------------------------------------*/
1000 /* Name - add_general */
1002 /* Function - Determine code and stack size incremements for a */
1005 /*------------------------------------------------------------------*/
1008 add_general (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
)
1010 if (*gr
> S390_LAST_ARG_REG
) {
1011 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1012 ainfo
->offset
= sz
->stack_size
;
1013 ainfo
->reg
= STK_BASE
;
1014 ainfo
->regtype
= RegTypeBase
;
1015 sz
->stack_size
+= sizeof(long);
1016 sz
->local_size
+= sizeof(long);
1017 sz
->offStruct
+= sizeof(long);
1018 sz
->code_size
+= 12;
1026 /*========================= End of Function ========================*/
1028 /*------------------------------------------------------------------*/
1030 /* Name - add_stackParm */
1032 /* Function - Determine code and stack size incremements for a */
1035 /*------------------------------------------------------------------*/
1038 add_stackParm (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
, gint size
)
1040 if (*gr
> S390_LAST_ARG_REG
) {
1041 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1042 ainfo
->reg
= STK_BASE
;
1043 ainfo
->offset
= sz
->stack_size
;
1044 ainfo
->regtype
= RegTypeStructByAddrOnStack
;
1045 sz
->stack_size
+= sizeof (target_mgreg_t
);
1046 sz
->parm_size
+= sizeof(gpointer
);
1047 sz
->offStruct
+= sizeof(gpointer
);
1050 ainfo
->offset
= sz
->stack_size
;
1051 ainfo
->regtype
= RegTypeStructByAddr
;
1054 ainfo
->offparm
= sz
->offset
;
1055 sz
->offset
= S390_ALIGN(sz
->offset
+size
, sizeof(long));
1057 ainfo
->vtsize
= size
;
1058 sz
->parm_size
+= size
;
1061 /*========================= End of Function ========================*/
1063 /*------------------------------------------------------------------*/
1065 /* Name - add_float */
1067 /* Function - Determine code and stack size incremements for a */
1068 /* float parameter. */
1070 /*------------------------------------------------------------------*/
1073 add_float (guint
*fr
, size_data
*sz
, ArgInfo
*ainfo
, gboolean isDouble
)
1075 if ((*fr
) <= S390_LAST_FPARG_REG
) {
1077 ainfo
->regtype
= RegTypeFP
;
1079 ainfo
->regtype
= RegTypeFPR4
;
1085 ainfo
->offset
= sz
->stack_size
;
1086 ainfo
->reg
= STK_BASE
;
1088 sz
->stack_size
+= sizeof(double);
1089 sz
->local_size
+= sizeof(double);
1090 sz
->offStruct
+= sizeof(double);
1091 ainfo
->regtype
= RegTypeBase
;
1095 /*========================= End of Function ========================*/
1097 /*------------------------------------------------------------------*/
1099 /* Name - get_call_info */
1101 /* Function - Determine the amount of space required for code */
1102 /* and stack. In addition determine starting points */
1103 /* for stack-based parameters, and area for struct- */
1104 /* ures being returned on the stack. */
1106 /*------------------------------------------------------------------*/
1109 get_call_info (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1111 guint i
, fr
, gr
, size
, pstart
;
1112 int nParm
= sig
->hasthis
+ sig
->param_count
;
1114 guint32 simpleType
, align
;
1115 gboolean is_pinvoke
= sig
->pinvoke
;
1120 cinfo
= mono_mempool_alloc0 (mp
, sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1122 cinfo
= g_malloc0 (sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1127 cinfo
->struct_ret
= 0;
1132 sz
->offStruct
= S390_MINIMAL_STACK_SIZE
;
1133 sz
->stack_size
= S390_MINIMAL_STACK_SIZE
;
1140 /*----------------------------------------------------------*/
1141 /* We determine the size of the return code/stack in case we*/
1142 /* need to reserve a register to be used to address a stack */
1143 /* area that the callee will use. */
1144 /*----------------------------------------------------------*/
1146 ret_type
= mini_get_underlying_type (sig
->ret
);
1147 simpleType
= ret_type
->type
;
1149 switch (simpleType
) {
1158 case MONO_TYPE_OBJECT
:
1160 case MONO_TYPE_FNPTR
:
1161 cinfo
->ret
.reg
= s390_r2
;
1166 cinfo
->ret
.reg
= s390_f0
;
1171 cinfo
->ret
.reg
= s390_r2
;
1174 case MONO_TYPE_GENERICINST
:
1175 if (!mono_type_generic_inst_is_valuetype (sig
->ret
)) {
1176 cinfo
->ret
.reg
= s390_r2
;
1181 case MONO_TYPE_VALUETYPE
: {
1182 MonoClass
*klass
= mono_class_from_mono_type_internal (sig
->ret
);
1183 if (m_class_is_enumtype (klass
)) {
1184 simpleType
= mono_class_enum_basetype_internal (klass
)->type
;
1187 size
= mini_type_stack_size_full (m_class_get_byval_arg (klass
), NULL
, sig
->pinvoke
);
1189 cinfo
->struct_ret
= 1;
1190 cinfo
->ret
.size
= size
;
1191 cinfo
->ret
.vtsize
= size
;
1194 case MONO_TYPE_TYPEDBYREF
:
1195 size
= MONO_ABI_SIZEOF (MonoTypedRef
);
1196 cinfo
->struct_ret
= 1;
1197 cinfo
->ret
.size
= size
;
1198 cinfo
->ret
.vtsize
= size
;
1200 case MONO_TYPE_VOID
:
1203 g_error ("Can't handle as return value 0x%x", sig
->ret
->type
);
1209 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1210 * the first argument, allowing 'this' to be always passed in the first arg reg.
1211 * Also do this if the first argument is a reference type, since virtual calls
1212 * are sometimes made using calli without sig->hasthis set, like in the delegate
1215 if (cinfo
->struct_ret
&& !is_pinvoke
&&
1217 (sig
->param_count
> 0 &&
1218 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig
->params
[0]))))) {
1220 cinfo
->args
[nParm
].size
= sizeof (target_mgreg_t
);
1221 add_general (&gr
, sz
, cinfo
->args
+ nParm
);
1223 cinfo
->args
[nParm
].size
= sizeof (target_mgreg_t
);
1224 add_general (&gr
, sz
, &cinfo
->args
[sig
->hasthis
+ nParm
]);
1228 cinfo
->vret_arg_index
= 1;
1229 cinfo
->ret
.reg
= gr
;
1234 cinfo
->args
[nParm
].size
= sizeof (target_mgreg_t
);
1235 add_general (&gr
, sz
, cinfo
->args
+ nParm
);
1239 if (cinfo
->struct_ret
) {
1240 cinfo
->ret
.reg
= gr
;
1245 if ((sig
->call_convention
== MONO_CALL_VARARG
) && (sig
->param_count
== 0)) {
1246 gr
= S390_LAST_ARG_REG
+ 1;
1247 fr
= S390_LAST_FPARG_REG
+ 1;
1249 /* Emit the signature cookie just before the implicit arguments */
1250 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1253 /*----------------------------------------------------------*/
1254 /* We determine the size of the parameter code and stack */
1255 /* requirements by checking the types and sizes of the */
1257 /*----------------------------------------------------------*/
1259 for (i
= pstart
; i
< sig
->param_count
; ++i
) {
1262 /*--------------------------------------------------*/
1263 /* Handle vararg type calls. All args are put on */
1265 /*--------------------------------------------------*/
1266 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1267 (i
== sig
->sentinelpos
)) {
1268 gr
= S390_LAST_ARG_REG
+ 1;
1269 fr
= S390_LAST_FPARG_REG
+ 1;
1270 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1273 if (sig
->params
[i
]->byref
) {
1274 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1275 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1280 ptype
= mini_get_underlying_type (sig
->params
[i
]);
1281 simpleType
= ptype
->type
;
1282 cinfo
->args
[nParm
].type
= simpleType
;
1283 switch (simpleType
) {
1286 cinfo
->args
[nParm
].size
= sizeof(char);
1287 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1292 cinfo
->args
[nParm
].size
= sizeof(short);
1293 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1298 cinfo
->args
[nParm
].size
= sizeof(int);
1299 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1305 case MONO_TYPE_FNPTR
:
1306 case MONO_TYPE_OBJECT
:
1307 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1308 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1313 cinfo
->args
[nParm
].size
= sizeof(long long);
1314 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1318 cinfo
->args
[nParm
].size
= sizeof(float);
1319 add_float (&fr
, sz
, cinfo
->args
+nParm
, FALSE
);
1323 cinfo
->args
[nParm
].size
= sizeof(double);
1324 add_float (&fr
, sz
, cinfo
->args
+nParm
, TRUE
);
1327 case MONO_TYPE_GENERICINST
:
1328 if (!mono_type_generic_inst_is_valuetype (ptype
)) {
1329 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1330 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1335 case MONO_TYPE_VALUETYPE
: {
1336 MonoMarshalType
*info
;
1337 MonoClass
*klass
= mono_class_from_mono_type_internal (ptype
);
1340 size
= mono_class_native_size(klass
, NULL
);
1342 size
= mono_class_value_size(klass
, NULL
);
1344 if (simpleType
!= MONO_TYPE_GENERICINST
) {
1345 info
= mono_marshal_load_type_info(klass
);
1347 if ((info
->native_size
== sizeof(float)) &&
1348 (info
->num_fields
== 1) &&
1349 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R4
)) {
1350 cinfo
->args
[nParm
].size
= sizeof(float);
1351 add_float(&fr
, sz
, cinfo
->args
+nParm
, FALSE
);
1356 if ((info
->native_size
== sizeof(double)) &&
1357 (info
->num_fields
== 1) &&
1358 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R8
)) {
1359 cinfo
->args
[nParm
].size
= sizeof(double);
1360 add_float(&fr
, sz
, cinfo
->args
+nParm
, TRUE
);
1366 cinfo
->args
[nParm
].vtsize
= 0;
1367 cinfo
->args
[nParm
].size
= 0;
1370 /*----------------------------------*/
1371 /* On S/390, structures of size 1, */
1372 /* 2, 4, and 8 bytes are passed in */
1373 /* (a) register(s). */
1374 /*----------------------------------*/
1380 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1381 cinfo
->args
[nParm
].size
= size
;
1382 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1384 sz
->local_size
+= sizeof(long);
1387 add_stackParm(&gr
, sz
, cinfo
->args
+nParm
, size
);
1392 case MONO_TYPE_TYPEDBYREF
: {
1393 int size
= MONO_ABI_SIZEOF (MonoTypedRef
);
1395 cinfo
->args
[nParm
].vtsize
= 0;
1396 cinfo
->args
[nParm
].size
= 0;
1399 /*----------------------------------*/
1400 /* On S/390, structures of size 1, */
1401 /* 2, 4, and 8 bytes are passed in */
1402 /* (a) register(s). */
1403 /*----------------------------------*/
1409 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1410 cinfo
->args
[nParm
].size
= size
;
1411 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1413 sz
->local_size
+= sizeof(long);
1416 add_stackParm(&gr
, sz
, cinfo
->args
+nParm
, size
);
1422 g_error ("Can't trampoline 0x%x", ptype
);
1426 /*----------------------------------------------------------*/
1427 /* Handle the case where there are no implicit arguments */
1428 /*----------------------------------------------------------*/
1429 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1432 (sig
->param_count
== sig
->sentinelpos
)) {
1433 gr
= S390_LAST_ARG_REG
+ 1;
1434 fr
= S390_LAST_FPARG_REG
+ 1;
1435 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1438 /*----------------------------------------------------------*/
1439 /* If we are passing a structure back then if it won't be */
1440 /* in a register(s) then we make room at the end of the */
1441 /* parameters that may have been placed on the stack */
1442 /*----------------------------------------------------------*/
1443 if (cinfo
->struct_ret
) {
1444 cinfo
->ret
.offset
= sz
->stack_size
;
1445 switch (cinfo
->ret
.size
) {
1453 sz
->stack_size
+= S390_ALIGN(cinfo
->ret
.size
, align
);
1458 sz
->stack_size
= sz
->stack_size
+ sz
->local_size
+ sz
->parm_size
+
1460 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1465 /*========================= End of Function ========================*/
1467 /*------------------------------------------------------------------*/
1469 /* Name - mono_arch_allocate_vars */
1471 /* Function - Set var information according to the calling */
1472 /* convention for S/390. The local var stuff should */
1473 /* most likely be split in another method. */
1475 /* Parameter - @m - Compile unit. */
1477 /*------------------------------------------------------------------*/
1480 mono_arch_allocate_vars (MonoCompile
*cfg
)
1482 MonoMethodSignature
*sig
;
1483 MonoMethodHeader
*header
;
1486 int iParm
, iVar
, offset
, align
, size
, curinst
;
1487 int frame_reg
= STK_BASE
;
1490 header
= cfg
->header
;
1492 cfg
->flags
|= MONO_CFG_HAS_SPILLUP
;
1494 /*---------------------------------------------------------*/
1495 /* We use the frame register also for any method that has */
1496 /* filter clauses. This way, when the handlers are called, */
1497 /* the code will reference local variables using the frame */
1498 /* reg instead of the stack pointer: if we had to restore */
1499 /* the stack pointer, we'd corrupt the method frames that */
1500 /* are already on the stack (since filters get called */
1501 /* before stack unwinding happens) when the filter code */
1502 /* would call any method. */
1503 /*---------------------------------------------------------*/
1504 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
1505 frame_reg
= s390_r11
;
1507 cfg
->frame_reg
= frame_reg
;
1509 cfg
->arch
.bkchain_reg
= -1;
1511 if (frame_reg
!= STK_BASE
)
1512 cfg
->used_int_regs
|= (1LL << frame_reg
);
1514 sig
= mono_method_signature_internal (cfg
->method
);
1516 cinfo
= get_call_info (cfg
->mempool
, sig
);
1518 if (!cinfo
->struct_ret
) {
1519 switch (mini_get_underlying_type (sig
->ret
)->type
) {
1520 case MONO_TYPE_VOID
:
1523 cfg
->ret
->opcode
= OP_REGVAR
;
1524 cfg
->ret
->dreg
= s390_r2
;
1529 /*--------------------------------------------------------------*/
1530 /* local vars are at a positive offset from the stack pointer */
1531 /* also note that if the function uses alloca, we use s390_r11 */
1532 /* to point at the local variables. */
1533 /* add parameter area size for called functions */
1534 /*--------------------------------------------------------------*/
1535 if (cfg
->param_area
== 0)
1536 offset
= S390_MINIMAL_STACK_SIZE
;
1538 offset
= cfg
->param_area
;
1540 cfg
->sig_cookie
= 0;
1542 if (cinfo
->struct_ret
) {
1543 inst
= cfg
->vret_addr
;
1544 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1545 inst
->inst_offset
= offset
;
1546 inst
->opcode
= OP_REGOFFSET
;
1547 inst
->inst_basereg
= frame_reg
;
1548 offset
+= sizeof(gpointer
);
1549 if (G_UNLIKELY (cfg
->verbose_level
> 1)) {
1550 printf ("vret_addr =");
1551 mono_print_ins (cfg
->vret_addr
);
1556 inst
= cfg
->args
[0];
1557 if (inst
->opcode
!= OP_REGVAR
) {
1558 inst
->opcode
= OP_REGOFFSET
;
1559 inst
->inst_basereg
= frame_reg
;
1560 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1561 inst
->inst_offset
= offset
;
1562 offset
+= sizeof (target_mgreg_t
);
1569 eArg
= sig
->param_count
+ sArg
;
1571 if (sig
->call_convention
== MONO_CALL_VARARG
)
1572 cfg
->sig_cookie
+= S390_MINIMAL_STACK_SIZE
;
1574 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
1575 inst
= cfg
->args
[curinst
];
1576 if (inst
->opcode
!= OP_REGVAR
) {
1577 switch (cinfo
->args
[iParm
].regtype
) {
1578 case RegTypeStructByAddr
: {
1581 size
= sizeof (target_mgreg_t
);
1583 inst
->opcode
= OP_REGOFFSET
;
1584 inst
->inst_basereg
= frame_reg
;
1585 offset
= S390_ALIGN (offset
, sizeof (target_mgreg_t
));
1586 inst
->inst_offset
= offset
;
1588 /* Add a level of indirection */
1589 MONO_INST_NEW (cfg
, indir
, 0);
1591 inst
->opcode
= OP_VTARG_ADDR
;
1592 inst
->inst_left
= indir
;
1595 case RegTypeStructByAddrOnStack
: {
1598 size
= sizeof (target_mgreg_t
);
1600 /* Similar to the == STK_BASE case below */
1601 cfg
->arch
.bkchain_reg
= s390_r12
;
1602 cfg
->used_int_regs
|= 1 << cfg
->arch
.bkchain_reg
;
1604 inst
->opcode
= OP_REGOFFSET
;
1605 inst
->dreg
= mono_alloc_preg (cfg
);
1606 inst
->inst_basereg
= cfg
->arch
.bkchain_reg
;
1607 inst
->inst_offset
= cinfo
->args
[iParm
].offset
;
1609 /* Add a level of indirection */
1610 MONO_INST_NEW (cfg
, indir
, 0);
1612 inst
->opcode
= OP_VTARG_ADDR
;
1613 inst
->inst_left
= indir
;
1616 case RegTypeStructByVal
:
1617 size
= cinfo
->args
[iParm
].size
;
1618 offset
= S390_ALIGN(offset
, size
);
1619 inst
->opcode
= OP_REGOFFSET
;
1620 inst
->inst_basereg
= frame_reg
;
1621 inst
->inst_offset
= offset
;
1624 if (cinfo
->args
[iParm
].reg
== STK_BASE
) {
1626 * These arguments are in the previous frame, so we can't
1627 * compute their offset from the current frame pointer right
1628 * now, since cfg->stack_offset is not yet known, so dedicate a
1629 * register holding the previous frame pointer.
1631 cfg
->arch
.bkchain_reg
= s390_r12
;
1632 cfg
->used_int_regs
|= 1 << cfg
->arch
.bkchain_reg
;
1634 inst
->opcode
= OP_REGOFFSET
;
1635 inst
->inst_basereg
= cfg
->arch
.bkchain_reg
;
1636 size
= (cinfo
->args
[iParm
].size
< 8
1637 ? 8 - cinfo
->args
[iParm
].size
1639 inst
->inst_offset
= cinfo
->args
[iParm
].offset
+ size
;
1640 size
= sizeof (long);
1642 inst
->opcode
= OP_REGOFFSET
;
1643 inst
->inst_basereg
= frame_reg
;
1644 size
= (cinfo
->args
[iParm
].size
< 8
1647 offset
= S390_ALIGN(offset
, size
);
1648 if (cfg
->method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
)
1649 inst
->inst_offset
= offset
;
1651 inst
->inst_offset
= offset
+ (8 - size
);
1655 offset
+= MAX(size
, 8);
1660 cfg
->locals_min_stack_offset
= offset
;
1662 curinst
= cfg
->locals_start
;
1663 for (iVar
= curinst
; iVar
< cfg
->num_varinfo
; ++iVar
) {
1664 inst
= cfg
->varinfo
[iVar
];
1665 if ((inst
->flags
& MONO_INST_IS_DEAD
) ||
1666 (inst
->opcode
== OP_REGVAR
))
1669 /*--------------------------------------------------*/
1670 /* inst->backend.is_pinvoke indicates native sized */
1671 /* value types this is used by the pinvoke wrappers */
1672 /* when they call functions returning structure */
1673 /*--------------------------------------------------*/
1674 if (inst
->backend
.is_pinvoke
&& MONO_TYPE_ISSTRUCT (inst
->inst_vtype
))
1675 size
= mono_class_native_size (mono_class_from_mono_type_internal (inst
->inst_vtype
),
1676 (guint32
*) &align
);
1678 size
= mono_type_size (inst
->inst_vtype
, &align
);
1680 offset
= S390_ALIGN(offset
, align
);
1681 inst
->inst_offset
= offset
;
1682 inst
->opcode
= OP_REGOFFSET
;
1683 inst
->inst_basereg
= frame_reg
;
1685 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
1686 iVar
, inst
->inst_offset
, size
));
1689 cfg
->locals_max_stack_offset
= offset
;
1691 /*------------------------------------------------------*/
1692 /* Reserve space to save LMF and caller saved registers */
1693 /*------------------------------------------------------*/
1694 if (cfg
->method
->save_lmf
)
1695 offset
+= sizeof (MonoLMF
);
1697 /*------------------------------------------------------*/
1698 /* align the offset */
1699 /*------------------------------------------------------*/
1700 cfg
->stack_offset
= S390_ALIGN(offset
, S390_STACK_ALIGNMENT
);
1702 /*------------------------------------------------------*/
1703 /* Fix offsets for args whose value is in parent frame */
1704 /*------------------------------------------------------*/
1705 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
1706 inst
= cfg
->args
[iParm
];
1708 if (inst
->opcode
== OP_S390_STKARG
) {
1709 inst
->opcode
= OP_REGOFFSET
;
1710 inst
->inst_offset
+= cfg
->stack_offset
;
1715 /*========================= End of Function ========================*/
1717 /*------------------------------------------------------------------*/
1719 /* Name - mono_arch_create_vars */
1721 /*------------------------------------------------------------------*/
1724 mono_arch_create_vars (MonoCompile
*cfg
)
1726 MonoMethodSignature
*sig
;
1729 sig
= mono_method_signature_internal (cfg
->method
);
1731 cinfo
= get_call_info (cfg
->mempool
, sig
);
1733 if (cinfo
->struct_ret
) {
1734 cfg
->vret_addr
= mono_compile_create_var (cfg
, mono_get_int_type (), OP_ARG
);
1735 if (G_UNLIKELY (cfg
->verbose_level
> 1)) {
1736 printf ("vret_addr = ");
1737 mono_print_ins (cfg
->vret_addr
);
1742 /*========================= End of Function ========================*/
1744 /*------------------------------------------------------------------*/
1746 /* Name - add_outarg_reg2. */
1748 /*------------------------------------------------------------------*/
1751 add_outarg_reg2 (MonoCompile
*cfg
, MonoCallInst
*call
, ArgStorage storage
, int reg
, MonoInst
*tree
)
1756 case RegTypeGeneral
:
1757 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
1758 ins
->dreg
= mono_alloc_ireg (cfg
);
1759 ins
->sreg1
= tree
->dreg
;
1760 MONO_ADD_INS (cfg
->cbb
, ins
);
1761 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, FALSE
);
1764 MONO_INST_NEW (cfg
, ins
, OP_FMOVE
);
1765 ins
->dreg
= mono_alloc_freg (cfg
);
1766 ins
->sreg1
= tree
->dreg
;
1767 MONO_ADD_INS (cfg
->cbb
, ins
);
1768 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, TRUE
);
1771 MONO_INST_NEW (cfg
, ins
, OP_S390_SETF4RET
);
1772 ins
->dreg
= mono_alloc_freg (cfg
);
1773 ins
->sreg1
= tree
->dreg
;
1774 MONO_ADD_INS (cfg
->cbb
, ins
);
1775 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, TRUE
);
1778 g_assert_not_reached ();
1782 /*========================= End of Function ========================*/
1784 /*------------------------------------------------------------------*/
1786 /* Name - emit_sig_cookie. */
1788 /*------------------------------------------------------------------*/
1791 emit_sig_cookie (MonoCompile
*cfg
, MonoCallInst
*call
, CallInfo
*cinfo
)
1793 MonoMethodSignature
*tmpSig
;
1796 cfg
->disable_aot
= TRUE
;
1798 /*----------------------------------------------------------*/
1799 /* mono_ArgIterator_Setup assumes the signature cookie is */
1800 /* passed first and all the arguments which were before it */
1801 /* passed on the stack after the signature. So compensate */
1802 /* by passing a different signature. */
1803 /*----------------------------------------------------------*/
1804 tmpSig
= mono_metadata_signature_dup (call
->signature
);
1805 tmpSig
->param_count
-= call
->signature
->sentinelpos
;
1806 tmpSig
->sentinelpos
= 0;
1807 if (tmpSig
->param_count
> 0)
1808 memcpy (tmpSig
->params
,
1809 call
->signature
->params
+ call
->signature
->sentinelpos
,
1810 tmpSig
->param_count
* sizeof(MonoType
*));
1812 MONO_INST_NEW (cfg
, sig_arg
, OP_ICONST
);
1813 sig_arg
->dreg
= mono_alloc_ireg (cfg
);
1814 sig_arg
->inst_p0
= tmpSig
;
1815 MONO_ADD_INS (cfg
->cbb
, sig_arg
);
1817 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORE_MEMBASE_REG
, STK_BASE
,
1818 cinfo
->sigCookie
.offset
, sig_arg
->dreg
);
1821 /*========================= End of Function ========================*/
1823 /*------------------------------------------------------------------*/
1825 /* Name - mono_arch_emit_call */
1827 /*------------------------------------------------------------------*/
1830 mono_arch_emit_call (MonoCompile
*cfg
, MonoCallInst
*call
)
1833 MonoMethodSignature
*sig
;
1835 int i
, n
, lParamArea
;
1837 ArgInfo
*ainfo
= NULL
;
1839 MonoMethodHeader
*header
;
1841 sig
= call
->signature
;
1842 n
= sig
->param_count
+ sig
->hasthis
;
1843 DEBUG (g_print ("Call requires: %d parameters\n",n
));
1845 cinfo
= get_call_info (cfg
->mempool
, sig
);
1847 stackSize
= cinfo
->sz
.stack_size
+ cinfo
->sz
.local_size
+
1848 cinfo
->sz
.parm_size
+ cinfo
->sz
.offset
;
1849 call
->stack_usage
= MAX(stackSize
, call
->stack_usage
);
1850 lParamArea
= MAX((call
->stack_usage
-S390_MINIMAL_STACK_SIZE
-cinfo
->sz
.parm_size
), 0);
1851 cfg
->param_area
= MAX(((signed) cfg
->param_area
), lParamArea
);
1852 cfg
->flags
|= MONO_CFG_HAS_CALLS
;
1854 if (cinfo
->struct_ret
) {
1855 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
1856 ins
->sreg1
= call
->vret_var
->dreg
;
1857 ins
->dreg
= mono_alloc_preg (cfg
);
1858 MONO_ADD_INS (cfg
->cbb
, ins
);
1859 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, cinfo
->ret
.reg
, FALSE
);
1862 header
= cfg
->header
;
1864 for (i
= 0; i
< n
; ++i
) {
1867 ainfo
= cinfo
->args
+ i
;
1868 if (i
>= sig
->hasthis
)
1869 t
= sig
->params
[i
- sig
->hasthis
];
1871 t
= mono_get_int_type ();
1872 t
= mini_get_underlying_type (t
);
1874 in
= call
->args
[i
];
1876 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1878 (i
== sig
->sentinelpos
)) {
1879 emit_sig_cookie (cfg
, call
, cinfo
);
1882 switch (ainfo
->regtype
) {
1883 case RegTypeGeneral
:
1884 add_outarg_reg2 (cfg
, call
, ainfo
->regtype
, ainfo
->reg
, in
);
1888 if (MONO_TYPE_ISSTRUCT (t
)) {
1889 /* Valuetype passed in one fp register */
1890 ainfo
->regtype
= RegTypeStructByValInFP
;
1893 add_outarg_reg2 (cfg
, call
, ainfo
->regtype
, ainfo
->reg
, in
);
1896 case RegTypeStructByVal
:
1897 case RegTypeStructByAddr
:
1898 case RegTypeStructByAddrOnStack
: {
1902 if (sig
->params
[i
- sig
->hasthis
]->type
== MONO_TYPE_TYPEDBYREF
) {
1903 size
= MONO_ABI_SIZEOF (MonoTypedRef
);
1904 align
= sizeof (target_mgreg_t
);
1908 size
= mono_type_native_stack_size (m_class_get_byval_arg (in
->klass
), &align
);
1911 * Other backends use mono_type_stack_size (), but that
1912 * aligns the size to 8, which is larger than the size of
1913 * the source, leading to reads of invalid memory if the
1914 * source is at the end of address space.
1916 size
= mono_class_value_size (in
->klass
, &align
);
1919 g_assert (in
->klass
);
1921 ainfo
->offparm
+= cinfo
->sz
.offStruct
;
1923 MONO_INST_NEW (cfg
, ins
, OP_OUTARG_VT
);
1924 ins
->sreg1
= in
->dreg
;
1925 ins
->klass
= in
->klass
;
1926 ins
->backend
.size
= ainfo
->size
;
1927 ins
->inst_p0
= call
;
1928 ins
->inst_p1
= mono_mempool_alloc (cfg
->mempool
, sizeof (ArgInfo
));
1929 memcpy (ins
->inst_p1
, ainfo
, sizeof (ArgInfo
));
1931 MONO_ADD_INS (cfg
->cbb
, ins
);
1936 if (!t
->byref
&& t
->type
== MONO_TYPE_R4
) {
1937 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORER4_MEMBASE_REG
,
1938 STK_BASE
, ainfo
->offset
+ 4,
1940 } else if (!t
->byref
&& (t
->type
== MONO_TYPE_R8
)) {
1941 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORER8_MEMBASE_REG
,
1942 STK_BASE
, ainfo
->offset
,
1945 MONO_INST_NEW (cfg
, ins
, OP_STORE_MEMBASE_REG
);
1946 ins
->inst_destbasereg
= STK_BASE
;
1947 ins
->inst_offset
= ainfo
->offset
;
1948 ins
->sreg1
= in
->dreg
;
1949 MONO_ADD_INS (cfg
->cbb
, ins
);
1953 g_assert_not_reached ();
1959 * Handle the case where there are no implicit arguments
1961 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1963 (i
== sig
->sentinelpos
)) {
1964 emit_sig_cookie (cfg
, call
, cinfo
);
1967 if (cinfo
->struct_ret
) {
1970 MONO_INST_NEW (cfg
, vtarg
, OP_MOVE
);
1971 vtarg
->sreg1
= call
->vret_var
->dreg
;
1972 vtarg
->dreg
= mono_alloc_preg (cfg
);
1973 MONO_ADD_INS (cfg
->cbb
, vtarg
);
1975 mono_call_inst_add_outarg_reg (cfg
, call
, vtarg
->dreg
, cinfo
->struct_ret
, FALSE
);
1979 /*========================= End of Function ========================*/
1981 /*------------------------------------------------------------------*/
1983 /* Name - mono_arch_emit_outarg_vt */
1985 /*------------------------------------------------------------------*/
1988 mono_arch_emit_outarg_vt (MonoCompile
*cfg
, MonoInst
*ins
, MonoInst
*src
)
1990 MonoCallInst
*call
= (MonoCallInst
*)ins
->inst_p0
;
1991 ArgInfo
*ainfo
= (ArgInfo
*)ins
->inst_p1
;
1992 int size
= ins
->backend
.size
;
1994 if (ainfo
->regtype
== RegTypeStructByVal
) {
1996 arg->ins.sreg1 = ainfo->reg;
1997 arg->ins.opcode = OP_OUTARG_VT;
1998 arg->size = ainfo->size;
1999 arg->offset = ainfo->offset;
2000 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2002 if (ainfo
->reg
!= STK_BASE
) {
2003 MONO_OUTPUT_VTR (cfg
, size
, ainfo
->reg
, src
->dreg
, 0);
2005 MONO_OUTPUT_VTS (cfg
, size
, ainfo
->reg
, ainfo
->offset
,
2008 } else if (ainfo
->regtype
== RegTypeStructByValInFP
) {
2009 int dreg
= mono_alloc_freg (cfg
);
2011 if (ainfo
->size
== 4) {
2012 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg
, OP_LOADR4_MEMBASE
, dreg
, src
->dreg
, 0);
2013 MONO_EMIT_NEW_UNALU (cfg
, OP_S390_SETF4RET
, dreg
, dreg
);
2015 g_assert (ainfo
->size
== 8);
2017 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg
, OP_LOADR8_MEMBASE
, dreg
, src
->dreg
, 0);
2020 mono_call_inst_add_outarg_reg (cfg
, call
, dreg
, ainfo
->reg
, TRUE
);
2023 MonoMethodHeader
*header
;
2024 MonoInst
*vtcopy
= mono_compile_create_var (cfg
, m_class_get_byval_arg (src
->klass
), OP_LOCAL
);
2026 int ovf_size
= ainfo
->vtsize
,
2030 /* FIXME: alignment? */
2031 if (call
->signature
->pinvoke
) {
2032 size
= mono_type_native_stack_size (m_class_get_byval_arg (src
->klass
), NULL
);
2033 vtcopy
->backend
.is_pinvoke
= 1;
2035 size
= mini_type_stack_size (m_class_get_byval_arg (src
->klass
), NULL
);
2038 g_assert (ovf_size
> 0);
2040 header
= mono_method_get_header_checked (cfg
->method
, error
);
2041 mono_error_assert_ok (error
); /* FIXME don't swallow the error */
2042 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
2047 EMIT_NEW_VARLOADA (cfg
, load
, vtcopy
, vtcopy
->inst_vtype
);
2048 mini_emit_memcpy (cfg
, load
->dreg
, 0, src
->dreg
, 0, size
, TARGET_SIZEOF_VOID_P
);
2050 if (ainfo
->reg
== STK_BASE
) {
2051 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORE_MEMBASE_REG
, srcReg
, ainfo
->offset
, load
->dreg
);
2053 if (cfg
->compute_gc_maps
) {
2056 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg
, def
, ainfo
->offset
, m_class_get_byval_arg (ins
->klass
));
2059 mono_call_inst_add_outarg_reg (cfg
, call
, load
->dreg
, ainfo
->reg
, FALSE
);
2063 /*========================= End of Function ========================*/
2065 /*------------------------------------------------------------------*/
2067 /* Name - mono_arch_emit_setret */
2069 /*------------------------------------------------------------------*/
2072 mono_arch_emit_setret (MonoCompile
*cfg
, MonoMethod
*method
, MonoInst
*val
)
2074 MonoType
*ret
= mini_get_underlying_type (mono_method_signature_internal (method
)->ret
);
2077 if (ret
->type
== MONO_TYPE_R4
) {
2078 MONO_EMIT_NEW_UNALU (cfg
, OP_S390_SETF4RET
, s390_f0
, val
->dreg
);
2080 } else if (ret
->type
== MONO_TYPE_R8
) {
2081 MONO_EMIT_NEW_UNALU (cfg
, OP_FMOVE
, s390_f0
, val
->dreg
);
2086 MONO_EMIT_NEW_UNALU (cfg
, OP_MOVE
, cfg
->ret
->dreg
, val
->dreg
);
2089 /*========================= End of Function ========================*/
2091 /*------------------------------------------------------------------*/
2093 /* Name - compare_and_branch */
2095 /* Function - Form a peephole pass at the code looking for */
2096 /* simple optimizations. */
2098 /*------------------------------------------------------------------*/
2101 compare_and_branch(MonoBasicBlock
*bb
, MonoInst
*ins
, int cc
, gboolean logical
)
2105 if (mono_hwcap_s390x_has_gie
) {
2106 last
= mono_inst_prev (ins
, FILTER_IL_SEQ_POINT
);
2107 ins
->sreg1
= last
->sreg1
;
2108 ins
->sreg2
= last
->sreg2
;
2110 switch(last
->opcode
) {
2113 ins
->opcode
= OP_S390_CLRJ
;
2115 ins
->opcode
= OP_S390_CRJ
;
2116 MONO_DELETE_INS(bb
, last
);
2121 ins
->opcode
= OP_S390_CLGRJ
;
2123 ins
->opcode
= OP_S390_CGRJ
;
2124 MONO_DELETE_INS(bb
, last
);
2126 case OP_ICOMPARE_IMM
:
2127 ins
->backend
.data
= (gpointer
) last
->inst_imm
;
2129 ins
->opcode
= OP_S390_CLIJ
;
2131 ins
->opcode
= OP_S390_CIJ
;
2132 MONO_DELETE_INS(bb
, last
);
2134 case OP_COMPARE_IMM
:
2135 case OP_LCOMPARE_IMM
:
2136 ins
->backend
.data
= (gpointer
) last
->inst_imm
;
2138 ins
->opcode
= OP_S390_CLGIJ
;
2140 ins
->opcode
= OP_S390_CGIJ
;
2141 MONO_DELETE_INS(bb
, last
);
2147 /*========================= End of Function ========================*/
2149 /*------------------------------------------------------------------*/
2151 /* Name - mono_arch_peephole_pass_1 */
2153 /* Function - Form a peephole pass at the code looking for */
2154 /* simple optimizations. */
2156 /*------------------------------------------------------------------*/
2159 mono_arch_peephole_pass_1 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2163 MONO_BB_FOR_EACH_INS_SAFE (bb
, n
, ins
) {
2164 switch (ins
->opcode
) {
2167 compare_and_branch(bb
, ins
, S390_CC_EQ
, FALSE
);
2171 compare_and_branch(bb
, ins
, S390_CC_NE
, TRUE
);
2175 compare_and_branch(bb
, ins
, S390_CC_LT
, FALSE
);
2179 compare_and_branch(bb
, ins
, S390_CC_LT
, TRUE
);
2183 compare_and_branch(bb
, ins
, S390_CC_GT
, FALSE
);
2187 compare_and_branch(bb
, ins
, S390_CC_GT
, TRUE
);
2191 compare_and_branch(bb
, ins
, S390_CC_GE
, FALSE
);
2195 compare_and_branch(bb
, ins
, S390_CC_GE
, TRUE
);
2199 compare_and_branch(bb
, ins
, S390_CC_LE
, FALSE
);
2203 compare_and_branch(bb
, ins
, S390_CC_LE
, TRUE
);
2207 // mono_peephole_ins (bb, ins);
2212 /*========================= End of Function ========================*/
2214 /*------------------------------------------------------------------*/
2216 /* Name - mono_arch_peephole_pass_2 */
2218 /* Function - Form a peephole pass at the code looking for */
2219 /* simple optimizations. */
2221 /*------------------------------------------------------------------*/
2224 mono_arch_peephole_pass_2 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2226 MonoInst
*ins
, *n
, *last_ins
= NULL
;
2228 MONO_BB_FOR_EACH_INS_SAFE (bb
, n
, ins
) {
2229 switch (ins
->opcode
) {
2230 case OP_LOADU4_MEMBASE
:
2231 case OP_LOADI4_MEMBASE
:
2232 if (last_ins
&& (last_ins
->opcode
== OP_STOREI4_MEMBASE_REG
) &&
2233 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
2234 ins
->inst_offset
== last_ins
->inst_offset
) {
2235 ins
->opcode
= (ins
->opcode
== OP_LOADI4_MEMBASE
) ? OP_ICONV_TO_I4
: OP_ICONV_TO_U4
;
2236 ins
->sreg1
= last_ins
->sreg1
;
2240 mono_peephole_ins (bb
, ins
);
2244 /*========================= End of Function ========================*/
2246 /*------------------------------------------------------------------*/
2248 /* Name - mono_arch_lowering_pass. */
2250 /*------------------------------------------------------------------*/
2253 mono_arch_lowering_pass (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2255 MonoInst
*ins
, *next
;
2257 MONO_BB_FOR_EACH_INS_SAFE (bb
, next
, ins
) {
2258 switch (ins
->opcode
) {
2263 case OP_IDIV_UN_IMM
:
2264 case OP_IREM_UN_IMM
:
2269 case OP_LOCALLOC_IMM
:
2270 mono_decompose_op_imm (cfg
, bb
, ins
);
2273 if (!s390_is_imm16 (ins
->inst_imm
))
2274 /* This is created by the memcpy code which ignores is_inst_imm */
2275 mono_decompose_op_imm (cfg
, bb
, ins
);
2282 bb
->max_vreg
= cfg
->next_vreg
;
2285 /*========================= End of Function ========================*/
2287 /*------------------------------------------------------------------*/
2289 /* Name - emit_float_to_int */
2291 /* Function - Create instructions which will convert a floating */
2292 /* point value to integer. */
2294 /*------------------------------------------------------------------*/
2297 emit_float_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
2299 /* sreg is a float, dreg is an integer reg. */
2301 s390_cgebr (code
, dreg
, 5, sreg
);
2304 s390_ltgr (code
, dreg
, dreg
);
2306 s390_oill (code
, dreg
, 0x80);
2307 s390_lghi (code
, s390_r0
, 0xff);
2308 s390_ngr (code
, dreg
, s390_r0
);
2311 s390_ltgr (code
, dreg
, dreg
);
2313 s390_oill (code
, dreg
, 0x8000);
2314 s390_llill(code
, s390_r0
, 0xffff);
2315 s390_ngr (code
, dreg
, s390_r0
);
2320 S390_SET (code
, s390_r13
, 0x4f000000u
);
2321 s390_ldgr (code
, s390_f14
, s390_r13
);
2322 s390_ler (code
, s390_f15
, sreg
);
2323 s390_cebr (code
, s390_f15
, s390_f14
);
2324 s390_jl (code
, 0); CODEPTR (code
, o
[0]);
2325 S390_SET (code
, s390_r13
, 0x4f800000u
);
2326 s390_ldgr (code
, s390_f14
, s390_r13
);
2327 s390_sebr (code
, s390_f15
, s390_f14
);
2328 s390_cfebr (code
, dreg
, 7, s390_f15
);
2330 PTRSLOT (code
, o
[0]);
2331 s390_cfebr (code
, dreg
, 5, sreg
);
2334 s390_lghi (code
, s390_r0
, 0xff);
2335 s390_ngr (code
, dreg
, s390_r0
);
2338 s390_llill(code
, s390_r0
, 0xffff);
2339 s390_ngr (code
, dreg
, s390_r0
);
2346 /*========================= End of Function ========================*/
2348 /*------------------------------------------------------------------*/
2350 /* Name - emit_double_to_int */
2352 /* Function - Create instructions which will convert a floating */
2353 /* point value to integer. */
2355 /*------------------------------------------------------------------*/
2358 emit_double_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
2360 /* sreg is a float, dreg is an integer reg. */
2362 s390_cgdbr (code
, dreg
, 5, sreg
);
2365 s390_ltgr (code
, dreg
, dreg
);
2367 s390_oill (code
, dreg
, 0x80);
2368 s390_lghi (code
, s390_r0
, 0xff);
2369 s390_ngr (code
, dreg
, s390_r0
);
2372 s390_ltgr (code
, dreg
, dreg
);
2374 s390_oill (code
, dreg
, 0x8000);
2375 s390_llill(code
, s390_r0
, 0xffff);
2376 s390_ngr (code
, dreg
, s390_r0
);
2381 S390_SET (code
, s390_r13
, 0x41e0000000000000llu
);
2382 s390_ldgr (code
, s390_f14
, s390_r13
);
2383 s390_ldr (code
, s390_f15
, sreg
);
2384 s390_cdbr (code
, s390_f15
, s390_f14
);
2385 s390_jl (code
, 0); CODEPTR (code
, o
[0]);
2386 S390_SET (code
, s390_r13
, 0x41f0000000000000llu
);
2387 s390_ldgr (code
, s390_f14
, s390_r13
);
2388 s390_sdbr (code
, s390_f15
, s390_f14
);
2389 s390_cfdbr (code
, dreg
, 7, s390_f15
);
2391 PTRSLOT (code
, o
[0]);
2392 s390_cfdbr (code
, dreg
, 5, sreg
);
2395 s390_lghi (code
, s390_r0
, 0xff);
2396 s390_ngr (code
, dreg
, s390_r0
);
2399 s390_llill(code
, s390_r0
, 0xffff);
2400 s390_ngr (code
, dreg
, s390_r0
);
2407 /*========================= End of Function ========================*/
2409 /*------------------------------------------------------------------*/
2411 /* Name - is_unsigned. */
2413 /* Function - Return TRUE if next opcode is checking for un- */
2416 /*------------------------------------------------------------------*/
2419 is_unsigned (MonoInst
*next
)
2422 (((next
->opcode
>= OP_IBNE_UN
) &&
2423 (next
->opcode
<= OP_IBLT_UN
)) ||
2424 ((next
->opcode
>= OP_LBNE_UN
) &&
2425 (next
->opcode
<= OP_LBLT_UN
)) ||
2426 ((next
->opcode
>= OP_COND_EXC_NE_UN
) &&
2427 (next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
2428 ((next
->opcode
>= OP_COND_EXC_INE_UN
) &&
2429 (next
->opcode
<= OP_COND_EXC_ILT_UN
)) ||
2430 ((next
->opcode
== OP_CLT_UN
) ||
2431 (next
->opcode
== OP_CGT_UN
) ||
2432 (next
->opcode
== OP_ICGE_UN
) ||
2433 (next
->opcode
== OP_ICLE_UN
)) ||
2434 ((next
->opcode
== OP_ICLT_UN
) ||
2435 (next
->opcode
== OP_ICGT_UN
) ||
2436 (next
->opcode
== OP_LCLT_UN
) ||
2437 (next
->opcode
== OP_LCGT_UN
))))
2443 /*========================= End of Function ========================*/
2445 /*------------------------------------------------------------------*/
2447 /* Name - mono_arch_output_basic_block */
2449 /* Function - Perform the "real" work of emitting instructions */
2450 /* that will do the work of in the basic block. */
2452 /*------------------------------------------------------------------*/
2455 mono_arch_output_basic_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2459 guint8
*code
= cfg
->native_code
+ cfg
->code_len
;
2462 /* we don't align basic blocks of loops on s390 */
2464 if (cfg
->verbose_level
> 2)
2465 g_print ("Basic block %d starting at offset 0x%x\n", bb
->block_num
, bb
->native_offset
);
2467 MONO_BB_FOR_EACH_INS (bb
, ins
) {
2468 const guint offset
= code
- cfg
->native_code
;
2469 set_code_cursor (cfg
, code
);
2470 int max_len
= ins_get_size (ins
->opcode
);
2471 code
= realloc_code (cfg
, max_len
);
2473 mono_debug_record_line_number (cfg
, ins
, offset
);
2475 switch (ins
->opcode
) {
2476 case OP_STOREI1_MEMBASE_IMM
: {
2477 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2478 S390_LONG (code
, stcy
, stc
, s390_r0
, 0,
2479 ins
->inst_destbasereg
, ins
->inst_offset
);
2482 case OP_STOREI2_MEMBASE_IMM
: {
2483 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2484 S390_LONG (code
, sthy
, sth
, s390_r0
, 0,
2485 ins
->inst_destbasereg
, ins
->inst_offset
);
2488 case OP_STOREI4_MEMBASE_IMM
: {
2489 s390_lgfi (code
, s390_r0
, ins
->inst_imm
);
2490 S390_LONG (code
, sty
, st
, s390_r0
, 0,
2491 ins
->inst_destbasereg
, ins
->inst_offset
);
2494 case OP_STORE_MEMBASE_IMM
:
2495 case OP_STOREI8_MEMBASE_IMM
: {
2496 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2497 S390_LONG (code
, stg
, stg
, s390_r0
, 0,
2498 ins
->inst_destbasereg
, ins
->inst_offset
);
2501 case OP_STOREI1_MEMBASE_REG
: {
2502 S390_LONG (code
, stcy
, stc
, ins
->sreg1
, 0,
2503 ins
->inst_destbasereg
, ins
->inst_offset
);
2506 case OP_STOREI2_MEMBASE_REG
: {
2507 S390_LONG (code
, sthy
, sth
, ins
->sreg1
, 0,
2508 ins
->inst_destbasereg
, ins
->inst_offset
);
2511 case OP_STOREI4_MEMBASE_REG
: {
2512 S390_LONG (code
, sty
, st
, ins
->sreg1
, 0,
2513 ins
->inst_destbasereg
, ins
->inst_offset
);
2516 case OP_STORE_MEMBASE_REG
:
2517 case OP_STOREI8_MEMBASE_REG
: {
2518 S390_LONG (code
, stg
, stg
, ins
->sreg1
, 0,
2519 ins
->inst_destbasereg
, ins
->inst_offset
);
2523 g_assert_not_reached ();
2525 case OP_LOAD_MEMBASE
:
2526 case OP_LOADI8_MEMBASE
: {
2527 S390_LONG (code
, lg
, lg
, ins
->dreg
, 0,
2528 ins
->inst_basereg
, ins
->inst_offset
);
2531 case OP_LOADI4_MEMBASE
: {
2532 S390_LONG (code
, lgf
, lgf
, ins
->dreg
, 0,
2533 ins
->inst_basereg
, ins
->inst_offset
);
2536 case OP_LOADU4_MEMBASE
: {
2537 S390_LONG (code
, llgf
, llgf
, ins
->dreg
, 0,
2538 ins
->inst_basereg
, ins
->inst_offset
);
2541 case OP_LOADU1_MEMBASE
: {
2542 S390_LONG (code
, llgc
, llgc
, ins
->dreg
, 0,
2543 ins
->inst_basereg
, ins
->inst_offset
);
2546 case OP_LOADI1_MEMBASE
: {
2547 S390_LONG (code
, lgb
, lgb
, ins
->dreg
, 0,
2548 ins
->inst_basereg
, ins
->inst_offset
);
2551 case OP_LOADU2_MEMBASE
: {
2552 S390_LONG (code
, llgh
, llgh
, ins
->dreg
, 0,
2553 ins
->inst_basereg
, ins
->inst_offset
);
2556 case OP_LOADI2_MEMBASE
: {
2557 S390_LONG (code
, lgh
, lgh
, ins
->dreg
, 0,
2558 ins
->inst_basereg
, ins
->inst_offset
);
2561 case OP_LCONV_TO_I1
: {
2562 s390_lgbr (code
, ins
->dreg
, ins
->sreg1
);
2565 case OP_LCONV_TO_I2
: {
2566 s390_lghr (code
, ins
->dreg
, ins
->sreg1
);
2569 case OP_LCONV_TO_U1
: {
2570 s390_llgcr (code
, ins
->dreg
, ins
->sreg1
);
2573 case OP_LCONV_TO_U2
: {
2574 s390_llghr (code
, ins
->dreg
, ins
->sreg1
);
2577 case OP_ICONV_TO_I1
: {
2578 s390_lgbr (code
, ins
->dreg
, ins
->sreg1
);
2581 case OP_ICONV_TO_I2
: {
2582 s390_lghr (code
, ins
->dreg
, ins
->sreg1
);
2585 case OP_ICONV_TO_U1
: {
2586 s390_llgcr (code
, ins
->dreg
, ins
->sreg1
);
2589 case OP_ICONV_TO_U2
: {
2590 s390_llghr (code
, ins
->dreg
, ins
->sreg1
);
2593 case OP_ICONV_TO_U4
: {
2594 s390_llgfr (code
, ins
->dreg
, ins
->sreg1
);
2597 case OP_ICONV_TO_I4
: {
2598 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
2603 if (is_unsigned (ins
->next
))
2604 s390_clgr (code
, ins
->sreg1
, ins
->sreg2
);
2606 s390_cgr (code
, ins
->sreg1
, ins
->sreg2
);
2610 if (is_unsigned (ins
->next
))
2611 s390_clr (code
, ins
->sreg1
, ins
->sreg2
);
2613 s390_cr (code
, ins
->sreg1
, ins
->sreg2
);
2616 case OP_COMPARE_IMM
:
2617 case OP_LCOMPARE_IMM
: {
2618 gboolean branchUn
= is_unsigned (ins
->next
);
2619 if ((ins
->inst_imm
== 0) && (!branchUn
)) {
2620 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
2622 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2624 s390_clgr (code
, ins
->sreg1
, s390_r0
);
2626 s390_cgr (code
, ins
->sreg1
, s390_r0
);
2630 case OP_ICOMPARE_IMM
: {
2631 gboolean branchUn
= is_unsigned (ins
->next
);
2632 if ((ins
->inst_imm
== 0) && (!branchUn
)) {
2633 s390_ltr (code
, ins
->sreg1
, ins
->sreg1
);
2635 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2637 s390_clr (code
, ins
->sreg1
, s390_r0
);
2639 s390_cr (code
, ins
->sreg1
, s390_r0
);
2644 mono_add_patch_info (cfg
, code
- cfg
->native_code
, MONO_PATCH_INFO_ABS
,
2646 S390_CALL_TEMPLATE (code
, s390_r14
);
2650 if (mono_hwcap_s390x_has_mlt
) {
2651 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2654 s390_agr (code
, ins
->dreg
, src2
);
2659 if (mono_hwcap_s390x_has_mlt
) {
2660 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2663 s390_agr (code
, ins
->dreg
, src2
);
2669 s390_alcgr (code
, ins
->dreg
, src2
);
2673 if (mono_hwcap_s390x_has_mlt
) {
2674 if (s390_is_imm16 (ins
->inst_imm
)) {
2675 s390_aghik(code
, ins
->dreg
, ins
->sreg1
, ins
->inst_imm
);
2677 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2678 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2681 if (ins
->dreg
!= ins
->sreg1
) {
2682 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2684 if (s390_is_imm16 (ins
->inst_imm
)) {
2685 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
2686 } else if (s390_is_imm32 (ins
->inst_imm
)) {
2687 s390_agfi (code
, ins
->dreg
, ins
->inst_imm
);
2689 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2690 s390_agr (code
, ins
->dreg
, s390_r0
);
2696 if (ins
->dreg
!= ins
->sreg1
) {
2697 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2699 if (s390_is_imm32 (ins
->inst_imm
)) {
2700 s390_agfi (code
, ins
->dreg
, ins
->inst_imm
);
2702 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2703 s390_agr (code
, ins
->dreg
, s390_r0
);
2708 if (ins
->dreg
!= ins
->sreg1
) {
2709 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2711 if (s390_is_imm16 (ins
->inst_imm
)) {
2712 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2713 s390_alcgr (code
, ins
->dreg
, s390_r0
);
2715 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2716 s390_alcgr (code
, ins
->dreg
, s390_r0
);
2721 case OP_S390_IADD_OVF
: {
2723 s390_ar (code
, ins
->dreg
, src2
);
2724 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2725 s390_lgfr (code
, ins
->dreg
, ins
->dreg
);
2728 case OP_IADD_OVF_UN
:
2729 case OP_S390_IADD_OVF_UN
: {
2731 s390_algr (code
, ins
->dreg
, src2
);
2732 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
2733 s390_llgfr (code
, ins
->dreg
, ins
->dreg
);
2736 case OP_ADD_OVF_CARRY
: {
2738 s390_lghi (code
, s390_r0
, 0);
2739 s390_lgr (code
, s390_r1
, s390_r0
);
2740 s390_alcgr (code
, s390_r0
, s390_r1
);
2741 s390_agr (code
, ins
->dreg
, src2
);
2742 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2743 s390_agr (code
, ins
->dreg
, s390_r0
);
2744 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2747 case OP_ADD_OVF_UN_CARRY
: {
2749 s390_alcgr (code
, ins
->dreg
, src2
);
2750 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
2754 if (mono_hwcap_s390x_has_mlt
) {
2755 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2758 s390_sgr (code
, ins
->dreg
, src2
);
2763 if (mono_hwcap_s390x_has_mlt
) {
2764 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2767 s390_sgr (code
, ins
->dreg
, src2
);
2773 s390_slbgr(code
, ins
->dreg
, src2
);
2777 if (ins
->dreg
!= ins
->sreg1
) {
2778 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2780 if (s390_is_imm16 (-ins
->inst_imm
)) {
2781 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
2782 } else if (s390_is_imm32 (-ins
->inst_imm
)) {
2783 s390_slgfi (code
, ins
->dreg
, ins
->inst_imm
);
2785 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2786 s390_slgr (code
, ins
->dreg
, s390_r0
);
2791 if (ins
->dreg
!= ins
->sreg1
) {
2792 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2794 if (s390_is_imm16 (-ins
->inst_imm
)) {
2795 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
2796 } else if (s390_is_imm32 (-ins
->inst_imm
)) {
2797 s390_slgfi (code
, ins
->dreg
, ins
->inst_imm
);
2799 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2800 s390_slgr (code
, ins
->dreg
, s390_r0
);
2805 if (ins
->dreg
!= ins
->sreg1
) {
2806 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2808 if (s390_is_imm16 (-ins
->inst_imm
)) {
2809 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2810 s390_slbgr (code
, ins
->dreg
, s390_r0
);
2812 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2813 s390_slbgr(code
, ins
->dreg
, s390_r0
);
2817 case OP_SUB_OVF_CARRY
: {
2819 s390_lghi (code
, s390_r0
, 0);
2820 s390_lgr (code
, s390_r1
, s390_r0
);
2821 s390_slbgr (code
, s390_r0
, s390_r1
);
2822 s390_sgr (code
, ins
->dreg
, src2
);
2823 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2824 s390_agr (code
, ins
->dreg
, s390_r0
);
2825 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2828 case OP_SUB_OVF_UN_CARRY
: {
2830 s390_slbgr (code
, ins
->dreg
, src2
);
2831 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
2835 if (mono_hwcap_s390x_has_mlt
) {
2836 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2838 if (ins
->sreg1
== ins
->dreg
) {
2839 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
2841 if (ins
->sreg2
== ins
->dreg
) {
2842 s390_ngr (code
, ins
->dreg
, ins
->sreg1
);
2844 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2845 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
2852 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
2853 if (mono_hwcap_s390x_has_mlt
) {
2854 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2856 if (ins
->dreg
!= ins
->sreg1
) {
2857 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2859 s390_ngr (code
, ins
->dreg
, s390_r0
);
2864 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2865 s390_dsgr (code
, s390_r0
, ins
->sreg2
);
2866 s390_lgr (code
, ins
->dreg
, s390_r1
);
2870 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2871 s390_lghi (code
, s390_r0
, 0);
2872 s390_dlgr (code
, s390_r0
, ins
->sreg2
);
2873 s390_lgr (code
, ins
->dreg
, s390_r1
);
2877 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2878 s390_dsgr (code
, s390_r0
, ins
->sreg2
);
2879 s390_lgr (code
, ins
->dreg
, s390_r0
);
2883 if (s390_is_imm16 (ins
->inst_imm
)) {
2884 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
2886 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
2888 s390_lgr (code
, s390_r0
, ins
->sreg1
);
2889 s390_dsgr (code
, s390_r0
, s390_r13
);
2890 s390_lgfr (code
, ins
->dreg
, s390_r0
);
2894 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2895 s390_lghi (code
, s390_r0
, 0);
2896 s390_dlgr (code
, s390_r0
, ins
->sreg2
);
2897 s390_lgr (code
, ins
->dreg
, s390_r0
);
2901 if (mono_hwcap_s390x_has_mlt
) {
2902 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2904 if (ins
->sreg1
== ins
->dreg
) {
2905 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
2907 if (ins
->sreg2
== ins
->dreg
) {
2908 s390_ogr (code
, ins
->dreg
, ins
->sreg1
);
2910 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2911 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
2918 S390_SET_MASK(code
, s390_r0
, ins
->inst_imm
);
2919 if (mono_hwcap_s390x_has_mlt
) {
2920 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2922 if (ins
->dreg
!= ins
->sreg1
) {
2923 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2925 s390_ogr (code
, ins
->dreg
, s390_r0
);
2930 if (mono_hwcap_s390x_has_mlt
) {
2931 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2933 if (ins
->sreg1
== ins
->dreg
) {
2934 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
2937 if (ins
->sreg2
== ins
->dreg
) {
2938 s390_xgr (code
, ins
->dreg
, ins
->sreg1
);
2941 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2942 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
2949 S390_SET_MASK(code
, s390_r0
, ins
->inst_imm
);
2950 if (mono_hwcap_s390x_has_mlt
) {
2951 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2953 if (ins
->dreg
!= ins
->sreg1
) {
2954 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2956 s390_xgr (code
, ins
->dreg
, s390_r0
);
2962 s390_sllg (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
2967 if (ins
->sreg1
!= ins
->dreg
) {
2968 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2970 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
2975 s390_srag (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
2980 if (ins
->sreg1
!= ins
->dreg
) {
2981 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2983 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
2987 case OP_LSHR_UN_IMM
: {
2988 if (ins
->sreg1
!= ins
->dreg
) {
2989 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2991 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
2996 s390_srlg (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
3000 if (ins
->sreg1
!= ins
->dreg
) {
3001 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3003 s390_lghi (code
, s390_r0
, -1);
3004 s390_xgr (code
, ins
->dreg
, s390_r0
);
3008 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
3013 s390_msgr (code
, ins
->dreg
, src2
);
3018 if (ins
->dreg
!= ins
->sreg1
) {
3019 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3021 if ((mono_hwcap_s390x_has_gie
) &&
3022 (s390_is_imm32 (ins
->inst_imm
))) {
3023 s390_msgfi (code
, ins
->dreg
, ins
->inst_imm
);
3025 if (s390_is_imm16 (ins
->inst_imm
)) {
3026 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3027 } else if (s390_is_imm32 (ins
->inst_imm
)) {
3028 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3030 S390_SET (code
, s390_r13
, ins
->inst_imm
);
3032 s390_msgr (code
, ins
->dreg
, s390_r13
);
3038 if (mono_hwcap_s390x_has_mie2
) {
3039 s390_msgrkc (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3040 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3042 s390_ltgr (code
, s390_r1
, ins
->sreg1
);
3043 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3044 s390_ltgr (code
, s390_r0
, ins
->sreg2
);
3046 s390_lghi (code
, s390_r1
, 0);
3047 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3048 s390_xgr (code
, s390_r0
, s390_r1
);
3049 s390_msgr (code
, s390_r1
, ins
->sreg2
);
3050 s390_xgr (code
, s390_r0
, s390_r1
);
3051 s390_srlg (code
, s390_r0
, s390_r0
, 0, 63);
3052 s390_ltgr (code
, s390_r0
, s390_r0
);
3053 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3054 PTRSLOT (code
, o
[0]);
3055 PTRSLOT (code
, o
[1]);
3056 s390_lgr (code
, ins
->dreg
, s390_r1
);
3060 case OP_LMUL_OVF_UN
: {
3061 s390_lghi (code
, s390_r0
, 0);
3062 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3063 s390_mlgr (code
, s390_r0
, ins
->sreg2
);
3064 s390_ltgr (code
, s390_r0
, s390_r0
);
3065 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3066 s390_lgr (code
, ins
->dreg
, s390_r1
);
3070 g_assert_not_reached ();
3072 s390_algr (code
, ins
->dreg
, src2
);
3077 s390_agr (code
, ins
->dreg
, src2
);
3081 g_assert_not_reached ();
3083 s390_alcgr (code
, ins
->dreg
, src2
);
3087 if (ins
->dreg
!= ins
->sreg1
) {
3088 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3090 if (s390_is_imm16 (ins
->inst_imm
)) {
3091 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
3093 s390_afi (code
, ins
->dreg
, ins
->inst_imm
);
3098 if (ins
->dreg
!= ins
->sreg1
) {
3099 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3101 if (s390_is_imm16 (ins
->inst_imm
)) {
3102 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3103 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3105 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3106 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3111 case OP_S390_LADD_OVF
: {
3112 if (mono_hwcap_s390x_has_mlt
) {
3113 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3116 s390_agr (code
, ins
->dreg
, src2
);
3118 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3121 case OP_LADD_OVF_UN
:
3122 case OP_S390_LADD_OVF_UN
: {
3123 if (mono_hwcap_s390x_has_mlt
) {
3124 s390_algrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3127 s390_algr (code
, ins
->dreg
, src2
);
3129 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3133 if (mono_hwcap_s390x_has_mlt
) {
3134 s390_slgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3136 CHECK_SRCDST_NCOM_I
;
3137 s390_slgr (code
, ins
->dreg
, src2
);
3142 if (mono_hwcap_s390x_has_mlt
) {
3143 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3145 CHECK_SRCDST_NCOM_I
;
3146 s390_sgr (code
, ins
->dreg
, src2
);
3151 CHECK_SRCDST_NCOM_I
;
3152 s390_slbgr (code
, ins
->dreg
, src2
);
3156 if (ins
->dreg
!= ins
->sreg1
) {
3157 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3159 if (s390_is_imm16 (-ins
->inst_imm
)) {
3160 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
3162 s390_agfi (code
, ins
->dreg
, -ins
->inst_imm
);
3167 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3168 s390_slgfr (code
, ins
->dreg
, s390_r0
);
3172 case OP_S390_ISUB_OVF
: {
3173 if (mono_hwcap_s390x_has_mlt
) {
3174 s390_srk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3175 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3178 s390_sr (code
, ins
->dreg
, src2
);
3179 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3180 s390_lgfr (code
, ins
->dreg
, ins
->dreg
);
3184 case OP_ISUB_OVF_UN
:
3185 case OP_S390_ISUB_OVF_UN
: {
3186 if (mono_hwcap_s390x_has_mlt
) {
3187 s390_slrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3190 s390_slr (code
, ins
->dreg
, src2
);
3192 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3193 s390_llgfr(code
, ins
->dreg
, ins
->dreg
);
3197 case OP_S390_LSUB_OVF
: {
3198 if (mono_hwcap_s390x_has_mlt
) {
3199 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3202 s390_sgr (code
, ins
->dreg
, src2
);
3204 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3207 case OP_LSUB_OVF_UN
:
3208 case OP_S390_LSUB_OVF_UN
: {
3210 s390_slgr (code
, ins
->dreg
, src2
);
3211 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3215 if (mono_hwcap_s390x_has_mlt
) {
3216 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3218 CHECK_SRCDST_NCOM_I
;
3219 s390_ngr (code
, ins
->dreg
, src2
);
3224 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3225 if (mono_hwcap_s390x_has_mlt
) {
3226 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3228 if (ins
->dreg
!= ins
->sreg1
) {
3229 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3231 s390_ngr (code
, ins
->dreg
, s390_r0
);
3236 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3237 s390_srda (code
, s390_r0
, 0, 32);
3238 s390_dr (code
, s390_r0
, ins
->sreg2
);
3239 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3243 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3244 s390_srdl (code
, s390_r0
, 0, 32);
3245 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3246 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3250 if (s390_is_imm16 (ins
->inst_imm
)) {
3251 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3253 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3255 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3256 s390_srda (code
, s390_r0
, 0, 32);
3257 s390_dr (code
, s390_r0
, ins
->sreg2
);
3258 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3262 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3263 s390_srda (code
, s390_r0
, 0, 32);
3264 s390_dr (code
, s390_r0
, ins
->sreg2
);
3265 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3268 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3269 s390_srdl (code
, s390_r0
, 0, 32);
3270 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3271 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3275 if (s390_is_imm16 (ins
->inst_imm
)) {
3276 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3278 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3280 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3281 s390_srda (code
, s390_r0
, 0, 32);
3282 s390_dr (code
, s390_r0
, ins
->sreg2
);
3283 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3287 if (mono_hwcap_s390x_has_mlt
) {
3288 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3291 s390_ogr (code
, ins
->dreg
, src2
);
3296 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3297 if (mono_hwcap_s390x_has_mlt
) {
3298 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3300 if (ins
->dreg
!= ins
->sreg1
) {
3301 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3303 s390_ogr (code
, ins
->dreg
, s390_r0
);
3308 if (mono_hwcap_s390x_has_mlt
) {
3309 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3312 s390_xgr (code
, ins
->dreg
, src2
);
3317 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3318 if (mono_hwcap_s390x_has_mlt
) {
3319 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3321 if (ins
->dreg
!= ins
->sreg1
) {
3322 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3324 s390_xgr (code
, ins
->dreg
, s390_r0
);
3330 s390_sll (code
, ins
->dreg
, src2
, 0);
3334 if (ins
->sreg1
!= ins
->dreg
) {
3335 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3337 s390_sll (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3342 s390_sra (code
, ins
->dreg
, src2
, 0);
3346 if (ins
->sreg1
!= ins
->dreg
) {
3347 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3349 s390_sra (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3352 case OP_ISHR_UN_IMM
: {
3353 if (ins
->sreg1
!= ins
->dreg
) {
3354 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3356 s390_srl (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3361 s390_srl (code
, ins
->dreg
, src2
, 0);
3365 if (ins
->sreg1
!= ins
->dreg
) {
3366 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3368 s390_lghi (code
, s390_r0
, -1);
3369 s390_xgr (code
, ins
->dreg
, s390_r0
);
3373 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
3378 s390_msr (code
, ins
->dreg
, src2
);
3382 if (ins
->dreg
!= ins
->sreg1
) {
3383 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3385 if (s390_is_imm16 (ins
->inst_imm
)) {
3386 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3388 s390_lgfi (code
, s390_r0
, ins
->inst_imm
);
3390 s390_msr (code
, ins
->dreg
, s390_r0
);
3395 s390_ltr (code
, s390_r1
, ins
->sreg1
);
3396 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3397 s390_ltr (code
, s390_r0
, ins
->sreg2
);
3399 s390_lhi (code
, s390_r1
, 0);
3400 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3401 s390_xr (code
, s390_r0
, s390_r1
);
3402 s390_msr (code
, s390_r1
, ins
->sreg2
);
3403 s390_xr (code
, s390_r0
, s390_r1
);
3404 s390_srl (code
, s390_r0
, 0, 31);
3405 s390_ltr (code
, s390_r0
, s390_r0
);
3406 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3407 PTRSLOT (code
, o
[0]);
3408 PTRSLOT (code
, o
[1]);
3409 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3412 case OP_IMUL_OVF_UN
: {
3413 s390_lhi (code
, s390_r0
, 0);
3414 s390_lr (code
, s390_r1
, ins
->sreg1
);
3415 s390_mlr (code
, s390_r0
, ins
->sreg2
);
3416 s390_ltr (code
, s390_r0
, s390_r0
);
3417 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3418 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3423 S390_SET (code
, ins
->dreg
, ins
->inst_c0
);
3427 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3428 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
3429 S390_LOAD_TEMPLATE (code
, ins
->dreg
);
3432 case OP_JUMP_TABLE
: {
3433 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3434 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
3435 S390_LOAD_TEMPLATE (code
, ins
->dreg
);
3439 if (ins
->dreg
!= ins
->sreg1
) {
3440 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3444 case OP_LCONV_TO_I8
:
3446 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3448 case OP_LCONV_TO_I4
:
3449 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3452 case OP_LCONV_TO_U8
:
3453 case OP_LCONV_TO_U4
:
3455 s390_llgfr (code
, ins
->dreg
, ins
->sreg1
);
3457 case OP_LCONV_TO_OVF_U4
:
3458 S390_SET (code
, s390_r0
, 4294967295);
3459 s390_clgr (code
, ins
->sreg1
, s390_r0
);
3460 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, "OverflowException");
3461 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
3462 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, "OverflowException");
3463 s390_llgfr(code
, ins
->dreg
, ins
->sreg1
);
3465 case OP_LCONV_TO_OVF_I4_UN
:
3466 S390_SET (code
, s390_r0
, 2147483647);
3467 s390_cgr (code
, ins
->sreg1
, s390_r0
);
3468 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, "OverflowException");
3469 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
3470 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, "OverflowException");
3471 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3474 if (ins
->dreg
!= ins
->sreg1
) {
3475 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
3478 case OP_MOVE_F_TO_I8
:
3479 s390_lgdr (code
, ins
->dreg
, ins
->sreg1
);
3481 case OP_MOVE_I8_TO_F
:
3482 s390_ldgr (code
, ins
->dreg
, ins
->sreg1
);
3484 case OP_MOVE_F_TO_I4
:
3485 s390_ledbr (code
, s390_f0
, ins
->sreg1
);
3486 s390_lgdr (code
, ins
->dreg
, s390_f0
);
3487 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0, 32);
3489 case OP_MOVE_I4_TO_F
:
3490 s390_slag (code
, s390_r0
, ins
->sreg1
, 0, 32);
3491 s390_ldgr (code
, ins
->dreg
, s390_r0
);
3493 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
3495 case OP_FCONV_TO_R4
:
3496 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
3498 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
3500 case OP_S390_SETF4RET
:
3502 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
3505 if (s390_is_imm16 (ins
->inst_offset
)) {
3506 s390_lghi (code
, s390_r13
, ins
->inst_offset
);
3507 } else if (s390_is_imm32 (ins
->inst_offset
)) {
3508 s390_lgfi (code
, s390_r13
, ins
->inst_offset
);
3510 S390_SET (code
, s390_r13
, ins
->inst_offset
);
3512 s390_ear (code
, s390_r1
, 0);
3513 s390_sllg(code
, s390_r1
, s390_r1
, 0, 32);
3514 s390_ear (code
, s390_r1
, 1);
3515 s390_lg (code
, ins
->dreg
, s390_r13
, s390_r1
, 0);
3519 if (s390_is_imm16 (ins
->inst_offset
)) {
3520 s390_lghi (code
, s390_r13
, ins
->inst_offset
);
3521 } else if (s390_is_imm32 (ins
->inst_offset
)) {
3522 s390_lgfi (code
, s390_r13
, ins
->inst_offset
);
3524 S390_SET (code
, s390_r13
, ins
->inst_offset
);
3526 s390_ear (code
, s390_r1
, 0);
3527 s390_sllg(code
, s390_r1
, s390_r1
, 0, 32);
3528 s390_ear (code
, s390_r1
, 1);
3529 s390_stg (code
, ins
->sreg1
, s390_r13
, s390_r1
, 0);
3532 case OP_TAILCALL_PARAMETER
:
3533 // This opcode helps compute sizes, i.e.
3534 // of the subsequent OP_TAILCALL, but contributes no code.
3535 g_assert (ins
->next
);
3538 case OP_TAILCALL_MEMBASE
: {
3539 MonoCallInst
*call
= (MonoCallInst
*) ins
;
3540 MonoMethod
*method
= call
->method
;
3541 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
3542 CallInfo
*cinfo
= get_call_info (NULL
, sig
);
3543 int32_t stackUsage
= (cinfo
->sz
.stack_size
- S390_MINIMAL_STACK_SIZE
),
3544 stackOffset
= S390_MINIMAL_STACK_SIZE
;
3546 if (cfg
->method
->save_lmf
)
3547 restoreLMF(code
, cfg
->frame_reg
, cfg
->stack_usage
);
3549 s390_lgr (code
, s390_r12
, cfg
->frame_reg
);
3550 code
= backUpStackPtr(cfg
, code
);
3552 while (stackUsage
> 256) {
3553 s390_mvc (code
, 256, STK_BASE
, stackOffset
,
3554 s390_r12
, stackOffset
);
3560 s390_mvc (code
, stackUsage
, STK_BASE
, stackOffset
,
3561 s390_r12
, stackOffset
);
3563 s390_lmg (code
, s390_r6
, s390_r13
, STK_BASE
, S390_REG_SAVE_OFFSET
);
3565 if (cfg
->arch
.used_fp_regs
!= 0) {
3566 int32_t fpOffset
= sizeof(double);
3567 for (int i
=8; i
<16; i
++) {
3568 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
3569 s390_ld (code
, i
, cfg
->arch
.fpSize
, STK_BASE
, fpOffset
);
3570 fpOffset
+= sizeof(double);
3575 s390_lg (code
, s390_r14
, 0, STK_BASE
, S390_RET_ADDR_OFFSET
);
3576 if (ins
->opcode
== OP_TAILCALL_MEMBASE
) {
3577 if (mono_hwcap_s390x_has_mie2
) {
3578 s390_bi (code
, 0, ins
->sreg1
, ins
->inst_offset
);
3580 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3581 s390_br (code
, s390_r1
);
3584 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3585 MONO_PATCH_INFO_METHOD_JUMP
,
3587 s390_jcl (code
, S390_CC_UN
, 0);
3593 case OP_CHECK_THIS
: {
3594 /* ensure ins->sreg1 is not NULL */
3595 s390_lg (code
, s390_r0
, 0, ins
->sreg1
, 0);
3596 s390_ltgr (code
, s390_r0
, s390_r0
);
3597 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3601 const int offset
= cfg
->sig_cookie
+ cfg
->stack_usage
;
3603 if (s390_is_imm16 (offset
)) {
3604 s390_lghi (code
, s390_r0
, offset
);
3605 } else if (s390_is_imm32 (offset
)) {
3606 s390_lgfi (code
, s390_r0
, offset
);
3608 S390_SET (code
, s390_r0
, offset
);
3610 s390_agr (code
, s390_r0
, cfg
->frame_reg
);
3611 s390_stg (code
, s390_r0
, 0, ins
->sreg1
, 0);
3615 call
= (MonoCallInst
*)ins
;
3616 if (ins
->flags
& MONO_INST_HAS_METHOD
)
3617 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
3618 MONO_PATCH_INFO_METHOD
,
3621 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
3622 MONO_PATCH_INFO_ABS
,
3624 S390_CALL_TEMPLATE (code
, s390_r14
);
3625 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
3626 s390_ldebr (code
, s390_f0
, s390_f0
);
3635 call
= (MonoCallInst
*)ins
;
3636 mono_call_add_patch_info (cfg
, call
, code
- cfg
->native_code
);
3637 S390_CALL_TEMPLATE (code
, s390_r14
);
3640 case OP_FCALL_REG
: {
3641 call
= (MonoCallInst
*)ins
;
3642 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3643 s390_basr (code
, s390_r14
, s390_r1
);
3644 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
3645 s390_ldebr (code
, s390_f0
, s390_f0
);
3651 case OP_VOIDCALL_REG
:
3654 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3655 s390_basr (code
, s390_r14
, s390_r1
);
3658 case OP_FCALL_MEMBASE
: {
3659 call
= (MonoCallInst
*)ins
;
3660 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3661 s390_basr (code
, s390_r14
, s390_r1
);
3662 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
3663 s390_ldebr (code
, s390_f0
, s390_f0
);
3666 case OP_LCALL_MEMBASE
:
3667 case OP_VCALL_MEMBASE
:
3668 case OP_VCALL2_MEMBASE
:
3669 case OP_VOIDCALL_MEMBASE
:
3670 case OP_RCALL_MEMBASE
:
3671 case OP_CALL_MEMBASE
: {
3672 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3673 s390_basr (code
, s390_r14
, s390_r1
);
3680 if (cfg
->param_area
== 0)
3681 alloca_skip
= S390_MINIMAL_STACK_SIZE
;
3683 alloca_skip
= cfg
->param_area
;
3685 area_offset
= S390_ALIGN(alloca_skip
, S390_STACK_ALIGNMENT
);
3686 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3687 if (ins
->flags
& MONO_INST_INIT
)
3688 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3689 s390_aghi (code
, s390_r1
, 14);
3690 s390_srlg (code
, s390_r1
, s390_r1
, 0, 3);
3691 s390_sllg (code
, s390_r1
, s390_r1
, 0, 3);
3692 if (cfg
->method
->save_lmf
) {
3693 /*----------------------------------*/
3694 /* we have to adjust lmf ebp value */
3695 /*----------------------------------*/
3696 int lmfOffset
= cfg
->stack_usage
- sizeof(MonoLMF
);
3698 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
3699 if (s390_is_imm16(lmfOffset
)) {
3700 s390_aghi (code
, s390_r13
, lmfOffset
);
3701 } else if (s390_is_imm32(lmfOffset
)) {
3702 s390_agfi (code
, s390_r13
, lmfOffset
);
3704 S390_SET (code
, s390_r13
, lmfOffset
);
3706 s390_lgr (code
, s390_r14
, STK_BASE
);
3707 s390_sgr (code
, s390_r14
, s390_r1
);
3708 s390_stg (code
, s390_r14
, 0, s390_r13
,
3709 G_STRUCT_OFFSET(MonoLMF
, ebp
));
3711 s390_lg (code
, s390_r13
, 0, STK_BASE
, 0);
3712 s390_sgr (code
, STK_BASE
, s390_r1
);
3713 s390_stg (code
, s390_r13
, 0, STK_BASE
, 0);
3714 s390_la (code
, ins
->dreg
, 0, STK_BASE
, area_offset
);
3715 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
3716 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
3717 if (ins
->flags
& MONO_INST_INIT
) {
3718 s390_lgr (code
, s390_r1
, s390_r0
);
3719 s390_lgr (code
, s390_r0
, ins
->dreg
);
3720 s390_lgr (code
, s390_r14
, s390_r12
);
3721 s390_lghi (code
, s390_r13
, 0);
3722 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
3724 s390_lgr (code
, s390_r12
, s390_r14
);
3729 s390_lgr (code
, s390_r2
, ins
->sreg1
);
3730 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
3731 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_throw_exception
));
3732 S390_CALL_TEMPLATE(code
, s390_r14
);
3736 s390_lgr (code
, s390_r2
, ins
->sreg1
);
3737 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
3738 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception
));
3739 S390_CALL_TEMPLATE(code
, s390_r14
);
3742 case OP_START_HANDLER
: {
3743 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
3745 S390_LONG (code
, stg
, stg
, s390_r14
, 0,
3746 spvar
->inst_basereg
,
3747 spvar
->inst_offset
);
3750 case OP_ENDFILTER
: {
3751 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
3753 if (ins
->sreg1
!= s390_r2
)
3754 s390_lgr(code
, s390_r2
, ins
->sreg1
);
3755 S390_LONG (code
, lg
, lg
, s390_r14
, 0,
3756 spvar
->inst_basereg
,
3757 spvar
->inst_offset
);
3758 s390_br (code
, s390_r14
);
3761 case OP_ENDFINALLY
: {
3762 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
3764 S390_LONG (code
, lg
, lg
, s390_r14
, 0,
3765 spvar
->inst_basereg
,
3766 spvar
->inst_offset
);
3767 s390_br (code
, s390_r14
);
3770 case OP_CALL_HANDLER
: {
3771 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
3772 MONO_PATCH_INFO_BB
, ins
->inst_target_bb
);
3773 s390_brasl (code
, s390_r14
, 0);
3774 for (GList
*tmp
= ins
->inst_eh_blocks
; tmp
!= bb
->clause_holes
; tmp
= tmp
->prev
)
3775 mono_cfg_add_try_hole (cfg
, ((MonoLeaveClause
*) tmp
->data
)->clause
, code
, bb
);
3779 ins
->inst_c0
= code
- cfg
->native_code
;
3782 case OP_RELAXED_NOP
:
3785 case OP_DUMMY_ICONST
:
3786 case OP_DUMMY_I8CONST
:
3787 case OP_DUMMY_R8CONST
:
3788 case OP_DUMMY_R4CONST
:
3789 case OP_NOT_REACHED
:
3793 case OP_IL_SEQ_POINT
:
3794 mono_add_seq_point (cfg
, bb
, ins
, code
- cfg
->native_code
);
3796 case OP_SEQ_POINT
: {
3799 if (cfg
->compile_aot
)
3803 * Read from the single stepping trigger page. This will cause a
3804 * SIGSEGV when single stepping is enabled.
3805 * We do this _before_ the breakpoint, so single stepping after
3806 * a breakpoint is hit will step to the next IL offset.
3808 if (ins
->flags
& MONO_INST_SINGLE_STEP_LOC
) {
3809 breakpointCode
.pTrigger
= ss_trigger_page
;
3810 memcpy(code
, (void *) &breakpointCode
, BREAKPOINT_SIZE
);
3811 code
+= BREAKPOINT_SIZE
;
3814 mono_add_seq_point (cfg
, bb
, ins
, code
- cfg
->native_code
);
3817 * A placeholder for a possible breakpoint inserted by
3818 * mono_arch_set_breakpoint ().
3820 for (i
= 0; i
< (BREAKPOINT_SIZE
/ S390X_NOP_SIZE
); ++i
)
3824 * Add an additional nop so skipping the bp doesn't cause the ip to point
3825 * to another IL offset.
3831 case OP_GENERIC_CLASS_INIT
: {
3832 static int byte_offset
= -1;
3833 static guint8 bitmask
;
3836 g_assert (ins
->sreg1
== S390_FIRST_ARG_REG
);
3838 if (byte_offset
< 0)
3839 mono_marshal_find_bitfield_offset (MonoVTable
, initialized
, &byte_offset
, &bitmask
);
3841 s390_tm (code
, ins
->sreg1
, byte_offset
, bitmask
);
3842 s390_jo (code
, 0); CODEPTR(code
, jump
);
3844 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
3845 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_generic_class_init
));
3846 S390_CALL_TEMPLATE(code
, s390_r14
);
3848 PTRSLOT (code
, jump
);
3850 ins
->flags
|= MONO_INST_GC_CALLSITE
;
3851 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
3855 EMIT_UNCOND_BRANCH(ins
);
3858 s390_br (code
, ins
->sreg1
);
3864 s390_lghi(code
, ins
->dreg
, 1);
3866 s390_lghi(code
, ins
->dreg
, 0);
3872 s390_lghi(code
, ins
->dreg
, 1);
3874 s390_lghi(code
, ins
->dreg
, 0);
3880 s390_lghi(code
, ins
->dreg
, 1);
3882 s390_lghi(code
, ins
->dreg
, 0);
3888 s390_lghi(code
, ins
->dreg
, 1);
3890 s390_lghi(code
, ins
->dreg
, 0);
3896 s390_lghi(code
, ins
->dreg
, 1);
3898 s390_lghi(code
, ins
->dreg
, 0);
3902 s390_lghi(code
, ins
->dreg
, 1);
3904 s390_lghi(code
, ins
->dreg
, 0);
3908 s390_lghi(code
, ins
->dreg
, 1);
3910 s390_lghi(code
, ins
->dreg
, 0);
3914 s390_lghi(code
, ins
->dreg
, 1);
3916 s390_lghi(code
, ins
->dreg
, 0);
3920 s390_lghi(code
, ins
->dreg
, 1);
3922 s390_lghi(code
, ins
->dreg
, 0);
3926 s390_lghi(code
, ins
->dreg
, 1);
3928 s390_lghi(code
, ins
->dreg
, 0);
3931 case OP_COND_EXC_EQ
:
3932 case OP_COND_EXC_IEQ
:
3933 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ
, ins
->inst_p1
);
3935 case OP_COND_EXC_NE_UN
:
3936 case OP_COND_EXC_INE_UN
:
3937 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE
, ins
->inst_p1
);
3939 case OP_COND_EXC_LT
:
3940 case OP_COND_EXC_ILT
:
3941 case OP_COND_EXC_LT_UN
:
3942 case OP_COND_EXC_ILT_UN
:
3943 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, ins
->inst_p1
);
3945 case OP_COND_EXC_GT
:
3946 case OP_COND_EXC_IGT
:
3947 case OP_COND_EXC_GT_UN
:
3948 case OP_COND_EXC_IGT_UN
:
3949 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, ins
->inst_p1
);
3951 case OP_COND_EXC_GE
:
3952 case OP_COND_EXC_IGE
:
3953 case OP_COND_EXC_GE_UN
:
3954 case OP_COND_EXC_IGE_UN
:
3955 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE
, ins
->inst_p1
);
3957 case OP_COND_EXC_LE
:
3958 case OP_COND_EXC_ILE
:
3959 case OP_COND_EXC_LE_UN
:
3960 case OP_COND_EXC_ILE_UN
:
3961 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE
, ins
->inst_p1
);
3963 case OP_COND_EXC_OV
:
3964 case OP_COND_EXC_IOV
:
3965 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, ins
->inst_p1
);
3967 case OP_COND_EXC_NO
:
3968 case OP_COND_EXC_INO
:
3969 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO
, ins
->inst_p1
);
3972 case OP_COND_EXC_IC
:
3973 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, ins
->inst_p1
);
3975 case OP_COND_EXC_NC
:
3976 case OP_COND_EXC_INC
:
3977 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, ins
->inst_p1
);
3981 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
3985 EMIT_COND_BRANCH (ins
, S390_CC_NE
);
3991 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
3997 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4003 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4009 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4013 EMIT_COMP_AND_BRANCH(ins
, crj
, cr
);
4017 EMIT_COMP_AND_BRANCH(ins
, clrj
, clr
);
4021 EMIT_COMP_AND_BRANCH(ins
, cgrj
, cgr
);
4025 EMIT_COMP_AND_BRANCH(ins
, clgrj
, clgr
);
4029 EMIT_COMP_AND_BRANCH_IMM(ins
, crj
, cr
, ltr
, FALSE
);
4033 EMIT_COMP_AND_BRANCH_IMM(ins
, clrj
, clr
, ltr
, TRUE
);
4037 EMIT_COMP_AND_BRANCH_IMM(ins
, cgrj
, cgr
, ltgr
, FALSE
);
4041 EMIT_COMP_AND_BRANCH_IMM(ins
, clgrj
, clgr
, ltgr
, TRUE
);
4044 /* floating point opcodes */
4046 if (*((double *) ins
->inst_p0
) == 0) {
4047 s390_lzdr (code
, ins
->dreg
);
4049 S390_SET (code
, s390_r13
, ins
->inst_p0
);
4050 s390_ld (code
, ins
->dreg
, 0, s390_r13
, 0);
4055 if (*((float *) ins
->inst_p0
) == 0) {
4057 s390_lzer (code
, ins
->dreg
);
4059 s390_lzdr (code
, ins
->dreg
);
4061 S390_SET (code
, s390_r13
, ins
->inst_p0
);
4063 S390_LONG (code
, ley
, le
, ins
->dreg
, 0, s390_r13
, 0);
4065 s390_ldeb (code
, ins
->dreg
, 0, s390_r13
, 0);
4070 case OP_STORER8_MEMBASE_REG
: {
4071 S390_LONG (code
, stdy
, std
, ins
->sreg1
, 0,
4072 ins
->inst_destbasereg
, ins
->inst_offset
);
4075 case OP_LOADR8_MEMBASE
: {
4076 S390_LONG (code
, ldy
, ld
, ins
->dreg
, 0,
4077 ins
->inst_basereg
, ins
->inst_offset
);
4080 case OP_STORER4_MEMBASE_REG
: {
4082 S390_LONG (code
, stey
, ste
, ins
->sreg1
, 0,
4083 ins
->inst_destbasereg
, ins
->inst_offset
);
4085 s390_ledbr (code
, s390_f15
, ins
->sreg1
);
4086 S390_LONG (code
, stey
, ste
, s390_f15
, 0,
4087 ins
->inst_destbasereg
, ins
->inst_offset
);
4091 case OP_LOADR4_MEMBASE
: {
4093 S390_LONG (code
, ley
, le
, ins
->dreg
, 0,
4094 ins
->inst_basereg
, ins
->inst_offset
);
4096 S390_LONG (code
, ley
, le
, s390_f15
, 0,
4097 ins
->inst_basereg
, ins
->inst_offset
);
4098 s390_ldebr (code
, ins
->dreg
, s390_f15
);
4102 case OP_ICONV_TO_R_UN
: {
4103 if (mono_hwcap_s390x_has_fpe
) {
4104 s390_cdlfbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4106 s390_llgfr (code
, s390_r0
, ins
->sreg1
);
4107 s390_cdgbr (code
, ins
->dreg
, s390_r0
);
4111 case OP_LCONV_TO_R_UN
: {
4112 if (mono_hwcap_s390x_has_fpe
) {
4113 s390_cdlgbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4116 s390_cxgbr (code
, s390_f12
, ins
->sreg1
);
4117 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4118 s390_jnl (code
, 0); CODEPTR(code
, jump
);
4119 S390_SET (code
, s390_r13
, 0x403f000000000000llu
);
4120 s390_lgdr (code
, s390_f13
, s390_r13
);
4121 s390_lzdr (code
, s390_f15
);
4122 s390_axbr (code
, s390_f12
, s390_f13
);
4123 PTRSLOT(code
, jump
);
4124 s390_ldxbr (code
, s390_f13
, s390_f12
);
4125 s390_ldr (code
, ins
->dreg
, s390_f13
);
4129 case OP_LCONV_TO_R4
:
4130 case OP_ICONV_TO_R4
: {
4131 s390_cegbr (code
, ins
->dreg
, ins
->sreg1
);
4133 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
4136 case OP_LCONV_TO_R8
:
4137 case OP_ICONV_TO_R8
: {
4138 s390_cdgbr (code
, ins
->dreg
, ins
->sreg1
);
4141 case OP_FCONV_TO_I1
:
4142 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4143 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4145 s390_oill (code
, ins
->dreg
, 0x80);
4146 s390_lghi (code
, s390_r0
, 0xff);
4147 s390_ngr (code
, ins
->dreg
, s390_r0
);
4149 case OP_FCONV_TO_U1
:
4150 if (mono_hwcap_s390x_has_fpe
) {
4151 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4152 s390_lghi (code
, s390_r0
, 0xff);
4153 s390_ngr (code
, ins
->dreg
, s390_r0
);
4155 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4158 case OP_FCONV_TO_I2
:
4159 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4160 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4162 s390_oill (code
, ins
->dreg
, 0x8000);
4163 s390_llill (code
, s390_r0
, 0xffff);
4164 s390_ngr (code
, ins
->dreg
, s390_r0
);
4166 case OP_FCONV_TO_U2
:
4167 if (mono_hwcap_s390x_has_fpe
) {
4168 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4169 s390_llill (code
, s390_r0
, 0xffff);
4170 s390_ngr (code
, ins
->dreg
, s390_r0
);
4172 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4175 case OP_FCONV_TO_I4
:
4177 s390_cfdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4179 case OP_FCONV_TO_U4
:
4181 if (mono_hwcap_s390x_has_fpe
) {
4182 s390_clfdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4184 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4187 case OP_FCONV_TO_I8
:
4188 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4190 case OP_FCONV_TO_U8
:
4191 if (mono_hwcap_s390x_has_fpe
) {
4192 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4194 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 8, FALSE
);
4197 case OP_RCONV_TO_I1
:
4198 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4199 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4201 s390_oill (code
, ins
->dreg
, 0x80);
4202 s390_lghi (code
, s390_r0
, 0xff);
4203 s390_ngr (code
, ins
->dreg
, s390_r0
);
4205 case OP_RCONV_TO_U1
:
4206 if (mono_hwcap_s390x_has_fpe
) {
4207 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4208 s390_lghi (code
, s390_r0
, 0xff);
4209 s390_ngr (code
, ins
->dreg
, s390_r0
);
4211 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4214 case OP_RCONV_TO_I2
:
4215 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4216 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4218 s390_oill (code
, ins
->dreg
, 0x8000);
4219 s390_llill (code
, s390_r0
, 0xffff);
4220 s390_ngr (code
, ins
->dreg
, s390_r0
);
4222 case OP_RCONV_TO_U2
:
4223 if (mono_hwcap_s390x_has_fpe
) {
4224 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4225 s390_llill (code
, s390_r0
, 0xffff);
4226 s390_ngr (code
, ins
->dreg
, s390_r0
);
4228 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4231 case OP_RCONV_TO_I4
:
4233 s390_cfebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4235 case OP_RCONV_TO_U4
:
4236 if (mono_hwcap_s390x_has_fpe
) {
4237 s390_clfebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4239 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4242 case OP_RCONV_TO_I8
:
4243 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4245 case OP_RCONV_TO_U8
:
4246 if (mono_hwcap_s390x_has_fpe
) {
4247 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4249 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 8, FALSE
);
4252 case OP_LCONV_TO_OVF_I
: {
4253 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4255 s390_ltgr (code
, ins
->sreg2
, ins
->sreg2
);
4256 s390_jnl (code
, 0); CODEPTR(code
, o
[0]);
4257 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4258 s390_jnl (code
, 0); CODEPTR(code
, o
[1]);
4259 s390_lhi (code
, s390_r13
, -1);
4260 s390_cgr (code
, ins
->sreg1
, s390_r13
);
4261 s390_jnz (code
, 0); CODEPTR(code
, o
[2]);
4262 if (ins
->dreg
!= ins
->sreg2
)
4263 s390_lgr (code
, ins
->dreg
, ins
->sreg2
);
4264 s390_j (code
, 0); CODEPTR(code
, o
[3]);
4265 PTRSLOT(code
, o
[0]);
4266 s390_jz (code
, 0); CODEPTR(code
, o
[4]);
4267 PTRSLOT(code
, o
[1]);
4268 PTRSLOT(code
, o
[2]);
4269 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4270 MONO_PATCH_INFO_EXC
, "OverflowException");
4271 s390_brasl (code
, s390_r14
, 0);
4272 PTRSLOT(code
, o
[3]);
4273 PTRSLOT(code
, o
[4]);
4277 s390_lpdbr (code
, ins
->dreg
, ins
->sreg1
);
4281 s390_sqdbr (code
, ins
->dreg
, ins
->sreg1
);
4286 s390_adbr (code
, ins
->dreg
, src2
);
4291 s390_aebr (code
, ins
->dreg
, src2
);
4295 CHECK_SRCDST_NCOM_F
;
4296 s390_sdbr (code
, ins
->dreg
, src2
);
4300 CHECK_SRCDST_NCOM_F
;
4301 s390_sebr (code
, ins
->dreg
, src2
);
4306 s390_mdbr (code
, ins
->dreg
, src2
);
4311 s390_meer (code
, ins
->dreg
, src2
);
4315 CHECK_SRCDST_NCOM_F
;
4316 s390_ddbr (code
, ins
->dreg
, src2
);
4320 CHECK_SRCDST_NCOM_F
;
4321 s390_debr (code
, ins
->dreg
, src2
);
4325 s390_lcdbr (code
, ins
->dreg
, ins
->sreg1
);
4329 s390_lcebr (code
, ins
->dreg
, ins
->sreg1
);
4333 CHECK_SRCDST_NCOM_F
;
4334 s390_didbr (code
, ins
->dreg
, src2
, 5, s390_f15
);
4338 CHECK_SRCDST_NCOM_F
;
4339 s390_diebr (code
, ins
->dreg
, src2
, 5, s390_f15
);
4343 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4347 s390_cebr (code
, ins
->sreg1
, ins
->sreg2
);
4351 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4352 s390_lghi (code
, ins
->dreg
, 1);
4354 s390_lghi (code
, ins
->dreg
, 0);
4358 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4359 s390_lghi (code
, ins
->dreg
, 1);
4361 s390_lghi (code
, ins
->dreg
, 0);
4365 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4366 s390_lghi (code
, ins
->dreg
, 1);
4368 s390_lghi (code
, ins
->dreg
, 0);
4372 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4373 s390_lghi (code
, ins
->dreg
, 1);
4375 s390_lghi (code
, ins
->dreg
, 0);
4379 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4380 s390_lghi (code
, ins
->dreg
, 1);
4382 s390_lghi (code
, ins
->dreg
, 0);
4386 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4387 s390_lghi (code
, ins
->dreg
, 1);
4389 s390_lghi (code
, ins
->dreg
, 0);
4393 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4394 s390_lghi (code
, ins
->dreg
, 1);
4396 s390_lghi (code
, ins
->dreg
, 0);
4400 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4401 s390_lghi (code
, ins
->dreg
, 1);
4403 s390_lghi (code
, ins
->dreg
, 0);
4407 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4408 s390_lghi (code
, ins
->dreg
, 1);
4410 s390_lghi (code
, ins
->dreg
, 0);
4414 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4415 s390_lghi (code
, ins
->dreg
, 1);
4417 s390_lghi (code
, ins
->dreg
, 0);
4421 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4422 s390_lghi (code
, ins
->dreg
, 1);
4424 s390_lghi (code
, ins
->dreg
, 0);
4428 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4429 s390_lghi (code
, ins
->dreg
, 1);
4431 s390_lghi (code
, ins
->dreg
, 0);
4435 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4436 s390_lghi (code
, ins
->dreg
, 1);
4438 s390_lghi (code
, ins
->dreg
, 0);
4442 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4443 s390_lghi (code
, ins
->dreg
, 1);
4445 s390_lghi (code
, ins
->dreg
, 0);
4449 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4450 s390_lghi (code
, ins
->dreg
, 1);
4452 s390_lghi (code
, ins
->dreg
, 0);
4456 s390_cebr (code
, ins
->sreg1
, ins
->sreg2
);
4457 s390_lghi (code
, ins
->dreg
, 1);
4459 s390_lghi (code
, ins
->dreg
, 0);
4464 s390_jo (code
, 0); CODEPTR(code
, o
);
4465 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
4470 EMIT_COND_BRANCH (ins
, S390_CC_NE
|S390_CC_OV
);
4474 s390_jo (code
, 0); CODEPTR(code
, o
);
4475 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4480 EMIT_COND_BRANCH (ins
, S390_CC_LT
|S390_CC_OV
);
4484 s390_jo (code
, 0); CODEPTR(code
, o
);
4485 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4490 EMIT_COND_BRANCH (ins
, S390_CC_GT
|S390_CC_OV
);
4494 s390_jo (code
, 0); CODEPTR(code
, o
);
4495 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4500 EMIT_COND_BRANCH (ins
, S390_CC_GE
|S390_CC_OV
);
4504 s390_jo (code
, 0); CODEPTR(code
, o
);
4505 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4510 EMIT_COND_BRANCH (ins
, S390_CC_LE
|S390_CC_OV
);
4514 s390_lhi (code
, s390_r13
, 0x7f);
4515 s390_tcdb (code
, ins
->sreg1
, 0, s390_r13
, 0);
4516 s390_jz (code
, 0); CODEPTR(code
, o
);
4517 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4518 MONO_PATCH_INFO_EXC
, "OverflowException");
4519 s390_brasl (code
, s390_r14
,0);
4523 case OP_S390_MOVE
: {
4524 if (ins
->backend
.size
> 0) {
4525 if (ins
->backend
.size
<= 256) {
4526 s390_mvc (code
, ins
->backend
.size
, ins
->dreg
,
4527 ins
->inst_offset
, ins
->sreg1
, ins
->inst_imm
);
4529 s390_lgr (code
, s390_r0
, ins
->dreg
);
4530 if (ins
->inst_offset
> 0) {
4531 if (s390_is_imm16 (ins
->inst_offset
)) {
4532 s390_aghi (code
, s390_r0
, ins
->inst_offset
);
4533 } else if (s390_is_imm32 (ins
->inst_offset
)) {
4534 s390_agfi (code
, s390_r0
, ins
->inst_offset
);
4536 S390_SET (code
, s390_r13
, ins
->inst_offset
);
4537 s390_agr (code
, s390_r0
, s390_r13
);
4540 s390_lgr (code
, s390_r12
, ins
->sreg1
);
4541 if (ins
->inst_imm
> 0) {
4542 if (s390_is_imm16 (ins
->inst_imm
)) {
4543 s390_aghi (code
, s390_r12
, ins
->inst_imm
);
4544 } else if (s390_is_imm32 (ins
->inst_imm
)) {
4545 s390_agfi (code
, s390_r12
, ins
->inst_imm
);
4547 S390_SET (code
, s390_r13
, ins
->inst_imm
);
4548 s390_agr (code
, s390_r12
, s390_r13
);
4551 if (s390_is_imm16 (ins
->backend
.size
)) {
4552 s390_lghi (code
, s390_r1
, ins
->backend
.size
);
4553 } else if (s390_is_imm32 (ins
->inst_offset
)) {
4554 s390_agfi (code
, s390_r1
, ins
->backend
.size
);
4556 S390_SET (code
, s390_r13
, ins
->backend
.size
);
4557 s390_agr (code
, s390_r1
, s390_r13
);
4559 s390_lgr (code
, s390_r13
, s390_r1
);
4560 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
4566 case OP_ATOMIC_ADD_I8
: {
4567 if (mono_hwcap_s390x_has_ia
) {
4568 s390_laag (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4569 s390_agr (code
, ins
->dreg
, ins
->sreg2
);
4571 s390_lgr (code
, s390_r1
, ins
->sreg2
);
4572 s390_lg (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4573 s390_agr (code
, s390_r1
, s390_r0
);
4574 s390_csg (code
, s390_r0
, s390_r1
, ins
->inst_basereg
, ins
->inst_offset
);
4575 s390_jnz (code
, -10);
4576 s390_lgr (code
, ins
->dreg
, s390_r1
);
4580 case OP_ATOMIC_EXCHANGE_I8
: {
4581 s390_lg (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4582 s390_csg (code
, s390_r0
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4583 s390_jnz (code
, -6);
4584 s390_lgr (code
, ins
->dreg
, s390_r0
);
4587 case OP_ATOMIC_ADD_I4
: {
4588 if (mono_hwcap_s390x_has_ia
) {
4589 s390_laa (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4590 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
4592 s390_lgfr(code
, s390_r1
, ins
->sreg2
);
4593 s390_lgf (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4594 s390_agr (code
, s390_r1
, s390_r0
);
4595 s390_cs (code
, s390_r0
, s390_r1
, ins
->inst_basereg
, ins
->inst_offset
);
4596 s390_jnz (code
, -9);
4597 s390_lgfr(code
, ins
->dreg
, s390_r1
);
4601 case OP_ATOMIC_EXCHANGE_I4
: {
4602 s390_l (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4603 s390_cs (code
, s390_r0
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4604 s390_jnz (code
, -4);
4605 s390_lgfr(code
, ins
->dreg
, s390_r0
);
4608 case OP_S390_BKCHAIN
: {
4609 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
4610 if (s390_is_imm16 (cfg
->stack_offset
)) {
4611 s390_aghi (code
, ins
->dreg
, cfg
->stack_offset
);
4612 } else if (s390_is_imm32 (cfg
->stack_offset
)) {
4613 s390_agfi (code
, ins
->dreg
, cfg
->stack_offset
);
4615 S390_SET (code
, s390_r13
, cfg
->stack_offset
);
4616 s390_agr (code
, ins
->dreg
, s390_r13
);
4620 case OP_MEMORY_BARRIER
:
4623 case OP_LIVERANGE_START
: {
4624 if (cfg
->verbose_level
> 1)
4625 printf ("R%d START=0x%x\n", MONO_VARINFO (cfg
, ins
->inst_c0
)->vreg
, (int)(code
- cfg
->native_code
));
4626 MONO_VARINFO (cfg
, ins
->inst_c0
)->live_range_start
= code
- cfg
->native_code
;
4629 case OP_LIVERANGE_END
: {
4630 if (cfg
->verbose_level
> 1)
4631 printf ("R%d END=0x%x\n", MONO_VARINFO (cfg
, ins
->inst_c0
)->vreg
, (int)(code
- cfg
->native_code
));
4632 MONO_VARINFO (cfg
, ins
->inst_c0
)->live_range_end
= code
- cfg
->native_code
;
4635 case OP_GC_SAFE_POINT
: {
4638 s390_ltg (code
, s390_r0
, 0, ins
->sreg1
, 0);
4639 s390_jz (code
, 0); CODEPTR(code
, br
);
4640 mono_add_patch_info (cfg
, code
- cfg
->native_code
, MONO_PATCH_INFO_ABS
,
4641 mono_threads_state_poll
);
4642 S390_CALL_TEMPLATE (code
, s390_r14
);
4646 case OP_GC_LIVENESS_DEF
:
4647 case OP_GC_LIVENESS_USE
:
4648 case OP_GC_PARAM_SLOT_LIVENESS_DEF
:
4649 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
4651 case OP_GC_SPILL_SLOT_LIVENESS_DEF
:
4652 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
4653 bb
->spill_slot_defs
= g_slist_prepend_mempool (cfg
->mempool
, bb
->spill_slot_defs
, ins
);
4655 #ifdef MONO_ARCH_SIMD_INTRINSICS
4657 s390x_addps (code
, ins
->sreg1
, ins
->sreg2
);
4660 s390x_divps (code
, ins
->sreg1
, ins
->sreg2
);
4663 s390x_mulps (code
, ins
->sreg1
, ins
->sreg2
);
4666 s390x_subps (code
, ins
->sreg1
, ins
->sreg2
);
4669 s390x_maxps (code
, ins
->sreg1
, ins
->sreg2
);
4672 s390x_minps (code
, ins
->sreg1
, ins
->sreg2
);
4675 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 7);
4676 s390x_cmpps_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4679 s390x_andps (code
, ins
->sreg1
, ins
->sreg2
);
4682 s390x_andnps (code
, ins
->sreg1
, ins
->sreg2
);
4685 s390x_orps (code
, ins
->sreg1
, ins
->sreg2
);
4688 s390x_xorps (code
, ins
->sreg1
, ins
->sreg2
);
4691 s390x_sqrtps (code
, ins
->dreg
, ins
->sreg1
);
4694 s390x_rsqrtps (code
, ins
->dreg
, ins
->sreg1
);
4697 s390x_rcpps (code
, ins
->dreg
, ins
->sreg1
);
4700 s390x_addsubps (code
, ins
->sreg1
, ins
->sreg2
);
4703 s390x_haddps (code
, ins
->sreg1
, ins
->sreg2
);
4706 s390x_hsubps (code
, ins
->sreg1
, ins
->sreg2
);
4709 s390x_movshdup (code
, ins
->dreg
, ins
->sreg1
);
4712 s390x_movsldup (code
, ins
->dreg
, ins
->sreg1
);
4715 case OP_PSHUFLEW_HIGH
:
4716 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4717 s390x_pshufhw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
4719 case OP_PSHUFLEW_LOW
:
4720 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4721 s390x_pshuflw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
4724 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4725 s390x_pshufd_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
4728 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4729 s390x_shufps_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4732 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0x3);
4733 s390x_shufpd_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4737 s390x_addpd (code
, ins
->sreg1
, ins
->sreg2
);
4740 s390x_divpd (code
, ins
->sreg1
, ins
->sreg2
);
4743 s390x_mulpd (code
, ins
->sreg1
, ins
->sreg2
);
4746 s390x_subpd (code
, ins
->sreg1
, ins
->sreg2
);
4749 s390x_maxpd (code
, ins
->sreg1
, ins
->sreg2
);
4752 s390x_minpd (code
, ins
->sreg1
, ins
->sreg2
);
4755 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 7);
4756 s390x_cmppd_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4759 s390x_andpd (code
, ins
->sreg1
, ins
->sreg2
);
4762 s390x_andnpd (code
, ins
->sreg1
, ins
->sreg2
);
4765 s390x_orpd (code
, ins
->sreg1
, ins
->sreg2
);
4768 s390x_xorpd (code
, ins
->sreg1
, ins
->sreg2
);
4771 s390x_sqrtpd (code
, ins
->dreg
, ins
->sreg1
);
4774 s390x_addsubpd (code
, ins
->sreg1
, ins
->sreg2
);
4777 s390x_haddpd (code
, ins
->sreg1
, ins
->sreg2
);
4780 s390x_hsubpd (code
, ins
->sreg1
, ins
->sreg2
);
4783 s390x_movddup (code
, ins
->dreg
, ins
->sreg1
);
4786 case OP_EXTRACT_MASK
:
4787 s390x_pmovmskb (code
, ins
->dreg
, ins
->sreg1
);
4791 s390x_pand (code
, ins
->sreg1
, ins
->sreg2
);
4794 s390x_por (code
, ins
->sreg1
, ins
->sreg2
);
4797 s390x_pxor (code
, ins
->sreg1
, ins
->sreg2
);
4801 s390x_paddb (code
, ins
->sreg1
, ins
->sreg2
);
4804 s390x_paddw (code
, ins
->sreg1
, ins
->sreg2
);
4807 s390x_paddd (code
, ins
->sreg1
, ins
->sreg2
);
4810 s390x_paddq (code
, ins
->sreg1
, ins
->sreg2
);
4814 s390x_psubb (code
, ins
->sreg1
, ins
->sreg2
);
4817 s390x_psubw (code
, ins
->sreg1
, ins
->sreg2
);
4820 s390x_psubd (code
, ins
->sreg1
, ins
->sreg2
);
4823 s390x_psubq (code
, ins
->sreg1
, ins
->sreg2
);
4827 s390x_pmaxub (code
, ins
->sreg1
, ins
->sreg2
);
4830 s390x_pmaxuw (code
, ins
->sreg1
, ins
->sreg2
);
4833 s390x_pmaxud (code
, ins
->sreg1
, ins
->sreg2
);
4837 s390x_pmaxsb (code
, ins
->sreg1
, ins
->sreg2
);
4840 s390x_pmaxsw (code
, ins
->sreg1
, ins
->sreg2
);
4843 s390x_pmaxsd (code
, ins
->sreg1
, ins
->sreg2
);
4847 s390x_pavgb (code
, ins
->sreg1
, ins
->sreg2
);
4850 s390x_pavgw (code
, ins
->sreg1
, ins
->sreg2
);
4854 s390x_pminub (code
, ins
->sreg1
, ins
->sreg2
);
4857 s390x_pminuw (code
, ins
->sreg1
, ins
->sreg2
);
4860 s390x_pminud (code
, ins
->sreg1
, ins
->sreg2
);
4864 s390x_pminsb (code
, ins
->sreg1
, ins
->sreg2
);
4867 s390x_pminsw (code
, ins
->sreg1
, ins
->sreg2
);
4870 s390x_pminsd (code
, ins
->sreg1
, ins
->sreg2
);
4874 s390x_pcmpeqb (code
, ins
->sreg1
, ins
->sreg2
);
4877 s390x_pcmpeqw (code
, ins
->sreg1
, ins
->sreg2
);
4880 s390x_pcmpeqd (code
, ins
->sreg1
, ins
->sreg2
);
4883 s390x_pcmpeqq (code
, ins
->sreg1
, ins
->sreg2
);
4887 s390x_pcmpgtb (code
, ins
->sreg1
, ins
->sreg2
);
4890 s390x_pcmpgtw (code
, ins
->sreg1
, ins
->sreg2
);
4893 s390x_pcmpgtd (code
, ins
->sreg1
, ins
->sreg2
);
4896 s390x_pcmpgtq (code
, ins
->sreg1
, ins
->sreg2
);
4899 case OP_PSUM_ABS_DIFF
:
4900 s390x_psadbw (code
, ins
->sreg1
, ins
->sreg2
);
4903 case OP_UNPACK_LOWB
:
4904 s390x_punpcklbw (code
, ins
->sreg1
, ins
->sreg2
);
4906 case OP_UNPACK_LOWW
:
4907 s390x_punpcklwd (code
, ins
->sreg1
, ins
->sreg2
);
4909 case OP_UNPACK_LOWD
:
4910 s390x_punpckldq (code
, ins
->sreg1
, ins
->sreg2
);
4912 case OP_UNPACK_LOWQ
:
4913 s390x_punpcklqdq (code
, ins
->sreg1
, ins
->sreg2
);
4915 case OP_UNPACK_LOWPS
:
4916 s390x_unpcklps (code
, ins
->sreg1
, ins
->sreg2
);
4918 case OP_UNPACK_LOWPD
:
4919 s390x_unpcklpd (code
, ins
->sreg1
, ins
->sreg2
);
4922 case OP_UNPACK_HIGHB
:
4923 s390x_punpckhbw (code
, ins
->sreg1
, ins
->sreg2
);
4925 case OP_UNPACK_HIGHW
:
4926 s390x_punpckhwd (code
, ins
->sreg1
, ins
->sreg2
);
4928 case OP_UNPACK_HIGHD
:
4929 s390x_punpckhdq (code
, ins
->sreg1
, ins
->sreg2
);
4931 case OP_UNPACK_HIGHQ
:
4932 s390x_punpckhqdq (code
, ins
->sreg1
, ins
->sreg2
);
4934 case OP_UNPACK_HIGHPS
:
4935 s390x_unpckhps (code
, ins
->sreg1
, ins
->sreg2
);
4937 case OP_UNPACK_HIGHPD
:
4938 s390x_unpckhpd (code
, ins
->sreg1
, ins
->sreg2
);
4942 s390x_packsswb (code
, ins
->sreg1
, ins
->sreg2
);
4945 s390x_packssdw (code
, ins
->sreg1
, ins
->sreg2
);
4948 s390x_packuswb (code
, ins
->sreg1
, ins
->sreg2
);
4951 s390x_packusdw (code
, ins
->sreg1
, ins
->sreg2
);
4954 case OP_PADDB_SAT_UN
:
4955 s390x_paddusb (code
, ins
->sreg1
, ins
->sreg2
);
4957 case OP_PSUBB_SAT_UN
:
4958 s390x_psubusb (code
, ins
->sreg1
, ins
->sreg2
);
4960 case OP_PADDW_SAT_UN
:
4961 s390x_paddusw (code
, ins
->sreg1
, ins
->sreg2
);
4963 case OP_PSUBW_SAT_UN
:
4964 s390x_psubusw (code
, ins
->sreg1
, ins
->sreg2
);
4968 s390x_paddsb (code
, ins
->sreg1
, ins
->sreg2
);
4971 s390x_psubsb (code
, ins
->sreg1
, ins
->sreg2
);
4974 s390x_paddsw (code
, ins
->sreg1
, ins
->sreg2
);
4977 s390x_psubsw (code
, ins
->sreg1
, ins
->sreg2
);
4981 s390x_pmullw (code
, ins
->sreg1
, ins
->sreg2
);
4984 s390x_pmulld (code
, ins
->sreg1
, ins
->sreg2
);
4987 s390x_pmuludq (code
, ins
->sreg1
, ins
->sreg2
);
4989 case OP_PMULW_HIGH_UN
:
4990 s390x_pmulhuw (code
, ins
->sreg1
, ins
->sreg2
);
4993 s390x_pmulhw (code
, ins
->sreg1
, ins
->sreg2
);
4997 s390x_psrlw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5000 s390x_psrlw (code
, ins
->dreg
, ins
->sreg2
);
5004 s390x_psraw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5007 s390x_psraw (code
, ins
->dreg
, ins
->sreg2
);
5011 s390x_psllw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5014 s390x_psllw (code
, ins
->dreg
, ins
->sreg2
);
5018 s390x_psrld_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5021 s390x_psrld (code
, ins
->dreg
, ins
->sreg2
);
5025 s390x_psrad_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5028 s390x_psrad (code
, ins
->dreg
, ins
->sreg2
);
5032 s390x_pslld_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5035 s390x_pslld (code
, ins
->dreg
, ins
->sreg2
);
5039 s390x_psrlq_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5042 s390x_psrlq (code
, ins
->dreg
, ins
->sreg2
);
5045 /*TODO: This is appart of the sse spec but not added
5047 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5050 s390x_psraq (code, ins->dreg, ins->sreg2);
5055 s390x_psllq_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5058 s390x_psllq (code
, ins
->dreg
, ins
->sreg2
);
5061 s390x_cvtdq2pd (code
, ins
->dreg
, ins
->sreg1
);
5064 s390x_cvtdq2ps (code
, ins
->dreg
, ins
->sreg1
);
5067 s390x_cvtpd2dq (code
, ins
->dreg
, ins
->sreg1
);
5070 s390x_cvtpd2ps (code
, ins
->dreg
, ins
->sreg1
);
5073 s390x_cvtps2dq (code
, ins
->dreg
, ins
->sreg1
);
5076 s390x_cvtps2pd (code
, ins
->dreg
, ins
->sreg1
);
5079 s390x_cvttpd2dq (code
, ins
->dreg
, ins
->sreg1
);
5082 s390x_cvttps2dq (code
, ins
->dreg
, ins
->sreg1
);
5086 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5089 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5093 amd64_movhlps (code
, MONO_ARCH_FP_SCRATCH_REG
, ins
->sreg1
);
5094 amd64_movd_reg_xreg_size (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
, 8);
5096 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 8);
5101 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5103 amd64_shift_reg_imm (code
, X86_SHR
, ins
->dreg
, ins
->inst_c0
* 8);
5104 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, ins
->opcode
== OP_EXTRACT_I1
, FALSE
);
5108 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5110 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5111 s390x_pextrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5112 amd64_widen_reg_size (code
, ins
->dreg
, ins
->dreg
, ins
->opcode
== OP_EXTRACT_I2
, TRUE
, 4);
5116 amd64_movhlps (code
, ins
->dreg
, ins
->sreg1
);
5118 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5121 s390x_pinsrw_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5123 case OP_EXTRACTX_U2
:
5124 s390x_pextrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5126 case OP_INSERTX_U1_SLOW
:
5127 /*sreg1 is the extracted ireg (scratch)
5128 /sreg2 is the to be inserted ireg (scratch)
5129 /dreg is the xreg to receive the value*/
5131 /*clear the bits from the extracted word*/
5132 amd64_alu_reg_imm (code
, X86_AND
, ins
->sreg1
, ins
->inst_c0
& 1 ? 0x00FF : 0xFF00);
5133 /*shift the value to insert if needed*/
5134 if (ins
->inst_c0
& 1)
5135 amd64_shift_reg_imm_size (code
, X86_SHL
, ins
->sreg2
, 8, 4);
5136 /*join them together*/
5137 amd64_alu (code
, X86_OR
, ins
->sreg1
, ins
->sreg2
);
5138 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
/ 2);
5140 case OP_INSERTX_I4_SLOW
:
5141 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_c0
* 2);
5142 amd64_shift_reg_imm (code
, X86_SHR
, ins
->sreg2
, 16);
5143 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_c0
* 2 + 1);
5145 case OP_INSERTX_I8_SLOW
:
5146 amd64_movd_xreg_reg_size(code
, MONO_ARCH_FP_SCRATCH_REG
, ins
->sreg2
, 8);
5148 amd64_movlhps (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
);
5150 s390x_movsd (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
);
5153 case OP_INSERTX_R4_SLOW
:
5154 switch (ins
->inst_c0
) {
5157 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5159 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5162 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(1, 0, 2, 3));
5164 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5166 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5167 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(1, 0, 2, 3));
5170 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(2, 1, 0, 3));
5172 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5174 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5175 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(2, 1, 0, 3));
5178 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(3, 1, 2, 0));
5180 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5182 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5183 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(3, 1, 2, 0));
5187 case OP_INSERTX_R8_SLOW
:
5189 amd64_movlhps (code
, ins
->dreg
, ins
->sreg2
);
5191 s390x_movsd (code
, ins
->dreg
, ins
->sreg2
);
5193 case OP_STOREX_MEMBASE_REG
:
5194 case OP_STOREX_MEMBASE
:
5195 s390x_movups_membase_reg (code
, ins
->dreg
, ins
->inst_offset
, ins
->sreg1
);
5197 case OP_LOADX_MEMBASE
:
5198 s390x_movups_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5200 case OP_LOADX_ALIGNED_MEMBASE
:
5201 s390x_movaps_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5203 case OP_STOREX_ALIGNED_MEMBASE_REG
:
5204 s390x_movaps_membase_reg (code
, ins
->dreg
, ins
->inst_offset
, ins
->sreg1
);
5206 case OP_STOREX_NTA_MEMBASE_REG
:
5207 s390x_movntps_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5209 case OP_PREFETCH_MEMBASE
:
5210 s390x_prefetch_reg_membase (code
, ins
->backend
.arg_info
, ins
->sreg1
, ins
->inst_offset
);
5214 /*FIXME the peephole pass should have killed this*/
5215 if (ins
->dreg
!= ins
->sreg1
)
5216 s390x_movaps (code
, ins
->dreg
, ins
->sreg1
);
5219 s390x_pxor (code
, ins
->dreg
, ins
->dreg
);
5221 case OP_ICONV_TO_R4_RAW
:
5222 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5225 case OP_FCONV_TO_R8_X
:
5226 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5229 case OP_XCONV_R8_TO_I4
:
5230 s390x_cvttsd2si_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5231 switch (ins
->backend
.source_opcode
) {
5232 case OP_FCONV_TO_I1
:
5233 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, TRUE
, FALSE
);
5235 case OP_FCONV_TO_U1
:
5236 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, FALSE
, FALSE
);
5238 case OP_FCONV_TO_I2
:
5239 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, TRUE
, TRUE
);
5241 case OP_FCONV_TO_U2
:
5242 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, FALSE
, TRUE
);
5248 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, 0);
5249 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, 1);
5250 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5253 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5254 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5257 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 8);
5258 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0x44);
5262 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5264 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5265 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->dreg
);
5267 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5270 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5271 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0x44);
5275 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins
->opcode
), __FUNCTION__
);
5276 g_assert_not_reached ();
5279 if ((cfg
->opt
& MONO_OPT_BRANCH
) && ((code
- cfg
->native_code
- offset
) > max_len
)) {
5280 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5281 mono_inst_name (ins
->opcode
), max_len
, code
- cfg
->native_code
- offset
);
5282 g_assert_not_reached ();
5286 set_code_cursor (cfg
, code
);
5289 /*========================= End of Function ========================*/
5291 /*------------------------------------------------------------------*/
5293 /* Name - mono_arch_register_lowlevel_calls */
5295 /* Function - Register routines to help with --trace operation. */
5297 /*------------------------------------------------------------------*/
5300 mono_arch_register_lowlevel_calls (void)
5304 /*========================= End of Function ========================*/
5306 /*------------------------------------------------------------------*/
5308 /* Name - mono_arch_patch_code */
5310 /* Function - Process the patch data created during the */
5311 /* instruction build process. This resolves jumps, */
5312 /* calls, variables etc. */
5314 /*------------------------------------------------------------------*/
5317 mono_arch_patch_code (MonoCompile
*cfg
, MonoMethod
*method
, MonoDomain
*domain
,
5318 guint8
*code
, MonoJumpInfo
*ji
, gboolean run_cctors
,
5321 MonoJumpInfo
*patch_info
;
5325 for (patch_info
= ji
; patch_info
; patch_info
= patch_info
->next
) {
5326 unsigned char *ip
= patch_info
->ip
.i
+ code
;
5327 gconstpointer target
= NULL
;
5329 target
= mono_resolve_patch_target (method
, domain
, code
,
5330 patch_info
, run_cctors
, error
);
5331 return_if_nok (error
);
5333 switch (patch_info
->type
) {
5334 case MONO_PATCH_INFO_IP
:
5335 case MONO_PATCH_INFO_LDSTR
:
5336 case MONO_PATCH_INFO_TYPE_FROM_HANDLE
:
5337 case MONO_PATCH_INFO_LDTOKEN
:
5338 case MONO_PATCH_INFO_EXC
:
5339 s390_patch_addr (ip
, (guint64
) target
);
5341 case MONO_PATCH_INFO_JIT_ICALL
: //temporary
5343 case MONO_PATCH_INFO_TRAMPOLINE_FUNC_ADDR
:
5344 case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR
:
5345 case MONO_PATCH_INFO_METHOD
:
5346 case MONO_PATCH_INFO_JIT_ICALL_ID
:
5347 case MONO_PATCH_INFO_JIT_ICALL_ADDR
:
5348 case MONO_PATCH_INFO_RGCTX_FETCH
:
5349 case MONO_PATCH_INFO_ABS
: {
5350 S390_EMIT_CALL (ip
, target
);
5353 case MONO_PATCH_INFO_SWITCH
:
5354 /*----------------------------------*/
5355 /* ip points at the basr r13,0/j +4 */
5356 /* instruction the vtable value */
5357 /* follows this (i.e. ip+6) */
5358 /*----------------------------------*/
5359 S390_EMIT_LOAD (ip
, target
);
5361 case MONO_PATCH_INFO_METHODCONST
:
5362 case MONO_PATCH_INFO_CLASS
:
5363 case MONO_PATCH_INFO_IMAGE
:
5364 case MONO_PATCH_INFO_FIELD
:
5365 case MONO_PATCH_INFO_IID
:
5366 case MONO_PATCH_INFO_EXC_NAME
:
5367 target
= S390_RELATIVE(target
, ip
);
5368 s390_patch_rel (ip
, (guint64
) target
);
5370 case MONO_PATCH_INFO_R4
:
5371 case MONO_PATCH_INFO_R8
:
5372 case MONO_PATCH_INFO_METHOD_REL
:
5373 g_assert_not_reached ();
5376 target
= S390_RELATIVE(target
, ip
);
5378 s390_patch_rel (ip
, (guint64
) target
);
5383 /*========================= End of Function ========================*/
5385 /*------------------------------------------------------------------*/
5387 /* Name - mono_arch_emit_prolog */
5389 /* Function - Create the instruction sequence for a function */
5392 /*------------------------------------------------------------------*/
5395 mono_arch_emit_prolog (MonoCompile
*cfg
)
5397 MonoMethod
*method
= cfg
->method
;
5399 MonoMethodSignature
*sig
;
5401 long alloc_size
, pos
, max_offset
, i
, cfa_offset
= 0;
5405 int argsClobbered
= 0,
5409 cfg
->code_size
= 512;
5411 if (method
->save_lmf
)
5412 cfg
->code_size
+= 200;
5414 cfg
->native_code
= code
= g_malloc (cfg
->code_size
);
5416 mono_emit_unwind_op_def_cfa (cfg
, code
, STK_BASE
, 0);
5417 emit_unwind_regs(cfg
, code
, s390_r6
, s390_r14
, S390_REG_SAVE_OFFSET
);
5418 s390_stmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5419 mono_emit_unwind_op_offset (cfg
, code
, s390_r14
, S390_RET_ADDR_OFFSET
);
5420 mini_gc_set_slot_type_from_cfa (cfg
, S390_RET_ADDR_OFFSET
, SLOT_NOREF
);
5421 if (cfg
->arch
.bkchain_reg
!= -1)
5422 s390_lgr (code
, cfg
->arch
.bkchain_reg
, STK_BASE
);
5424 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
5425 cfg
->used_int_regs
|= 1 << s390_r11
;
5428 if ((cfg
->arch
.used_fp_regs
& S390_FP_SAVE_MASK
) != 0) {
5429 for (int i
=8; i
<16; i
++) {
5430 if (cfg
->arch
.used_fp_regs
& (1 << i
))
5431 fpOffset
+= sizeof(double);
5433 fpOffset
= S390_ALIGN(fpOffset
, 16);
5435 cfg
->arch
.fpSize
= fpOffset
;
5437 alloc_size
= cfg
->stack_offset
+ fpOffset
;
5439 cfg
->stack_usage
= cfa_offset
= alloc_size
;
5440 s390_lgr (code
, s390_r11
, STK_BASE
);
5441 if (s390_is_imm16 (alloc_size
)) {
5442 s390_aghi (code
, STK_BASE
, -alloc_size
);
5443 } else if (s390_is_imm32 (alloc_size
)) {
5444 s390_agfi (code
, STK_BASE
, -alloc_size
);
5446 int stackSize
= alloc_size
;
5447 while (stackSize
> INT_MAX
) {
5448 s390_agfi (code
, STK_BASE
, -INT_MAX
);
5449 stackSize
-= INT_MAX
;
5451 s390_agfi (code
, STK_BASE
, -stackSize
);
5453 s390_stg (code
, s390_r11
, 0, STK_BASE
, 0);
5458 s390_lgr (code
, s390_r1
, s390_r11
);
5459 s390_aghi (code
, s390_r1
, -fpOffset
);
5460 for (int i
=8; i
<16; i
++) {
5461 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
5462 emit_unwind_regs(cfg
, code
, 16+i
, 16+i
, stkOffset
+fpOffset
);
5463 s390_std (code
, i
, 0, s390_r1
, stkOffset
);
5464 stkOffset
+= sizeof(double);
5469 mono_emit_unwind_op_def_cfa_offset (cfg
, code
, alloc_size
);
5471 if (cfg
->frame_reg
!= STK_BASE
)
5472 s390_lgr (code
, s390_r11
, STK_BASE
);
5474 mono_emit_unwind_op_def_cfa_reg (cfg
, code
, cfg
->frame_reg
);
5476 /* store runtime generic context */
5477 if (cfg
->rgctx_var
) {
5478 g_assert (cfg
->rgctx_var
->opcode
== OP_REGOFFSET
);
5480 s390_stg (code
, MONO_ARCH_RGCTX_REG
, 0,
5481 cfg
->rgctx_var
->inst_basereg
,
5482 cfg
->rgctx_var
->inst_offset
);
5485 /* compute max_offset in order to use short forward jumps
5486 * we always do it on s390 because the immediate displacement
5487 * for jumps is too small
5490 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
5492 bb
->max_offset
= max_offset
;
5494 MONO_BB_FOR_EACH_INS (bb
, ins
)
5495 max_offset
+= ins_get_size (ins
->opcode
);
5498 /* load arguments allocated to register from the stack */
5499 sig
= mono_method_signature_internal (method
);
5502 cinfo
= get_call_info (cfg
->mempool
, sig
);
5504 if (cinfo
->struct_ret
) {
5505 ArgInfo
*ainfo
= &cinfo
->ret
;
5506 inst
= cfg
->vret_addr
;
5507 inst
->backend
.size
= ainfo
->vtsize
;
5508 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5511 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
5512 ArgInfo
*ainfo
= cinfo
->args
+ i
;
5513 inst
= cfg
->args
[pos
];
5515 if (inst
->opcode
== OP_VTARG_ADDR
)
5516 inst
= inst
->inst_left
;
5518 if (inst
->opcode
== OP_REGVAR
) {
5519 if (ainfo
->regtype
== RegTypeGeneral
)
5520 s390_lgr (code
, inst
->dreg
, ainfo
->reg
);
5521 else if (ainfo
->regtype
== RegTypeFP
) {
5522 if (inst
->dreg
!= ainfo
->reg
) {
5523 s390_ldr (code
, inst
->dreg
, ainfo
->reg
);
5525 } else if (ainfo
->regtype
== RegTypeFPR4
) {
5527 s390_ledbr (code
, inst
->dreg
, ainfo
->reg
);
5528 } else if (ainfo
->regtype
== RegTypeBase
) {
5529 s390_lgr (code
, s390_r13
, STK_BASE
);
5530 s390_aghi (code
, s390_r13
, alloc_size
);
5531 s390_lg (code
, inst
->dreg
, 0, s390_r13
, ainfo
->offset
);
5533 g_assert_not_reached ();
5535 if (cfg
->verbose_level
> 2)
5536 g_print ("Argument %d assigned to register %s\n",
5537 pos
, mono_arch_regname (inst
->dreg
));
5539 if (ainfo
->regtype
== RegTypeGeneral
) {
5540 if (!((ainfo
->reg
>= 2) && (ainfo
->reg
<= 6)))
5541 g_assert_not_reached();
5542 switch (ainfo
->size
) {
5544 s390_stc (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5547 s390_sth (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5550 s390_st (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5553 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5556 } else if (ainfo
->regtype
== RegTypeBase
) {
5557 } else if (ainfo
->regtype
== RegTypeFP
) {
5558 s390_std (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5559 } else if (ainfo
->regtype
== RegTypeFPR4
) {
5560 s390_ste (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5561 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
5562 int doffset
= inst
->inst_offset
;
5564 if (ainfo
->reg
!= STK_BASE
)
5568 s390_lgr (code
, s390_r13
, STK_BASE
);
5569 s390_aghi (code
, s390_r13
, alloc_size
);
5572 size
= (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
5573 ? mono_class_native_size(mono_class_from_mono_type_internal (inst
->inst_vtype
), NULL
)
5578 if (ainfo
->reg
== STK_BASE
)
5579 s390_ic (code
, reg
, 0, s390_r13
, ainfo
->offset
+7);
5580 s390_stc (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5583 if (ainfo
->reg
== STK_BASE
)
5584 s390_lh (code
, reg
, 0, s390_r13
, ainfo
->offset
+6);
5585 s390_sth (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5588 if (ainfo
->reg
== STK_BASE
)
5589 s390_l (code
, reg
, 0, s390_r13
, ainfo
->offset
+4);
5590 s390_st (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5593 if (ainfo
->reg
== STK_BASE
)
5594 s390_lg (code
, reg
, 0, s390_r13
, ainfo
->offset
);
5595 s390_stg (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5598 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
5599 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5600 } else if (ainfo
->regtype
== RegTypeStructByAddrOnStack
) {
5602 g_assert_not_reached ();
5607 if (method
->save_lmf
) {
5608 /*---------------------------------------------------------------*/
5609 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5610 /*---------------------------------------------------------------*/
5611 lmfOffset
= alloc_size
- sizeof(MonoLMF
);
5613 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
5614 s390_aghi (code
, s390_r13
, lmfOffset
);
5616 /*---------------------------------------------------------------*/
5617 /* Preserve the parameter registers while we fix up the lmf */
5618 /*---------------------------------------------------------------*/
5619 s390_stmg (code
, s390_r2
, s390_r6
, s390_r13
,
5620 G_STRUCT_OFFSET(MonoLMF
, pregs
[0]));
5622 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[0]), SLOT_NOREF
);
5623 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[1]), SLOT_NOREF
);
5624 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[2]), SLOT_NOREF
);
5625 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[3]), SLOT_NOREF
);
5626 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[4]), SLOT_NOREF
);
5628 /*---------------------------------------------------------------*/
5629 /* On return from this call r2 have the address of the &lmf */
5630 /*---------------------------------------------------------------*/
5631 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5632 MONO_PATCH_INFO_JIT_ICALL_ID
,
5633 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr
));
5634 S390_CALL_TEMPLATE(code
, s390_r1
);
5636 /*---------------------------------------------------------------*/
5637 /* Set lmf.lmf_addr = jit_tls->lmf */
5638 /*---------------------------------------------------------------*/
5639 s390_stg (code
, s390_r2
, 0, s390_r13
,
5640 G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
5641 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, lmf_addr
), SLOT_NOREF
);
5643 /*---------------------------------------------------------------*/
5644 /* Get current lmf */
5645 /*---------------------------------------------------------------*/
5646 s390_lg (code
, s390_r0
, 0, s390_r2
, 0);
5648 /*---------------------------------------------------------------*/
5649 /* Set our lmf as the current lmf */
5650 /*---------------------------------------------------------------*/
5651 s390_stg (code
, s390_r13
, 0, s390_r2
, 0);
5653 /*---------------------------------------------------------------*/
5654 /* Have our lmf.previous_lmf point to the last lmf */
5655 /*---------------------------------------------------------------*/
5656 s390_stg (code
, s390_r0
, 0, s390_r13
,
5657 G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
5658 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, previous_lmf
), SLOT_NOREF
);
5660 /*---------------------------------------------------------------*/
5661 /* save method info */
5662 /*---------------------------------------------------------------*/
5663 S390_SET (code
, s390_r1
, method
);
5664 s390_stg (code
, s390_r1
, 0, s390_r13
,
5665 G_STRUCT_OFFSET(MonoLMF
, method
));
5666 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, method
), SLOT_NOREF
);
5668 /*---------------------------------------------------------------*/
5669 /* save the current IP */
5670 /*---------------------------------------------------------------*/
5671 s390_stg (code
, STK_BASE
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, ebp
));
5672 s390_basr (code
, s390_r1
, 0);
5673 s390_stg (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, eip
));
5674 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, ebp
), SLOT_NOREF
);
5675 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, eip
), SLOT_NOREF
);
5677 /*---------------------------------------------------------------*/
5678 /* Save general and floating point registers */
5679 /*---------------------------------------------------------------*/
5680 s390_stmg (code
, s390_r2
, s390_r12
, s390_r13
,
5681 G_STRUCT_OFFSET(MonoLMF
, gregs
[2]));
5682 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[0]), SLOT_NOREF
);
5683 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[1]), SLOT_NOREF
);
5684 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[2]), SLOT_NOREF
);
5685 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[3]), SLOT_NOREF
);
5686 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[4]), SLOT_NOREF
);
5687 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[5]), SLOT_NOREF
);
5688 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[6]), SLOT_NOREF
);
5689 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[7]), SLOT_NOREF
);
5690 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[8]), SLOT_NOREF
);
5691 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[9]), SLOT_NOREF
);
5692 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[10]), SLOT_NOREF
);
5694 fpOffset
= lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, fregs
[0]);
5695 for (i
= 0; i
< 16; i
++) {
5696 s390_std (code
, i
, 0, s390_r13
,
5697 G_STRUCT_OFFSET(MonoLMF
, fregs
[i
]));
5698 mini_gc_set_slot_type_from_fp (cfg
, fpOffset
, SLOT_NOREF
);
5699 fpOffset
+= sizeof(double);
5702 /*---------------------------------------------------------------*/
5703 /* Restore the parameter registers now that we've set up the lmf */
5704 /*---------------------------------------------------------------*/
5705 s390_lmg (code
, s390_r2
, s390_r6
, s390_r13
,
5706 G_STRUCT_OFFSET(MonoLMF
, pregs
[0]));
5709 if (cfg
->method
->save_lmf
)
5710 argsClobbered
= TRUE
;
5713 * Optimize the common case of the first bblock making a call with the same
5714 * arguments as the method. This works because the arguments are still in their
5715 * original argument registers.
5717 if (!argsClobbered
) {
5718 MonoBasicBlock
*first_bb
= cfg
->bb_entry
;
5720 int filter
= FILTER_IL_SEQ_POINT
;
5722 next
= mono_bb_first_inst (first_bb
, filter
);
5723 if (!next
&& first_bb
->next_bb
) {
5724 first_bb
= first_bb
->next_bb
;
5725 next
= mono_bb_first_inst (first_bb
, filter
);
5728 if (first_bb
->in_count
> 1)
5731 for (i
= 0; next
&& i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
5732 ArgInfo
*ainfo
= cinfo
->args
+ i
;
5733 gboolean match
= FALSE
;
5735 inst
= cfg
->args
[i
];
5736 if (inst
->opcode
!= OP_REGVAR
) {
5737 switch (ainfo
->regtype
) {
5738 case RegTypeGeneral
: {
5739 if (((next
->opcode
== OP_LOAD_MEMBASE
) ||
5740 (next
->opcode
== OP_LOADI4_MEMBASE
)) &&
5741 next
->inst_basereg
== inst
->inst_basereg
&&
5742 next
->inst_offset
== inst
->inst_offset
) {
5743 if (next
->dreg
== ainfo
->reg
) {
5747 next
->opcode
= OP_MOVE
;
5748 next
->sreg1
= ainfo
->reg
;
5749 /* Only continue if the instruction doesn't change argument regs */
5750 if (next
->dreg
== ainfo
->reg
)
5760 /* Argument allocated to (non-volatile) register */
5761 switch (ainfo
->regtype
) {
5762 case RegTypeGeneral
:
5763 if (next
->opcode
== OP_MOVE
&&
5764 next
->sreg1
== inst
->dreg
&&
5765 next
->dreg
== ainfo
->reg
) {
5776 next
= mono_inst_next (next
, filter
);
5783 set_code_cursor (cfg
, code
);
5788 /*========================= End of Function ========================*/
5790 /*------------------------------------------------------------------*/
5792 /* Name - mono_arch_emit_epilog */
5794 /* Function - Emit the instructions for a function epilog. */
5796 /*------------------------------------------------------------------*/
5799 mono_arch_emit_epilog (MonoCompile
*cfg
)
5801 MonoMethod
*method
= cfg
->method
;
5803 int max_epilog_size
= 96;
5806 if (cfg
->method
->save_lmf
)
5807 max_epilog_size
+= 128;
5809 code
= realloc_code (cfg
, max_epilog_size
);
5811 if (method
->save_lmf
)
5812 restoreLMF(code
, cfg
->frame_reg
, cfg
->stack_usage
);
5814 code
= backUpStackPtr(cfg
, code
);
5816 if (cfg
->arch
.fpSize
!= 0) {
5817 fpOffset
= -cfg
->arch
.fpSize
;
5818 for (int i
=8; i
<16; i
++) {
5819 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
5820 s390_ldy (code
, i
, 0, STK_BASE
, fpOffset
);
5821 fpOffset
+= sizeof(double);
5826 s390_lmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5827 s390_br (code
, s390_r14
);
5829 set_code_cursor (cfg
, code
);
5833 /*========================= End of Function ========================*/
5835 /*------------------------------------------------------------------*/
5837 /* Name - mono_arch_emit_exceptions */
5839 /* Function - Emit the blocks to handle exception conditions. */
5841 /*------------------------------------------------------------------*/
5844 mono_arch_emit_exceptions (MonoCompile
*cfg
)
5846 MonoJumpInfo
*patch_info
;
5852 MonoClass
*exc_classes
[MAX_EXC
];
5853 guint8
*exc_throw_start
[MAX_EXC
];
5855 for (patch_info
= cfg
->patch_info
;
5857 patch_info
= patch_info
->next
) {
5858 if (patch_info
->type
== MONO_PATCH_INFO_EXC
)
5862 code_size
= exc_count
* 48;
5864 code
= realloc_code (cfg
, code_size
);
5866 /*---------------------------------------------------------------------*/
5867 /* Add code to raise exceptions */
5868 /*---------------------------------------------------------------------*/
5869 for (patch_info
= cfg
->patch_info
; patch_info
; patch_info
= patch_info
->next
) {
5870 switch (patch_info
->type
) {
5871 case MONO_PATCH_INFO_EXC
: {
5872 guint8
*ip
= patch_info
->ip
.i
+ cfg
->native_code
;
5873 MonoClass
*exc_class
;
5876 /*-----------------------------------------------------*/
5877 /* Patch the branch in epilog to come here */
5878 /*-----------------------------------------------------*/
5879 s390_patch_rel (ip
+ 2, (guint64
) S390_RELATIVE(code
,ip
));
5881 exc_class
= mono_class_load_from_name (mono_defaults
.corlib
,
5883 patch_info
->data
.name
);
5884 throw_ip
= patch_info
->ip
.i
;
5886 for (iExc
= 0; iExc
< nThrows
; ++iExc
)
5887 if (exc_classes
[iExc
] == exc_class
)
5890 if (iExc
< nThrows
) {
5891 s390_jcl (code
, S390_CC_UN
,
5892 (guint64
) exc_throw_start
[iExc
]);
5893 patch_info
->type
= MONO_PATCH_INFO_NONE
;
5896 if (nThrows
< MAX_EXC
) {
5897 exc_classes
[nThrows
] = exc_class
;
5898 exc_throw_start
[nThrows
] = code
;
5901 /*---------------------------------------------*/
5902 /* Patch the parameter passed to the handler */
5903 /*---------------------------------------------*/
5904 S390_SET (code
, s390_r2
, m_class_get_type_token (exc_class
));
5905 /*---------------------------------------------*/
5906 /* Load return address & parameter register */
5907 /*---------------------------------------------*/
5908 s390_larl (code
, s390_r14
, (guint64
)S390_RELATIVE((patch_info
->ip
.i
+
5909 cfg
->native_code
+ 8), code
));
5910 /*---------------------------------------------*/
5911 /* Reuse the current patch to set the jump */
5912 /*---------------------------------------------*/
5913 patch_info
->type
= MONO_PATCH_INFO_JIT_ICALL_ID
;
5914 patch_info
->data
.jit_icall_id
= MONO_JIT_ICALL_mono_arch_throw_corlib_exception
;
5915 patch_info
->ip
.i
= code
- cfg
->native_code
;
5916 S390_BR_TEMPLATE (code
, s390_r1
);
5925 set_code_cursor (cfg
, code
);
5928 /*========================= End of Function ========================*/
5930 /*------------------------------------------------------------------*/
5932 /* Name - mono_arch_finish_init */
5934 /* Function - Setup the JIT's Thread Level Specific Data. */
5936 /*------------------------------------------------------------------*/
5939 mono_arch_finish_init (void)
5943 /*========================= End of Function ========================*/
5945 /*------------------------------------------------------------------*/
5947 /* Name - mono_arch_free_jit_tls_data */
5949 /* Function - Free tls data. */
5951 /*------------------------------------------------------------------*/
5954 mono_arch_free_jit_tls_data (MonoJitTlsData
*tls
)
5958 /*========================= End of Function ========================*/
5960 /*------------------------------------------------------------------*/
5962 /* Name - mono_arch_emit_inst_for_method */
5964 /*------------------------------------------------------------------*/
5967 mono_arch_emit_inst_for_method (MonoCompile
*cfg
, MonoMethod
*cmethod
, MonoMethodSignature
*fsig
, MonoInst
**args
)
5972 /*========================= End of Function ========================*/
5974 /*------------------------------------------------------------------*/
5976 /* Name - mono_arch_decompose_opts */
5978 /* Function - Decompose opcode into a System z opcode. */
5980 /*------------------------------------------------------------------*/
5983 mono_arch_decompose_opts (MonoCompile
*cfg
, MonoInst
*ins
)
5986 * Have to rename these to avoid being decomposed normally, since the normal
5987 * decomposition does not work on S390.
5989 switch (ins
->opcode
) {
5991 ins
->opcode
= OP_S390_ISUB_OVF
;
5993 case OP_ISUB_OVF_UN
:
5994 ins
->opcode
= OP_S390_ISUB_OVF_UN
;
5997 ins
->opcode
= OP_S390_IADD_OVF
;
5999 case OP_IADD_OVF_UN
:
6000 ins
->opcode
= OP_S390_IADD_OVF_UN
;
6003 ins
->opcode
= OP_S390_LADD_OVF
;
6005 case OP_LADD_OVF_UN
:
6006 ins
->opcode
= OP_S390_LADD_OVF_UN
;
6009 ins
->opcode
= OP_S390_LSUB_OVF
;
6011 case OP_LSUB_OVF_UN
:
6012 ins
->opcode
= OP_S390_LSUB_OVF_UN
;
6019 /*========================= End of Function ========================*/
6021 /*------------------------------------------------------------------*/
6023 /* Name - mono_arch_regalloc_cost */
6025 /* Function - Determine the cost, in the number of memory */
6026 /* references, of the action of allocating the var- */
6027 /* iable VMV into a register during global register */
6030 /* Returns - Cost */
6032 /*------------------------------------------------------------------*/
6035 mono_arch_regalloc_cost (MonoCompile
*cfg
, MonoMethodVar
*vmv
)
6041 /*========================= End of Function ========================*/
6043 /*------------------------------------------------------------------*/
6045 /* Name - mono_arch_flush_register_windows */
6051 /*------------------------------------------------------------------*/
6054 mono_arch_flush_register_windows (void)
6058 /*========================= End of Function ========================*/
6060 /*------------------------------------------------------------------*/
6062 /* Name - mono_arch_is_inst_imm */
6064 /* Function - Determine if operand qualifies as an immediate */
6065 /* value. For s390 this is a value -32768-32768 */
6067 /* Returns - True|False - is [not] immediate value. */
6069 /*------------------------------------------------------------------*/
6072 mono_arch_is_inst_imm (int opcode
, int imm_opcode
, gint64 imm
)
6074 return s390_is_imm32 (imm
);
6077 /*========================= End of Function ========================*/
6079 /*------------------------------------------------------------------*/
6081 /* Name - mono_arch_get_patch_offset */
6083 /* Function - Dummy entry point until s390x supports aot. */
6085 /* Returns - Offset for patch. */
6087 /*------------------------------------------------------------------*/
6090 mono_arch_get_patch_offset (guint8
*code
)
6095 /*========================= End of Function ========================*/
6097 /*------------------------------------------------------------------*/
6099 /* Name - mono_arch_context_get_int_reg. */
6103 /* Returns - Return a register from the context. */
6105 /*------------------------------------------------------------------*/
6108 mono_arch_context_get_int_reg (MonoContext
*ctx
, int reg
)
6110 return ctx
->uc_mcontext
.gregs
[reg
];
6113 /*========================= End of Function ========================*/
6115 /*------------------------------------------------------------------*/
6117 /* Name - mono_arch_context_set_int_reg. */
6119 /* Function - Set a value in a specified register. */
6121 /*------------------------------------------------------------------*/
6124 mono_arch_context_set_int_reg (MonoContext
*ctx
, int reg
, host_mgreg_t val
)
6126 ctx
->uc_mcontext
.gregs
[reg
] = val
;
6129 /*========================= End of Function ========================*/
6131 /*------------------------------------------------------------------*/
6133 /* Name - mono_arch_get_this_arg_from_call. */
6137 /*------------------------------------------------------------------*/
6140 mono_arch_get_this_arg_from_call (host_mgreg_t
*regs
, guint8
*code
)
6142 return (gpointer
) regs
[s390_r2
];
6145 /*========================= End of Function ========================*/
6147 /*------------------------------------------------------------------*/
6149 /* Name - get_delegate_invoke_impl. */
6153 /*------------------------------------------------------------------*/
6156 get_delegate_invoke_impl (MonoTrampInfo
**info
, gboolean has_target
, guint32 param_count
, gboolean aot
)
6158 guint8
*code
, *start
;
6163 start
= code
= mono_global_codeman_reserve (size
);
6165 /* Replace the this argument with the target */
6166 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
6167 s390_lg (code
, s390_r2
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, target
));
6168 s390_br (code
, s390_r1
);
6169 g_assert ((code
- start
) <= size
);
6171 mono_arch_flush_icache (start
, size
);
6172 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6176 size
= 32 + param_count
* 8;
6177 start
= code
= mono_global_codeman_reserve (size
);
6179 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
6180 /* slide down the arguments */
6181 for (i
= 0; i
< param_count
; ++i
) {
6182 s390_lgr (code
, (s390_r2
+ i
), (s390_r2
+ i
+ 1));
6184 s390_br (code
, s390_r1
);
6186 g_assert ((code
- start
) <= size
);
6188 mono_arch_flush_icache (start
, size
);
6189 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6193 *info
= mono_tramp_info_create ("delegate_invoke_impl_has_target", start
, code
- start
, NULL
, NULL
);
6195 char *name
= g_strdup_printf ("delegate_invoke_impl_target_%d", param_count
);
6196 *info
= mono_tramp_info_create (name
, start
, code
- start
, NULL
, NULL
);
6203 /*========================= End of Function ========================*/
6205 /*------------------------------------------------------------------*/
6207 /* Name - mono_arch_get_delegate_invoke_impls. */
6211 /*------------------------------------------------------------------*/
6214 mono_arch_get_delegate_invoke_impls (void)
6217 MonoTrampInfo
*info
;
6220 get_delegate_invoke_impl (&info
, TRUE
, 0, TRUE
);
6221 res
= g_slist_prepend (res
, info
);
6223 for (i
= 0; i
<= MAX_ARCH_DELEGATE_PARAMS
; ++i
) {
6224 get_delegate_invoke_impl (&info
, FALSE
, i
, TRUE
);
6225 res
= g_slist_prepend (res
, info
);
6231 /*========================= End of Function ========================*/
6233 /*------------------------------------------------------------------*/
6235 /* Name - mono_arch_get_delegate_invoke_impl. */
6239 /*------------------------------------------------------------------*/
6242 mono_arch_get_delegate_invoke_impl (MonoMethodSignature
*sig
, gboolean has_target
)
6244 guint8
*code
, *start
;
6246 /* FIXME: Support more cases */
6247 if (MONO_TYPE_ISSTRUCT (sig
->ret
))
6251 static guint8
* cached
= NULL
;
6256 if (mono_ee_features
.use_aot_trampolines
) {
6257 start
= mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6259 MonoTrampInfo
*info
;
6260 start
= get_delegate_invoke_impl (&info
, TRUE
, 0, FALSE
);
6261 mono_tramp_info_register (info
, NULL
);
6264 mono_memory_barrier ();
6268 static guint8
* cache
[MAX_ARCH_DELEGATE_PARAMS
+ 1] = {NULL
};
6271 if (sig
->param_count
> MAX_ARCH_DELEGATE_PARAMS
)
6273 for (i
= 0; i
< sig
->param_count
; ++i
)
6274 if (!mono_is_regsize_var (sig
->params
[i
]))
6278 code
= cache
[sig
->param_count
];
6282 if (mono_ee_features
.use_aot_trampolines
) {
6283 char *name
= g_strdup_printf ("delegate_invoke_impl_target_%d", sig
->param_count
);
6284 start
= mono_aot_get_trampoline (name
);
6287 MonoTrampInfo
*info
;
6288 start
= get_delegate_invoke_impl (&info
, FALSE
, sig
->param_count
, FALSE
);
6289 mono_tramp_info_register (info
, NULL
);
6292 mono_memory_barrier ();
6294 cache
[sig
->param_count
] = start
;
6299 /*========================= End of Function ========================*/
6301 /*------------------------------------------------------------------*/
6303 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6307 /*------------------------------------------------------------------*/
6310 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature
*sig
, MonoMethod
*method
,
6311 int offset
, gboolean load_imt_reg
)
6313 guint8
*code
, *start
;
6316 start
= code
= mono_global_codeman_reserve (size
);
6319 * Replace the "this" argument with the target
6321 s390_lgr (code
, s390_r1
, s390_r2
);
6322 s390_lg (code
, s390_r2
, 0, s390_r1
, MONO_STRUCT_OFFSET(MonoDelegate
, target
));
6325 * Load the IMT register, if needed
6328 s390_lg (code
, MONO_ARCH_IMT_REG
, 0, s390_r1
, MONO_STRUCT_OFFSET(MonoDelegate
, method
));
6334 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET(MonoObject
, vtable
));
6336 s390_agfi(code
, s390_r1
, offset
);
6338 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6339 s390_br (code
, s390_r1
);
6341 mono_arch_flush_icache (start
, code
- start
);
6342 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6347 /*========================= End of Function ========================*/
6349 /*------------------------------------------------------------------*/
6351 /* Name - mono_arch_build_imt_trampoline. */
6355 /*------------------------------------------------------------------*/
6358 mono_arch_build_imt_trampoline (MonoVTable
*vtable
, MonoDomain
*domain
,
6359 MonoIMTCheckItem
**imt_entries
, int count
,
6360 gpointer fail_tramp
)
6364 guchar
*code
, *start
;
6367 for (i
= 0; i
< count
; ++i
) {
6368 MonoIMTCheckItem
*item
= imt_entries
[i
];
6369 if (item
->is_equals
) {
6370 if (item
->check_target_idx
) {
6371 if (!item
->compare_done
)
6372 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
6373 if (item
->has_target_code
)
6374 item
->chunk_size
+= BR_SIZE
+ JUMP_SIZE
+ LOADCON_SIZE
;
6376 item
->chunk_size
+= BR_SIZE
+ JUMP_SIZE
+ LOADCON_SIZE
+
6380 item
->chunk_size
+= CMP_SIZE
+ 2 * BR_SIZE
+ JUMP_SIZE
+
6382 if (!item
->has_target_code
)
6383 item
->chunk_size
+= LOAD_SIZE
;
6385 item
->chunk_size
+= LOADCON_SIZE
+ LOAD_SIZE
+ BR_SIZE
;
6386 #if ENABLE_WRONG_METHOD_CHECK
6387 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
6392 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
6393 imt_entries
[item
->check_target_idx
]->compare_done
= TRUE
;
6395 size
+= item
->chunk_size
;
6399 code
= mono_method_alloc_generic_virtual_trampoline (domain
, size
);
6401 code
= mono_domain_code_reserve (domain
, size
);
6405 for (i
= 0; i
< count
; ++i
) {
6406 MonoIMTCheckItem
*item
= imt_entries
[i
];
6407 item
->code_target
= (guint8
*) code
;
6408 if (item
->is_equals
) {
6409 if (item
->check_target_idx
) {
6410 if (!item
->compare_done
) {
6411 S390_SET (code
, s390_r0
, item
->key
);
6412 s390_cgr (code
, s390_r0
, MONO_ARCH_IMT_REG
);
6414 item
->jmp_code
= (guint8
*) code
;
6415 s390_jcl (code
, S390_CC_NE
, 0);
6417 if (item
->has_target_code
) {
6418 S390_SET (code
, s390_r1
, item
->value
.target_code
);
6420 S390_SET (code
, s390_r1
, (&(vtable
->vtable
[item
->value
.vtable_slot
])));
6421 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6423 s390_br (code
, s390_r1
);
6428 S390_SET (code
, s390_r0
, item
->key
);
6429 s390_cgr (code
, s390_r0
, MONO_ARCH_IMT_REG
);
6430 item
->jmp_code
= (guint8
*) code
;
6431 s390_jcl (code
, S390_CC_NE
, 0);
6432 if (item
->has_target_code
) {
6433 S390_SET (code
, s390_r1
, item
->value
.target_code
);
6436 S390_SET (code
, s390_r1
,
6437 (&(vtable
->vtable
[item
->value
.vtable_slot
])));
6438 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6440 s390_br (code
, s390_r1
);
6441 target
= (gint64
) S390_RELATIVE(code
, item
->jmp_code
);
6442 s390_patch_rel(item
->jmp_code
+2, target
);
6443 S390_SET (code
, s390_r1
, fail_tramp
);
6444 s390_br (code
, s390_r1
);
6445 item
->jmp_code
= NULL
;
6447 /* enable the commented code to assert on wrong method */
6448 #if ENABLE_WRONG_METHOD_CHECK
6449 g_assert_not_reached ();
6451 S390_SET (code
, s390_r1
, (&(vtable
->vtable
[item
->value
.vtable_slot
])));
6452 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6453 s390_br (code
, s390_r1
);
6457 S390_SET (code
, s390_r0
, item
->key
);
6458 s390_cgr (code
, MONO_ARCH_IMT_REG
, s390_r0
);
6459 item
->jmp_code
= (guint8
*) code
;
6460 s390_jcl (code
, S390_CC_GE
, 0);
6464 * patch the branches to get to the target items
6466 for (i
= 0; i
< count
; ++i
) {
6467 MonoIMTCheckItem
*item
= imt_entries
[i
];
6468 if (item
->jmp_code
) {
6469 if (item
->check_target_idx
) {
6471 offset
= (gint64
) S390_RELATIVE(imt_entries
[item
->check_target_idx
]->code_target
,
6473 s390_patch_rel ((guchar
*) item
->jmp_code
+ 2, (guint64
) offset
);
6478 mono_arch_flush_icache ((guint8
*)start
, (code
- start
));
6479 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE
, NULL
));
6482 UnlockedAdd (&mono_stats
.imt_trampolines_size
, code
- start
);
6484 g_assert (code
- start
<= size
);
6486 snprintf(trampName
, sizeof(trampName
), "%d_imt_trampoline", domain
->domain_id
);
6487 mono_tramp_info_register (mono_tramp_info_create (trampName
, start
, code
- start
, NULL
, NULL
), domain
);
6492 /*========================= End of Function ========================*/
6494 /*------------------------------------------------------------------*/
6496 /* Name - mono_arch_find_imt_method. */
6498 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6499 /* found in the save area. */
6501 /*------------------------------------------------------------------*/
6504 mono_arch_find_imt_method (host_mgreg_t
*regs
, guint8
*code
)
6506 return ((MonoMethod
*) regs
[MONO_ARCH_IMT_REG
]);
6509 /*========================= End of Function ========================*/
6511 /*------------------------------------------------------------------*/
6513 /* Name - mono_arch_find_static_call_vtable */
6515 /* Function - Find the static call vtable. */
6517 /*------------------------------------------------------------------*/
6520 mono_arch_find_static_call_vtable (host_mgreg_t
*regs
, guint8
*code
)
6522 return (MonoVTable
*)(gsize
) regs
[MONO_ARCH_RGCTX_REG
];
6525 /*========================= End of Function ========================*/
6527 /*------------------------------------------------------------------*/
6529 /* Name - mono_arch_get_cie_program */
6531 /* Function - Find the static call vtable. */
6533 /*------------------------------------------------------------------*/
6536 mono_arch_get_cie_program (void)
6540 mono_add_unwind_op_def_cfa (l
, 0, 0, STK_BASE
, 0);
6545 /*========================= End of Function ========================*/
6547 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6549 /*------------------------------------------------------------------*/
6551 /* Name - mono_arch_set_breakpoint. */
6553 /* Function - Set a breakpoint at the native code corresponding */
6554 /* to JI at NATIVE_OFFSET. The location should */
6555 /* contain code emitted by OP_SEQ_POINT. */
6557 /*------------------------------------------------------------------*/
6560 mono_arch_set_breakpoint (MonoJitInfo
*ji
, guint8
*ip
)
6564 breakpointCode
.pTrigger
= bp_trigger_page
;
6565 memcpy(code
, (void *) &breakpointCode
, BREAKPOINT_SIZE
);
6566 code
+= BREAKPOINT_SIZE
;
6569 /*========================= End of Function ========================*/
6571 /*------------------------------------------------------------------*/
6573 /* Name - mono_arch_clear_breakpoint. */
6575 /* Function - Clear the breakpoint at IP. */
6577 /*------------------------------------------------------------------*/
6580 mono_arch_clear_breakpoint (MonoJitInfo
*ji
, guint8
*ip
)
6585 for (i
= 0; i
< (BREAKPOINT_SIZE
/ S390X_NOP_SIZE
); i
++)
6589 /*========================= End of Function ========================*/
6591 /*------------------------------------------------------------------*/
6593 /* Name - mono_arch_is_breakpoint_event. */
6597 /*------------------------------------------------------------------*/
6600 mono_arch_is_breakpoint_event (void *info
, void *sigctx
)
6602 siginfo_t
* sinfo
= (siginfo_t
*) info
;
6605 * Sometimes the address is off by 4
6607 if (sinfo
->si_addr
>= bp_trigger_page
&& (guint8
*)sinfo
->si_addr
<= (guint8
*)bp_trigger_page
+ 128)
6613 /*========================= End of Function ========================*/
6615 /*------------------------------------------------------------------*/
6617 /* Name - mono_arch_skip_breakpoint. */
6619 /* Function - Modify the CTX so the IP is placed after the */
6620 /* breakpoint instruction, so when we resume, the */
6621 /* instruction is not executed again. */
6623 /*------------------------------------------------------------------*/
6626 mono_arch_skip_breakpoint (MonoContext
*ctx
, MonoJitInfo
*ji
)
6628 MONO_CONTEXT_SET_IP (ctx
, ((guint8
*)MONO_CONTEXT_GET_IP (ctx
) + sizeof(RXY_Format
)));
6631 /*========================= End of Function ========================*/
6633 /*------------------------------------------------------------------*/
6635 /* Name - mono_arch_start_single_stepping. */
6637 /* Function - Start single stepping. */
6639 /*------------------------------------------------------------------*/
6642 mono_arch_start_single_stepping (void)
6644 mono_mprotect (ss_trigger_page
, mono_pagesize (), 0);
6647 /*========================= End of Function ========================*/
6649 /*------------------------------------------------------------------*/
6651 /* Name - mono_arch_stop_single_stepping. */
6653 /* Function - Stop single stepping. */
6655 /*------------------------------------------------------------------*/
6658 mono_arch_stop_single_stepping (void)
6660 mono_mprotect (ss_trigger_page
, mono_pagesize (), MONO_MMAP_READ
);
6663 /*========================= End of Function ========================*/
6665 /*------------------------------------------------------------------*/
6667 /* Name - mono_arch_is_single_step_event. */
6669 /* Function - Return whether the machine state in sigctx cor- */
6670 /* responds to a single step event. */
6672 /*------------------------------------------------------------------*/
6675 mono_arch_is_single_step_event (void *info
, void *sigctx
)
6677 siginfo_t
* sinfo
= (siginfo_t
*) info
;
6680 * Sometimes the address is off by 4
6682 if (sinfo
->si_addr
>= ss_trigger_page
&& (guint8
*)sinfo
->si_addr
<= (guint8
*)ss_trigger_page
+ 128)
6688 /*========================= End of Function ========================*/
6690 /*------------------------------------------------------------------*/
6692 /* Name - mono_arch_skip_single_step. */
6694 /* Function - Modify the ctx so the IP is placed after the */
6695 /* single step trigger instruction, so that the */
6696 /* instruction is not executed again. */
6698 /*------------------------------------------------------------------*/
6701 mono_arch_skip_single_step (MonoContext
*ctx
)
6703 MONO_CONTEXT_SET_IP (ctx
, (guint8
*)MONO_CONTEXT_GET_IP (ctx
) + BREAKPOINT_SIZE
);
6706 /*========================= End of Function ========================*/
6708 /*------------------------------------------------------------------*/
6710 /* Name - mono_arch_create_seq_point_info. */
6712 /* Function - Return a pointer to a data struction which is */
6713 /* used by the sequence point implementation in */
6716 /*------------------------------------------------------------------*/
6719 mono_arch_get_seq_point_info (MonoDomain
*domain
, guint8
*code
)
6725 /*========================= End of Function ========================*/
6729 /*------------------------------------------------------------------*/
6731 /* Name - mono_arch_cpu_enumerate_simd_versions. */
6733 /* Function - If this CPU supports vector operations then it */
6734 /* supports the equivalent of SSE1-4. */
6736 /*------------------------------------------------------------------*/
6739 mono_arch_cpu_enumerate_simd_versions (void)
6741 guint32 sseOpts
= 0;
6743 if (mono_hwcap_s390x_has_vec
)
6744 sseOpts
= (SIMD_VERSION_SSE1
| SIMD_VERSION_SSE2
|
6745 SIMD_VERSION_SSE3
| SIMD_VERSION_SSSE3
|
6746 SIMD_VERSION_SSE41
| SIMD_VERSION_SSE42
|
6747 SIMD_VERSION_SSE4a
);
6752 /*========================= End of Function ========================*/
6754 /*------------------------------------------------------------------*/
6756 /* Name - mono_arch_opcode_supported. */
6758 /* Function - Check if a given op code is supported. */
6760 /*------------------------------------------------------------------*/
6763 mono_arch_opcode_supported (int opcode
)
6766 case OP_ATOMIC_ADD_I4
:
6767 case OP_ATOMIC_ADD_I8
:
6768 case OP_ATOMIC_EXCHANGE_I4
:
6769 case OP_ATOMIC_EXCHANGE_I8
:
6776 /*========================= End of Function ========================*/
6778 /*------------------------------------------------------------------*/
6780 /* Name - mono_arch_tailcall_supported. */
6782 /* Function - Check if a tailcall is supported. */
6784 /*------------------------------------------------------------------*/
6789 mono_arch_tailcall_supported (MonoCompile
*cfg
, MonoMethodSignature
*caller_sig
, MonoMethodSignature
*callee_sig
, gboolean virtual_
)
6791 g_assert (caller_sig
);
6792 g_assert (callee_sig
);
6794 CallInfo
*caller_info
= get_call_info (NULL
, caller_sig
);
6795 CallInfo
*callee_info
= get_call_info (NULL
, callee_sig
);
6797 gboolean res
= IS_SUPPORTED_TAILCALL (callee_info
->stack_usage
<= caller_info
->stack_usage
)
6798 && IS_SUPPORTED_TAILCALL (callee_info
->struct_ret
== caller_info
->struct_ret
)
6799 && IS_SUPPORTED_TAILCALL (memcmp (&callee_info
->ret
, &caller_info
->ret
, sizeof (caller_info
->ret
)) == 0);
6801 // valuetypes passed semantic-byvalue ABI-byref are often to a local.
6802 // FIXME ABIs vary as to if this local is in the parameter area or not,
6803 // so this check might not be needed.
6804 ArgInfo
const * const ainfo
= callee_info
->args
+ callee_sig
->hasthis
;
6805 for (int i
= 0; res
&& i
< callee_sig
->param_count
; ++i
) {
6806 res
= IS_SUPPORTED_TAILCALL (ainfo
[i
].regtype
!= RegTypeStructByAddr
)
6807 && IS_SUPPORTED_TAILCALL (ainfo
[i
].regtype
!= RegTypeStructByAddrOnStack
);
6810 g_free (caller_info
);
6811 g_free (callee_info
);
6818 /*========================= End of Function ========================*/