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 /*========================= End of Defines =========================*/
312 /*------------------------------------------------------------------*/
313 /* I n c l u d e s */
314 /*------------------------------------------------------------------*/
318 #include <sys/types.h>
321 #include <mono/metadata/abi-details.h>
322 #include <mono/metadata/appdomain.h>
323 #include <mono/metadata/debug-helpers.h>
324 #include <mono/metadata/profiler-private.h>
325 #include <mono/utils/mono-error.h>
326 #include <mono/utils/mono-error-internals.h>
327 #include <mono/utils/mono-math.h>
328 #include <mono/utils/mono-mmap.h>
329 #include <mono/utils/mono-hwcap.h>
330 #include <mono/utils/mono-threads.h>
331 #include <mono/utils/unlocked.h>
333 #include "mini-s390x.h"
334 #include "cpu-s390x.h"
335 #include "support-s390x.h"
336 #include "jit-icalls.h"
339 #include "aot-runtime.h"
340 #include "mini-runtime.h"
342 /*========================= End of Includes ========================*/
344 /*------------------------------------------------------------------*/
345 /* T y p e d e f s */
346 /*------------------------------------------------------------------*/
358 typedef struct InstList InstList
;
372 RegTypeStructByValInFP
,
374 RegTypeStructByAddrOnStack
378 gint32 offset
; /* offset from caller's stack */
379 gint32 offparm
; /* offset from callee's stack */
380 guint16 vtsize
; /* in param area */
383 guint32 size
; /* Size of structure used by RegTypeStructByVal */
384 gint32 type
; /* Data type of argument */
396 MonoMethodSignature
*sig
;
401 gint64 gr
[5]; /* R2-R6 */
402 gdouble fp
[3]; /* F0-F2 */
403 } __attribute__ ((__packed__
)) RegParm
;
411 } __attribute__ ((__packed__
)) breakpoint_t
;
413 /*========================= End of Typedefs ========================*/
415 /*------------------------------------------------------------------*/
416 /* P r o t o t y p e s */
417 /*------------------------------------------------------------------*/
419 static void indent (int);
420 static guint8
* backUpStackPtr(MonoCompile
*, guint8
*);
421 static void add_general (guint
*, size_data
*, ArgInfo
*);
422 static void add_stackParm (guint
*, size_data
*, ArgInfo
*, gint
);
423 static void add_float (guint
*, size_data
*, ArgInfo
*, gboolean
);
424 static CallInfo
* get_call_info (MonoMemPool
*, MonoMethodSignature
*);
425 static guchar
* emit_float_to_int (MonoCompile
*, guchar
*, int, int, int, gboolean
);
426 static __inline__
void emit_unwind_regs(MonoCompile
*, guint8
*, int, int, long);
427 static void compare_and_branch(MonoBasicBlock
*, MonoInst
*, int, gboolean
);
429 /*========================= End of Prototypes ======================*/
431 /*------------------------------------------------------------------*/
432 /* G l o b a l V a r i a b l e s */
433 /*------------------------------------------------------------------*/
435 __thread
int indent_level
= 0;
436 __thread
FILE *trFd
= NULL
;
440 * The code generated for sequence points reads from this location,
441 * which is made read-only when single stepping is enabled.
443 static gpointer ss_trigger_page
;
446 * Enabled breakpoints read from this trigger page
448 static gpointer bp_trigger_page
;
450 breakpoint_t breakpointCode
;
452 static const char * grNames
[] = {
453 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
454 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
455 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
459 static const char * fpNames
[] = {
460 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
461 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
462 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
466 static const char * vrNames
[] = {
467 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
468 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
469 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
470 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
473 /*====================== End of Global Variables ===================*/
475 /*------------------------------------------------------------------*/
477 /* Name - mono_arch_regname */
479 /* Function - Returns the name of the register specified by */
480 /* the input parameter. */
482 /*------------------------------------------------------------------*/
485 mono_arch_regname (int reg
)
487 if (reg
>= 0 && reg
< 16)
488 return grNames
[reg
];
493 /*========================= End of Function ========================*/
495 /*------------------------------------------------------------------*/
497 /* Name - mono_arch_fregname */
499 /* Function - Returns the name of the register specified by */
500 /* the input parameter. */
502 /*------------------------------------------------------------------*/
505 mono_arch_fregname (int reg
)
507 if (reg
>= 0 && reg
< 16)
508 return fpNames
[reg
];
513 /*========================= End of Function ========================*/
515 /*------------------------------------------------------------------*/
517 /* Name - mono_arch_xregname */
519 /* Function - Returns the name of the register specified by */
520 /* the input parameter. */
522 /*------------------------------------------------------------------*/
525 mono_arch_xregname (int reg
)
527 if (reg
< s390_VR_NREG
)
528 return vrNames
[reg
];
533 /*========================= End of Function ========================*/
535 /*------------------------------------------------------------------*/
537 /* Name - arch_get_argument_info */
539 /* Function - Gathers information on parameters such as size, */
540 /* alignment, and padding. arg_info should be large */
541 /* enough to hold param_count + 1 entries. */
543 /* Parameters - @csig - Method signature */
544 /* @param_count - No. of parameters to consider */
545 /* @arg_info - An array to store the result info */
547 /* Returns - Size of the activation frame */
549 /*------------------------------------------------------------------*/
552 mono_arch_get_argument_info (MonoMethodSignature
*csig
,
554 MonoJitArgumentInfo
*arg_info
)
556 int k
, frame_size
= 0;
557 int size
, align
, pad
;
560 if (MONO_TYPE_ISSTRUCT (csig
->ret
)) {
561 frame_size
+= sizeof (target_mgreg_t
);
565 arg_info
[0].offset
= offset
;
568 frame_size
+= sizeof (target_mgreg_t
);
572 arg_info
[0].size
= frame_size
;
574 for (k
= 0; k
< param_count
; k
++) {
577 size
= mono_type_native_stack_size (csig
->params
[k
], (guint32
*) &align
);
579 size
= mini_type_stack_size (csig
->params
[k
], &align
);
581 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
582 arg_info
[k
].pad
= pad
;
584 arg_info
[k
+ 1].pad
= 0;
585 arg_info
[k
+ 1].size
= size
;
587 arg_info
[k
+ 1].offset
= offset
;
591 align
= MONO_ARCH_FRAME_ALIGNMENT
;
592 frame_size
+= pad
= (align
- (frame_size
& (align
- 1))) & (align
- 1);
593 arg_info
[k
].pad
= pad
;
598 /*========================= End of Function ========================*/
600 /*------------------------------------------------------------------*/
602 /* Name - emit_unwind_regs. */
604 /* Function - Emit unwind information for a range of registers. */
606 /*------------------------------------------------------------------*/
608 static void __inline__
609 emit_unwind_regs(MonoCompile
*cfg
, guint8
*code
, int start
, int end
, long offset
)
613 for (i
= start
; i
< end
; i
++) {
614 mono_emit_unwind_op_offset (cfg
, code
, i
, offset
);
615 mini_gc_set_slot_type_from_cfa (cfg
, offset
, SLOT_NOREF
);
616 offset
+= sizeof(gulong
);
620 /*========================= End of Function ========================*/
622 /*------------------------------------------------------------------*/
624 /* Name - retFitsInReg. */
626 /* Function - Determines if a value can be returned in one or */
629 /*------------------------------------------------------------------*/
632 retFitsInReg(guint32 size
)
647 /*========================= End of Function ========================*/
649 /*------------------------------------------------------------------*/
651 /* Name - backStackPtr. */
653 /* Function - Restore Stack Pointer to previous frame. */
655 /*------------------------------------------------------------------*/
658 backUpStackPtr(MonoCompile
*cfg
, guint8
*code
)
660 int stackSize
= cfg
->stack_usage
;
662 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
663 s390_lg (code
, STK_BASE
, 0, STK_BASE
, 0);
665 if (cfg
->frame_reg
!= STK_BASE
)
666 s390_lgr (code
, STK_BASE
, cfg
->frame_reg
);
668 if (s390_is_imm16 (stackSize
)) {
669 s390_aghi (code
, STK_BASE
, stackSize
);
671 while (stackSize
> 32767) {
672 s390_aghi (code
, STK_BASE
, 32767);
675 s390_aghi (code
, STK_BASE
, stackSize
);
682 /*========================= End of Function ========================*/
684 /*------------------------------------------------------------------*/
688 /* Function - Perform nice indenting to current level */
690 /*------------------------------------------------------------------*/
696 indent_level
+= diff
;
698 fprintf (trFd
, "%p [%3d] ",(void *)pthread_self(),v
);
700 fprintf (trFd
, ". ");
703 indent_level
+= diff
;
706 /*========================= End of Function ========================*/
708 /*------------------------------------------------------------------*/
710 /* Name - cvtMonoType */
712 /* Function - Convert a mono-type to a string. */
714 /*------------------------------------------------------------------*/
717 cvtMonoType(MonoTypeEnum t
)
722 return "MONO_TYPE_END";
724 return "MONO_TYPE_VOID";
725 case MONO_TYPE_BOOLEAN
:
726 return "MONO_TYPE_BOOLEAN";
728 return "MONO_TYPE_CHAR";
730 return "MONO_TYPE_I1";
732 return "MONO_TYPE_U1";
734 return "MONO_TYPE_I2";
736 return "MONO_TYPE_U2";
738 return "MONO_TYPE_I4";
740 return "MONO_TYPE_U4";
742 return "MONO_TYPE_I8";
744 return "MONO_TYPE_U8";
746 return "MONO_TYPE_R4";
748 return "MONO_TYPE_R8";
749 case MONO_TYPE_STRING
:
750 return "MONO_TYPE_STRING";
752 return "MONO_TYPE_PTR";
753 case MONO_TYPE_BYREF
:
754 return "MONO_TYPE_BYREF";
755 case MONO_TYPE_VALUETYPE
:
756 return "MONO_TYPE_VALUETYPE";
757 case MONO_TYPE_CLASS
:
758 return "MONO_TYPE_CLASS";
760 return "MONO_TYPE_VAR";
761 case MONO_TYPE_ARRAY
:
762 return "MONO_TYPE_ARRAY";
763 case MONO_TYPE_GENERICINST
:
764 return "MONO_TYPE_GENERICINST";
765 case MONO_TYPE_TYPEDBYREF
:
766 return "MONO_TYPE_TYPEDBYREF";
768 return "MONO_TYPE_I";
770 return "MONO_TYPE_U";
771 case MONO_TYPE_FNPTR
:
772 return "MONO_TYPE_FNPTR";
773 case MONO_TYPE_OBJECT
:
774 return "MONO_TYPE_OBJECT";
775 case MONO_TYPE_SZARRAY
:
776 return "MONO_TYPE_SZARRAY";
778 return "MONO_TYPE_MVAR";
779 case MONO_TYPE_CMOD_REQD
:
780 return "MONO_TYPE_CMOD_REQD";
781 case MONO_TYPE_CMOD_OPT
:
782 return "MONO_TYPE_CMOD_OPT";
783 case MONO_TYPE_INTERNAL
:
784 return "MONO_TYPE_INTERNAL";
785 case MONO_TYPE_MODIFIER
:
786 return "MONO_TYPE_MODIFIER";
787 case MONO_TYPE_SENTINEL
:
788 return "MONO_TYPE_SENTINEL";
789 case MONO_TYPE_PINNED
:
790 return "MONO_TYPE_PINNED";
797 /*========================= End of Function ========================*/
799 /*------------------------------------------------------------------*/
801 /* Name - mono_arch_cpu_init */
803 /* Function - Perform CPU specific initialization to execute */
806 /*------------------------------------------------------------------*/
809 mono_arch_cpu_init (void)
813 /*========================= End of Function ========================*/
815 /*------------------------------------------------------------------*/
817 /* Name - mono_arch_init. */
819 /* Function - Initialize architecture specific code. */
821 /*------------------------------------------------------------------*/
824 mono_arch_init (void)
828 mono_set_partial_sharing_supported (FALSE
);
830 ss_trigger_page
= mono_valloc (NULL
, mono_pagesize (), MONO_MMAP_READ
, MONO_MEM_ACCOUNT_OTHER
);
831 bp_trigger_page
= mono_valloc (NULL
, mono_pagesize (), MONO_MMAP_READ
, MONO_MEM_ACCOUNT_OTHER
);
832 mono_mprotect (bp_trigger_page
, mono_pagesize (), 0);
834 code
= (guint8
*) &breakpointCode
;
835 s390_basr(code
, s390_r13
, 0);
838 s390_lg(code
, s390_r13
, 0, s390_r13
, 4);
839 s390_lg(code
, s390_r0
, 0, s390_r13
, 0);
842 /*========================= End of Function ========================*/
844 /*------------------------------------------------------------------*/
846 /* Name - mono_arch_cleanup. */
848 /* Function - Cleanup architecture specific code . */
850 /*------------------------------------------------------------------*/
853 mono_arch_cleanup (void)
856 mono_vfree (ss_trigger_page
, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER
);
858 mono_vfree (bp_trigger_page
, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER
);
861 /*========================= End of Function ========================*/
863 /*------------------------------------------------------------------*/
865 /* Name - mono_arch_have_fast_tls */
867 /* Function - Returns whether we use fast inlined thread local */
868 /* storage managed access, instead of falling back */
869 /* to native code. */
871 /*------------------------------------------------------------------*/
874 mono_arch_have_fast_tls (void)
879 /*========================= End of Function ========================*/
881 /*------------------------------------------------------------------*/
883 /* Name - mono_arch_cpu_optimizations */
885 /* Function - Returns the optimizations supported on this CPU */
887 /*------------------------------------------------------------------*/
890 mono_arch_cpu_optimizations (guint32
*exclude_mask
)
894 /*----------------------------------------------------------*/
895 /* No s390-specific optimizations yet */
896 /*----------------------------------------------------------*/
897 *exclude_mask
= MONO_OPT_LINEARS
;
901 /*========================= End of Function ========================*/
903 /*------------------------------------------------------------------*/
905 /* Name - mono_arch_get_allocatable_int_vars */
909 /*------------------------------------------------------------------*/
912 mono_arch_get_allocatable_int_vars (MonoCompile
*cfg
)
917 for (i
= 0; i
< cfg
->num_varinfo
; i
++) {
918 MonoInst
*ins
= cfg
->varinfo
[i
];
919 MonoMethodVar
*vmv
= MONO_VARINFO (cfg
, i
);
922 if (vmv
->range
.first_use
.abs_pos
>= vmv
->range
.last_use
.abs_pos
)
925 if (ins
->flags
& (MONO_INST_VOLATILE
|MONO_INST_INDIRECT
) ||
926 (ins
->opcode
!= OP_LOCAL
&& ins
->opcode
!= OP_ARG
))
929 /* we can only allocate 32 bit values */
930 if (mono_is_regsize_var(ins
->inst_vtype
)) {
931 g_assert (MONO_VARINFO (cfg
, i
)->reg
== -1);
932 g_assert (i
== vmv
->idx
);
933 vars
= mono_varlist_insert_sorted (cfg
, vars
, vmv
, FALSE
);
940 /*========================= End of Function ========================*/
942 /*------------------------------------------------------------------*/
944 /* Name - mono_arch_global_int_regs */
946 /* Function - Return a list of usable integer registers. */
948 /*------------------------------------------------------------------*/
951 mono_arch_get_global_int_regs (MonoCompile
*cfg
)
954 MonoMethodHeader
*header
;
957 header
= cfg
->header
;
958 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
959 cfg
->frame_reg
= s390_r11
;
962 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
964 for (i
= 8; i
< top
; ++i
) {
965 if ((cfg
->frame_reg
!= i
) &&
966 //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
967 (i
!= MONO_ARCH_IMT_REG
))
968 regs
= g_list_prepend (regs
, GUINT_TO_POINTER (i
));
974 /*========================= End of Function ========================*/
976 /*------------------------------------------------------------------*/
978 /* Name - mono_arch_flush_icache */
980 /* Function - Flush the CPU icache. */
982 /*------------------------------------------------------------------*/
985 mono_arch_flush_icache (guint8
*code
, gint size
)
989 /*========================= End of Function ========================*/
991 /*------------------------------------------------------------------*/
993 /* Name - add_general */
995 /* Function - Determine code and stack size incremements for a */
998 /*------------------------------------------------------------------*/
1001 add_general (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
)
1003 if (*gr
> S390_LAST_ARG_REG
) {
1004 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1005 ainfo
->offset
= sz
->stack_size
;
1006 ainfo
->reg
= STK_BASE
;
1007 ainfo
->regtype
= RegTypeBase
;
1008 sz
->stack_size
+= sizeof(long);
1009 sz
->local_size
+= sizeof(long);
1010 sz
->offStruct
+= sizeof(long);
1011 sz
->code_size
+= 12;
1019 /*========================= End of Function ========================*/
1021 /*------------------------------------------------------------------*/
1023 /* Name - add_stackParm */
1025 /* Function - Determine code and stack size incremements for a */
1028 /*------------------------------------------------------------------*/
1031 add_stackParm (guint
*gr
, size_data
*sz
, ArgInfo
*ainfo
, gint size
)
1033 if (*gr
> S390_LAST_ARG_REG
) {
1034 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1035 ainfo
->reg
= STK_BASE
;
1036 ainfo
->offset
= sz
->stack_size
;
1037 ainfo
->regtype
= RegTypeStructByAddrOnStack
;
1038 sz
->stack_size
+= sizeof (target_mgreg_t
);
1039 sz
->parm_size
+= sizeof(gpointer
);
1040 sz
->offStruct
+= sizeof(gpointer
);
1043 ainfo
->offset
= sz
->stack_size
;
1044 ainfo
->regtype
= RegTypeStructByAddr
;
1047 ainfo
->offparm
= sz
->offset
;
1048 sz
->offset
= S390_ALIGN(sz
->offset
+size
, sizeof(long));
1050 ainfo
->vtsize
= size
;
1051 sz
->parm_size
+= size
;
1054 /*========================= End of Function ========================*/
1056 /*------------------------------------------------------------------*/
1058 /* Name - add_float */
1060 /* Function - Determine code and stack size incremements for a */
1061 /* float parameter. */
1063 /*------------------------------------------------------------------*/
1066 add_float (guint
*fr
, size_data
*sz
, ArgInfo
*ainfo
, gboolean isDouble
)
1068 if ((*fr
) <= S390_LAST_FPARG_REG
) {
1070 ainfo
->regtype
= RegTypeFP
;
1072 ainfo
->regtype
= RegTypeFPR4
;
1078 ainfo
->offset
= sz
->stack_size
;
1079 ainfo
->reg
= STK_BASE
;
1081 sz
->stack_size
+= sizeof(double);
1082 sz
->local_size
+= sizeof(double);
1083 sz
->offStruct
+= sizeof(double);
1084 ainfo
->regtype
= RegTypeBase
;
1088 /*========================= End of Function ========================*/
1090 /*------------------------------------------------------------------*/
1092 /* Name - get_call_info */
1094 /* Function - Determine the amount of space required for code */
1095 /* and stack. In addition determine starting points */
1096 /* for stack-based parameters, and area for struct- */
1097 /* ures being returned on the stack. */
1099 /*------------------------------------------------------------------*/
1102 get_call_info (MonoMemPool
*mp
, MonoMethodSignature
*sig
)
1104 guint i
, fr
, gr
, size
, pstart
;
1105 int nParm
= sig
->hasthis
+ sig
->param_count
;
1107 guint32 simpleType
, align
;
1108 gboolean is_pinvoke
= sig
->pinvoke
;
1113 cinfo
= mono_mempool_alloc0 (mp
, sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1115 cinfo
= g_malloc0 (sizeof (CallInfo
) + sizeof (ArgInfo
) * nParm
);
1120 cinfo
->struct_ret
= 0;
1125 sz
->offStruct
= S390_MINIMAL_STACK_SIZE
;
1126 sz
->stack_size
= S390_MINIMAL_STACK_SIZE
;
1133 /*----------------------------------------------------------*/
1134 /* We determine the size of the return code/stack in case we*/
1135 /* need to reserve a register to be used to address a stack */
1136 /* area that the callee will use. */
1137 /*----------------------------------------------------------*/
1139 ret_type
= mini_get_underlying_type (sig
->ret
);
1140 simpleType
= ret_type
->type
;
1142 switch (simpleType
) {
1151 case MONO_TYPE_OBJECT
:
1153 case MONO_TYPE_FNPTR
:
1154 cinfo
->ret
.reg
= s390_r2
;
1159 cinfo
->ret
.reg
= s390_f0
;
1164 cinfo
->ret
.reg
= s390_r2
;
1167 case MONO_TYPE_GENERICINST
:
1168 if (!mono_type_generic_inst_is_valuetype (sig
->ret
)) {
1169 cinfo
->ret
.reg
= s390_r2
;
1174 case MONO_TYPE_VALUETYPE
: {
1175 MonoClass
*klass
= mono_class_from_mono_type_internal (sig
->ret
);
1176 if (m_class_is_enumtype (klass
)) {
1177 simpleType
= mono_class_enum_basetype_internal (klass
)->type
;
1180 size
= mini_type_stack_size_full (m_class_get_byval_arg (klass
), NULL
, sig
->pinvoke
);
1182 cinfo
->struct_ret
= 1;
1183 cinfo
->ret
.size
= size
;
1184 cinfo
->ret
.vtsize
= size
;
1187 case MONO_TYPE_TYPEDBYREF
:
1188 size
= MONO_ABI_SIZEOF (MonoTypedRef
);
1189 cinfo
->struct_ret
= 1;
1190 cinfo
->ret
.size
= size
;
1191 cinfo
->ret
.vtsize
= size
;
1193 case MONO_TYPE_VOID
:
1196 g_error ("Can't handle as return value 0x%x", sig
->ret
->type
);
1202 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1203 * the first argument, allowing 'this' to be always passed in the first arg reg.
1204 * Also do this if the first argument is a reference type, since virtual calls
1205 * are sometimes made using calli without sig->hasthis set, like in the delegate
1208 if (cinfo
->struct_ret
&& !is_pinvoke
&&
1210 (sig
->param_count
> 0 &&
1211 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig
->params
[0]))))) {
1213 cinfo
->args
[nParm
].size
= sizeof (target_mgreg_t
);
1214 add_general (&gr
, sz
, cinfo
->args
+ nParm
);
1216 cinfo
->args
[nParm
].size
= sizeof (target_mgreg_t
);
1217 add_general (&gr
, sz
, &cinfo
->args
[sig
->hasthis
+ nParm
]);
1221 cinfo
->vret_arg_index
= 1;
1222 cinfo
->ret
.reg
= gr
;
1227 cinfo
->args
[nParm
].size
= sizeof (target_mgreg_t
);
1228 add_general (&gr
, sz
, cinfo
->args
+ nParm
);
1232 if (cinfo
->struct_ret
) {
1233 cinfo
->ret
.reg
= gr
;
1238 if ((sig
->call_convention
== MONO_CALL_VARARG
) && (sig
->param_count
== 0)) {
1239 gr
= S390_LAST_ARG_REG
+ 1;
1240 fr
= S390_LAST_FPARG_REG
+ 1;
1242 /* Emit the signature cookie just before the implicit arguments */
1243 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1246 /*----------------------------------------------------------*/
1247 /* We determine the size of the parameter code and stack */
1248 /* requirements by checking the types and sizes of the */
1250 /*----------------------------------------------------------*/
1252 for (i
= pstart
; i
< sig
->param_count
; ++i
) {
1255 /*--------------------------------------------------*/
1256 /* Handle vararg type calls. All args are put on */
1258 /*--------------------------------------------------*/
1259 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1260 (i
== sig
->sentinelpos
)) {
1261 gr
= S390_LAST_ARG_REG
+ 1;
1262 fr
= S390_LAST_FPARG_REG
+ 1;
1263 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1266 if (sig
->params
[i
]->byref
) {
1267 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1268 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1273 ptype
= mini_get_underlying_type (sig
->params
[i
]);
1274 simpleType
= ptype
->type
;
1275 cinfo
->args
[nParm
].type
= simpleType
;
1276 switch (simpleType
) {
1279 cinfo
->args
[nParm
].size
= sizeof(char);
1280 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1285 cinfo
->args
[nParm
].size
= sizeof(short);
1286 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1291 cinfo
->args
[nParm
].size
= sizeof(int);
1292 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1298 case MONO_TYPE_FNPTR
:
1299 case MONO_TYPE_OBJECT
:
1300 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1301 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1306 cinfo
->args
[nParm
].size
= sizeof(long long);
1307 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1311 cinfo
->args
[nParm
].size
= sizeof(float);
1312 add_float (&fr
, sz
, cinfo
->args
+nParm
, FALSE
);
1316 cinfo
->args
[nParm
].size
= sizeof(double);
1317 add_float (&fr
, sz
, cinfo
->args
+nParm
, TRUE
);
1320 case MONO_TYPE_GENERICINST
:
1321 if (!mono_type_generic_inst_is_valuetype (ptype
)) {
1322 cinfo
->args
[nParm
].size
= sizeof(gpointer
);
1323 add_general (&gr
, sz
, cinfo
->args
+nParm
);
1328 case MONO_TYPE_VALUETYPE
: {
1329 MonoMarshalType
*info
;
1330 MonoClass
*klass
= mono_class_from_mono_type_internal (ptype
);
1333 size
= mono_class_native_size(klass
, NULL
);
1335 size
= mono_class_value_size(klass
, NULL
);
1337 if (simpleType
!= MONO_TYPE_GENERICINST
) {
1338 info
= mono_marshal_load_type_info(klass
);
1340 if ((info
->native_size
== sizeof(float)) &&
1341 (info
->num_fields
== 1) &&
1342 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R4
)) {
1343 cinfo
->args
[nParm
].size
= sizeof(float);
1344 add_float(&fr
, sz
, cinfo
->args
+nParm
, FALSE
);
1349 if ((info
->native_size
== sizeof(double)) &&
1350 (info
->num_fields
== 1) &&
1351 (info
->fields
[0].field
->type
->type
== MONO_TYPE_R8
)) {
1352 cinfo
->args
[nParm
].size
= sizeof(double);
1353 add_float(&fr
, sz
, cinfo
->args
+nParm
, TRUE
);
1359 cinfo
->args
[nParm
].vtsize
= 0;
1360 cinfo
->args
[nParm
].size
= 0;
1363 /*----------------------------------*/
1364 /* On S/390, structures of size 1, */
1365 /* 2, 4, and 8 bytes are passed in */
1366 /* (a) register(s). */
1367 /*----------------------------------*/
1373 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1374 cinfo
->args
[nParm
].size
= size
;
1375 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1377 sz
->local_size
+= sizeof(long);
1380 add_stackParm(&gr
, sz
, cinfo
->args
+nParm
, size
);
1385 case MONO_TYPE_TYPEDBYREF
: {
1386 int size
= MONO_ABI_SIZEOF (MonoTypedRef
);
1388 cinfo
->args
[nParm
].vtsize
= 0;
1389 cinfo
->args
[nParm
].size
= 0;
1392 /*----------------------------------*/
1393 /* On S/390, structures of size 1, */
1394 /* 2, 4, and 8 bytes are passed in */
1395 /* (a) register(s). */
1396 /*----------------------------------*/
1402 add_general(&gr
, sz
, cinfo
->args
+nParm
);
1403 cinfo
->args
[nParm
].size
= size
;
1404 cinfo
->args
[nParm
].regtype
= RegTypeStructByVal
;
1406 sz
->local_size
+= sizeof(long);
1409 add_stackParm(&gr
, sz
, cinfo
->args
+nParm
, size
);
1415 g_error ("Can't trampoline 0x%x", ptype
);
1419 /*----------------------------------------------------------*/
1420 /* Handle the case where there are no implicit arguments */
1421 /*----------------------------------------------------------*/
1422 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1425 (sig
->param_count
== sig
->sentinelpos
)) {
1426 gr
= S390_LAST_ARG_REG
+ 1;
1427 fr
= S390_LAST_FPARG_REG
+ 1;
1428 add_general (&gr
, sz
, &cinfo
->sigCookie
);
1431 /*----------------------------------------------------------*/
1432 /* If we are passing a structure back then if it won't be */
1433 /* in a register(s) then we make room at the end of the */
1434 /* parameters that may have been placed on the stack */
1435 /*----------------------------------------------------------*/
1436 if (cinfo
->struct_ret
) {
1437 cinfo
->ret
.offset
= sz
->stack_size
;
1438 switch (cinfo
->ret
.size
) {
1446 sz
->stack_size
+= S390_ALIGN(cinfo
->ret
.size
, align
);
1451 sz
->stack_size
= sz
->stack_size
+ sz
->local_size
+ sz
->parm_size
+
1453 sz
->stack_size
= S390_ALIGN(sz
->stack_size
, sizeof(long));
1458 /*========================= End of Function ========================*/
1460 /*------------------------------------------------------------------*/
1462 /* Name - mono_arch_allocate_vars */
1464 /* Function - Set var information according to the calling */
1465 /* convention for S/390. The local var stuff should */
1466 /* most likely be split in another method. */
1468 /* Parameter - @m - Compile unit. */
1470 /*------------------------------------------------------------------*/
1473 mono_arch_allocate_vars (MonoCompile
*cfg
)
1475 MonoMethodSignature
*sig
;
1476 MonoMethodHeader
*header
;
1479 int iParm
, iVar
, offset
, align
, size
, curinst
;
1480 int frame_reg
= STK_BASE
;
1483 header
= cfg
->header
;
1485 cfg
->flags
|= MONO_CFG_HAS_SPILLUP
;
1487 /*---------------------------------------------------------*/
1488 /* We use the frame register also for any method that has */
1489 /* filter clauses. This way, when the handlers are called, */
1490 /* the code will reference local variables using the frame */
1491 /* reg instead of the stack pointer: if we had to restore */
1492 /* the stack pointer, we'd corrupt the method frames that */
1493 /* are already on the stack (since filters get called */
1494 /* before stack unwinding happens) when the filter code */
1495 /* would call any method. */
1496 /*---------------------------------------------------------*/
1497 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
1498 frame_reg
= s390_r11
;
1500 cfg
->frame_reg
= frame_reg
;
1502 cfg
->arch
.bkchain_reg
= -1;
1504 if (frame_reg
!= STK_BASE
)
1505 cfg
->used_int_regs
|= (1LL << frame_reg
);
1507 sig
= mono_method_signature_internal (cfg
->method
);
1509 cinfo
= get_call_info (cfg
->mempool
, sig
);
1511 if (!cinfo
->struct_ret
) {
1512 switch (mini_get_underlying_type (sig
->ret
)->type
) {
1513 case MONO_TYPE_VOID
:
1516 cfg
->ret
->opcode
= OP_REGVAR
;
1517 cfg
->ret
->dreg
= s390_r2
;
1522 /*--------------------------------------------------------------*/
1523 /* local vars are at a positive offset from the stack pointer */
1524 /* also note that if the function uses alloca, we use s390_r11 */
1525 /* to point at the local variables. */
1526 /* add parameter area size for called functions */
1527 /*--------------------------------------------------------------*/
1528 if (cfg
->param_area
== 0)
1529 offset
= S390_MINIMAL_STACK_SIZE
;
1531 offset
= cfg
->param_area
;
1533 cfg
->sig_cookie
= 0;
1535 if (cinfo
->struct_ret
) {
1536 inst
= cfg
->vret_addr
;
1537 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1538 inst
->inst_offset
= offset
;
1539 inst
->opcode
= OP_REGOFFSET
;
1540 inst
->inst_basereg
= frame_reg
;
1541 offset
+= sizeof(gpointer
);
1542 if (G_UNLIKELY (cfg
->verbose_level
> 1)) {
1543 printf ("vret_addr =");
1544 mono_print_ins (cfg
->vret_addr
);
1549 inst
= cfg
->args
[0];
1550 if (inst
->opcode
!= OP_REGVAR
) {
1551 inst
->opcode
= OP_REGOFFSET
;
1552 inst
->inst_basereg
= frame_reg
;
1553 offset
= S390_ALIGN(offset
, sizeof(gpointer
));
1554 inst
->inst_offset
= offset
;
1555 offset
+= sizeof (target_mgreg_t
);
1562 eArg
= sig
->param_count
+ sArg
;
1564 if (sig
->call_convention
== MONO_CALL_VARARG
)
1565 cfg
->sig_cookie
+= S390_MINIMAL_STACK_SIZE
;
1567 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
1568 inst
= cfg
->args
[curinst
];
1569 if (inst
->opcode
!= OP_REGVAR
) {
1570 switch (cinfo
->args
[iParm
].regtype
) {
1571 case RegTypeStructByAddr
: {
1574 size
= sizeof (target_mgreg_t
);
1576 inst
->opcode
= OP_REGOFFSET
;
1577 inst
->inst_basereg
= frame_reg
;
1578 offset
= S390_ALIGN (offset
, sizeof (target_mgreg_t
));
1579 inst
->inst_offset
= offset
;
1581 /* Add a level of indirection */
1582 MONO_INST_NEW (cfg
, indir
, 0);
1584 inst
->opcode
= OP_VTARG_ADDR
;
1585 inst
->inst_left
= indir
;
1588 case RegTypeStructByAddrOnStack
: {
1591 size
= sizeof (target_mgreg_t
);
1593 /* Similar to the == STK_BASE case below */
1594 cfg
->arch
.bkchain_reg
= s390_r12
;
1595 cfg
->used_int_regs
|= 1 << cfg
->arch
.bkchain_reg
;
1597 inst
->opcode
= OP_REGOFFSET
;
1598 inst
->dreg
= mono_alloc_preg (cfg
);
1599 inst
->inst_basereg
= cfg
->arch
.bkchain_reg
;
1600 inst
->inst_offset
= cinfo
->args
[iParm
].offset
;
1602 /* Add a level of indirection */
1603 MONO_INST_NEW (cfg
, indir
, 0);
1605 inst
->opcode
= OP_VTARG_ADDR
;
1606 inst
->inst_left
= indir
;
1609 case RegTypeStructByVal
:
1610 size
= cinfo
->args
[iParm
].size
;
1611 offset
= S390_ALIGN(offset
, size
);
1612 inst
->opcode
= OP_REGOFFSET
;
1613 inst
->inst_basereg
= frame_reg
;
1614 inst
->inst_offset
= offset
;
1617 if (cinfo
->args
[iParm
].reg
== STK_BASE
) {
1619 * These arguments are in the previous frame, so we can't
1620 * compute their offset from the current frame pointer right
1621 * now, since cfg->stack_offset is not yet known, so dedicate a
1622 * register holding the previous frame pointer.
1624 cfg
->arch
.bkchain_reg
= s390_r12
;
1625 cfg
->used_int_regs
|= 1 << cfg
->arch
.bkchain_reg
;
1627 inst
->opcode
= OP_REGOFFSET
;
1628 inst
->inst_basereg
= cfg
->arch
.bkchain_reg
;
1629 size
= (cinfo
->args
[iParm
].size
< 8
1630 ? 8 - cinfo
->args
[iParm
].size
1632 inst
->inst_offset
= cinfo
->args
[iParm
].offset
+ size
;
1633 size
= sizeof (long);
1635 inst
->opcode
= OP_REGOFFSET
;
1636 inst
->inst_basereg
= frame_reg
;
1637 size
= (cinfo
->args
[iParm
].size
< 8
1640 offset
= S390_ALIGN(offset
, size
);
1641 if (cfg
->method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
)
1642 inst
->inst_offset
= offset
;
1644 inst
->inst_offset
= offset
+ (8 - size
);
1648 offset
+= MAX(size
, 8);
1653 cfg
->locals_min_stack_offset
= offset
;
1655 curinst
= cfg
->locals_start
;
1656 for (iVar
= curinst
; iVar
< cfg
->num_varinfo
; ++iVar
) {
1657 inst
= cfg
->varinfo
[iVar
];
1658 if ((inst
->flags
& MONO_INST_IS_DEAD
) ||
1659 (inst
->opcode
== OP_REGVAR
))
1662 /*--------------------------------------------------*/
1663 /* inst->backend.is_pinvoke indicates native sized */
1664 /* value types this is used by the pinvoke wrappers */
1665 /* when they call functions returning structure */
1666 /*--------------------------------------------------*/
1667 if (inst
->backend
.is_pinvoke
&& MONO_TYPE_ISSTRUCT (inst
->inst_vtype
))
1668 size
= mono_class_native_size (mono_class_from_mono_type_internal (inst
->inst_vtype
),
1669 (guint32
*) &align
);
1671 size
= mono_type_size (inst
->inst_vtype
, &align
);
1673 offset
= S390_ALIGN(offset
, align
);
1674 inst
->inst_offset
= offset
;
1675 inst
->opcode
= OP_REGOFFSET
;
1676 inst
->inst_basereg
= frame_reg
;
1678 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
1679 iVar
, inst
->inst_offset
, size
));
1682 cfg
->locals_max_stack_offset
= offset
;
1684 /*------------------------------------------------------*/
1685 /* Reserve space to save LMF and caller saved registers */
1686 /*------------------------------------------------------*/
1687 if (cfg
->method
->save_lmf
)
1688 offset
+= sizeof (MonoLMF
);
1690 /*------------------------------------------------------*/
1691 /* align the offset */
1692 /*------------------------------------------------------*/
1693 cfg
->stack_offset
= S390_ALIGN(offset
, S390_STACK_ALIGNMENT
);
1695 /*------------------------------------------------------*/
1696 /* Fix offsets for args whose value is in parent frame */
1697 /*------------------------------------------------------*/
1698 for (iParm
= sArg
; iParm
< eArg
; ++iParm
) {
1699 inst
= cfg
->args
[iParm
];
1701 if (inst
->opcode
== OP_S390_STKARG
) {
1702 inst
->opcode
= OP_REGOFFSET
;
1703 inst
->inst_offset
+= cfg
->stack_offset
;
1708 /*========================= End of Function ========================*/
1710 /*------------------------------------------------------------------*/
1712 /* Name - mono_arch_create_vars */
1714 /*------------------------------------------------------------------*/
1717 mono_arch_create_vars (MonoCompile
*cfg
)
1719 MonoMethodSignature
*sig
;
1722 sig
= mono_method_signature_internal (cfg
->method
);
1724 cinfo
= get_call_info (cfg
->mempool
, sig
);
1726 if (cinfo
->struct_ret
) {
1727 cfg
->vret_addr
= mono_compile_create_var (cfg
, mono_get_int_type (), OP_ARG
);
1728 if (G_UNLIKELY (cfg
->verbose_level
> 1)) {
1729 printf ("vret_addr = ");
1730 mono_print_ins (cfg
->vret_addr
);
1735 /*========================= End of Function ========================*/
1737 /*------------------------------------------------------------------*/
1739 /* Name - add_outarg_reg2. */
1741 /*------------------------------------------------------------------*/
1744 add_outarg_reg2 (MonoCompile
*cfg
, MonoCallInst
*call
, ArgStorage storage
, int reg
, MonoInst
*tree
)
1749 case RegTypeGeneral
:
1750 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
1751 ins
->dreg
= mono_alloc_ireg (cfg
);
1752 ins
->sreg1
= tree
->dreg
;
1753 MONO_ADD_INS (cfg
->cbb
, ins
);
1754 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, reg
, FALSE
);
1757 MONO_INST_NEW (cfg
, ins
, OP_FMOVE
);
1758 ins
->dreg
= mono_alloc_freg (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
, TRUE
);
1764 MONO_INST_NEW (cfg
, ins
, OP_S390_SETF4RET
);
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 g_assert_not_reached ();
1775 /*========================= End of Function ========================*/
1777 /*------------------------------------------------------------------*/
1779 /* Name - emit_sig_cookie. */
1781 /*------------------------------------------------------------------*/
1784 emit_sig_cookie (MonoCompile
*cfg
, MonoCallInst
*call
, CallInfo
*cinfo
)
1786 MonoMethodSignature
*tmpSig
;
1789 cfg
->disable_aot
= TRUE
;
1791 /*----------------------------------------------------------*/
1792 /* mono_ArgIterator_Setup assumes the signature cookie is */
1793 /* passed first and all the arguments which were before it */
1794 /* passed on the stack after the signature. So compensate */
1795 /* by passing a different signature. */
1796 /*----------------------------------------------------------*/
1797 tmpSig
= mono_metadata_signature_dup (call
->signature
);
1798 tmpSig
->param_count
-= call
->signature
->sentinelpos
;
1799 tmpSig
->sentinelpos
= 0;
1800 if (tmpSig
->param_count
> 0)
1801 memcpy (tmpSig
->params
,
1802 call
->signature
->params
+ call
->signature
->sentinelpos
,
1803 tmpSig
->param_count
* sizeof(MonoType
*));
1805 MONO_INST_NEW (cfg
, sig_arg
, OP_ICONST
);
1806 sig_arg
->dreg
= mono_alloc_ireg (cfg
);
1807 sig_arg
->inst_p0
= tmpSig
;
1808 MONO_ADD_INS (cfg
->cbb
, sig_arg
);
1810 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORE_MEMBASE_REG
, STK_BASE
,
1811 cinfo
->sigCookie
.offset
, sig_arg
->dreg
);
1814 /*========================= End of Function ========================*/
1816 /*------------------------------------------------------------------*/
1818 /* Name - mono_arch_emit_call */
1820 /*------------------------------------------------------------------*/
1823 mono_arch_emit_call (MonoCompile
*cfg
, MonoCallInst
*call
)
1826 MonoMethodSignature
*sig
;
1828 int i
, n
, lParamArea
;
1830 ArgInfo
*ainfo
= NULL
;
1833 sig
= call
->signature
;
1834 n
= sig
->param_count
+ sig
->hasthis
;
1835 DEBUG (g_print ("Call requires: %d parameters\n",n
));
1837 cinfo
= get_call_info (cfg
->mempool
, sig
);
1839 stackSize
= cinfo
->sz
.stack_size
+ cinfo
->sz
.local_size
+
1840 cinfo
->sz
.parm_size
+ cinfo
->sz
.offset
;
1841 call
->stack_usage
= MAX(stackSize
, call
->stack_usage
);
1842 lParamArea
= MAX((call
->stack_usage
-S390_MINIMAL_STACK_SIZE
-cinfo
->sz
.parm_size
), 0);
1843 cfg
->param_area
= MAX(((signed) cfg
->param_area
), lParamArea
);
1844 cfg
->flags
|= MONO_CFG_HAS_CALLS
;
1846 if (cinfo
->struct_ret
) {
1847 MONO_INST_NEW (cfg
, ins
, OP_MOVE
);
1848 ins
->sreg1
= call
->vret_var
->dreg
;
1849 ins
->dreg
= mono_alloc_preg (cfg
);
1850 MONO_ADD_INS (cfg
->cbb
, ins
);
1851 mono_call_inst_add_outarg_reg (cfg
, call
, ins
->dreg
, cinfo
->ret
.reg
, FALSE
);
1854 for (i
= 0; i
< n
; ++i
) {
1857 ainfo
= cinfo
->args
+ i
;
1858 if (i
>= sig
->hasthis
)
1859 t
= sig
->params
[i
- sig
->hasthis
];
1861 t
= mono_get_int_type ();
1862 t
= mini_get_underlying_type (t
);
1864 in
= call
->args
[i
];
1866 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1868 (i
== sig
->sentinelpos
)) {
1869 emit_sig_cookie (cfg
, call
, cinfo
);
1872 switch (ainfo
->regtype
) {
1873 case RegTypeGeneral
:
1874 add_outarg_reg2 (cfg
, call
, ainfo
->regtype
, ainfo
->reg
, in
);
1878 if (MONO_TYPE_ISSTRUCT (t
)) {
1879 /* Valuetype passed in one fp register */
1880 ainfo
->regtype
= RegTypeStructByValInFP
;
1883 add_outarg_reg2 (cfg
, call
, ainfo
->regtype
, ainfo
->reg
, in
);
1886 case RegTypeStructByVal
:
1887 case RegTypeStructByAddr
:
1888 case RegTypeStructByAddrOnStack
: {
1892 if (sig
->params
[i
- sig
->hasthis
]->type
== MONO_TYPE_TYPEDBYREF
) {
1893 size
= MONO_ABI_SIZEOF (MonoTypedRef
);
1894 align
= sizeof (target_mgreg_t
);
1898 size
= mono_type_native_stack_size (m_class_get_byval_arg (in
->klass
), &align
);
1901 * Other backends use mono_type_stack_size (), but that
1902 * aligns the size to 8, which is larger than the size of
1903 * the source, leading to reads of invalid memory if the
1904 * source is at the end of address space.
1906 size
= mono_class_value_size (in
->klass
, &align
);
1909 g_assert (in
->klass
);
1911 ainfo
->offparm
+= cinfo
->sz
.offStruct
;
1913 MONO_INST_NEW (cfg
, ins
, OP_OUTARG_VT
);
1914 ins
->sreg1
= in
->dreg
;
1915 ins
->klass
= in
->klass
;
1916 ins
->backend
.size
= ainfo
->size
;
1917 ins
->inst_p0
= call
;
1918 ins
->inst_p1
= mono_mempool_alloc (cfg
->mempool
, sizeof (ArgInfo
));
1919 memcpy (ins
->inst_p1
, ainfo
, sizeof (ArgInfo
));
1921 MONO_ADD_INS (cfg
->cbb
, ins
);
1926 if (!t
->byref
&& t
->type
== MONO_TYPE_R4
) {
1927 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORER4_MEMBASE_REG
,
1928 STK_BASE
, ainfo
->offset
+ 4,
1930 } else if (!t
->byref
&& (t
->type
== MONO_TYPE_R8
)) {
1931 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORER8_MEMBASE_REG
,
1932 STK_BASE
, ainfo
->offset
,
1935 MONO_INST_NEW (cfg
, ins
, OP_STORE_MEMBASE_REG
);
1936 ins
->inst_destbasereg
= STK_BASE
;
1937 ins
->inst_offset
= ainfo
->offset
;
1938 ins
->sreg1
= in
->dreg
;
1939 MONO_ADD_INS (cfg
->cbb
, ins
);
1943 g_assert_not_reached ();
1949 * Handle the case where there are no implicit arguments
1951 if ((sig
->call_convention
== MONO_CALL_VARARG
) &&
1953 (i
== sig
->sentinelpos
)) {
1954 emit_sig_cookie (cfg
, call
, cinfo
);
1957 if (cinfo
->struct_ret
) {
1960 MONO_INST_NEW (cfg
, vtarg
, OP_MOVE
);
1961 vtarg
->sreg1
= call
->vret_var
->dreg
;
1962 vtarg
->dreg
= mono_alloc_preg (cfg
);
1963 MONO_ADD_INS (cfg
->cbb
, vtarg
);
1965 mono_call_inst_add_outarg_reg (cfg
, call
, vtarg
->dreg
, cinfo
->struct_ret
, FALSE
);
1969 /*========================= End of Function ========================*/
1971 /*------------------------------------------------------------------*/
1973 /* Name - mono_arch_emit_outarg_vt */
1975 /*------------------------------------------------------------------*/
1978 mono_arch_emit_outarg_vt (MonoCompile
*cfg
, MonoInst
*ins
, MonoInst
*src
)
1980 MonoCallInst
*call
= (MonoCallInst
*)ins
->inst_p0
;
1981 ArgInfo
*ainfo
= (ArgInfo
*)ins
->inst_p1
;
1982 int size
= ins
->backend
.size
;
1984 if (ainfo
->regtype
== RegTypeStructByVal
) {
1986 arg->ins.sreg1 = ainfo->reg;
1987 arg->ins.opcode = OP_OUTARG_VT;
1988 arg->size = ainfo->size;
1989 arg->offset = ainfo->offset;
1990 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
1992 if (ainfo
->reg
!= STK_BASE
) {
1993 MONO_OUTPUT_VTR (cfg
, size
, ainfo
->reg
, src
->dreg
, 0);
1995 MONO_OUTPUT_VTS (cfg
, size
, ainfo
->reg
, ainfo
->offset
,
1998 } else if (ainfo
->regtype
== RegTypeStructByValInFP
) {
1999 int dreg
= mono_alloc_freg (cfg
);
2001 if (ainfo
->size
== 4) {
2002 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg
, OP_LOADR4_MEMBASE
, dreg
, src
->dreg
, 0);
2003 MONO_EMIT_NEW_UNALU (cfg
, OP_S390_SETF4RET
, dreg
, dreg
);
2005 g_assert (ainfo
->size
== 8);
2007 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg
, OP_LOADR8_MEMBASE
, dreg
, src
->dreg
, 0);
2010 mono_call_inst_add_outarg_reg (cfg
, call
, dreg
, ainfo
->reg
, TRUE
);
2013 MonoMethodHeader
*header
;
2014 MonoInst
*vtcopy
= mono_compile_create_var (cfg
, m_class_get_byval_arg (src
->klass
), OP_LOCAL
);
2016 int ovf_size
= ainfo
->vtsize
,
2020 /* FIXME: alignment? */
2021 if (call
->signature
->pinvoke
) {
2022 size
= mono_type_native_stack_size (m_class_get_byval_arg (src
->klass
), NULL
);
2023 vtcopy
->backend
.is_pinvoke
= 1;
2025 size
= mini_type_stack_size (m_class_get_byval_arg (src
->klass
), NULL
);
2028 g_assert (ovf_size
> 0);
2030 header
= mono_method_get_header_checked (cfg
->method
, error
);
2031 mono_error_assert_ok (error
); /* FIXME don't swallow the error */
2032 if ((cfg
->flags
& MONO_CFG_HAS_ALLOCA
) || header
->num_clauses
)
2037 EMIT_NEW_VARLOADA (cfg
, load
, vtcopy
, vtcopy
->inst_vtype
);
2038 mini_emit_memcpy (cfg
, load
->dreg
, 0, src
->dreg
, 0, size
, TARGET_SIZEOF_VOID_P
);
2040 if (ainfo
->reg
== STK_BASE
) {
2041 MONO_EMIT_NEW_STORE_MEMBASE (cfg
, OP_STORE_MEMBASE_REG
, srcReg
, ainfo
->offset
, load
->dreg
);
2043 if (cfg
->compute_gc_maps
) {
2046 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg
, def
, ainfo
->offset
, m_class_get_byval_arg (ins
->klass
));
2049 mono_call_inst_add_outarg_reg (cfg
, call
, load
->dreg
, ainfo
->reg
, FALSE
);
2053 /*========================= End of Function ========================*/
2055 /*------------------------------------------------------------------*/
2057 /* Name - mono_arch_emit_setret */
2059 /*------------------------------------------------------------------*/
2062 mono_arch_emit_setret (MonoCompile
*cfg
, MonoMethod
*method
, MonoInst
*val
)
2064 MonoType
*ret
= mini_get_underlying_type (mono_method_signature_internal (method
)->ret
);
2067 if (ret
->type
== MONO_TYPE_R4
) {
2068 MONO_EMIT_NEW_UNALU (cfg
, OP_S390_SETF4RET
, s390_f0
, val
->dreg
);
2070 } else if (ret
->type
== MONO_TYPE_R8
) {
2071 MONO_EMIT_NEW_UNALU (cfg
, OP_FMOVE
, s390_f0
, val
->dreg
);
2076 MONO_EMIT_NEW_UNALU (cfg
, OP_MOVE
, cfg
->ret
->dreg
, val
->dreg
);
2079 /*========================= End of Function ========================*/
2081 /*------------------------------------------------------------------*/
2083 /* Name - compare_and_branch */
2085 /* Function - Form a peephole pass at the code looking for */
2086 /* simple optimizations. */
2088 /*------------------------------------------------------------------*/
2091 compare_and_branch(MonoBasicBlock
*bb
, MonoInst
*ins
, int cc
, gboolean logical
)
2095 if (mono_hwcap_s390x_has_gie
) {
2096 last
= mono_inst_prev (ins
, FILTER_IL_SEQ_POINT
);
2097 ins
->sreg1
= last
->sreg1
;
2098 ins
->sreg2
= last
->sreg2
;
2100 switch(last
->opcode
) {
2103 ins
->opcode
= OP_S390_CLRJ
;
2105 ins
->opcode
= OP_S390_CRJ
;
2106 MONO_DELETE_INS(bb
, last
);
2111 ins
->opcode
= OP_S390_CLGRJ
;
2113 ins
->opcode
= OP_S390_CGRJ
;
2114 MONO_DELETE_INS(bb
, last
);
2116 case OP_ICOMPARE_IMM
:
2117 ins
->backend
.data
= (gpointer
) last
->inst_imm
;
2119 ins
->opcode
= OP_S390_CLIJ
;
2121 ins
->opcode
= OP_S390_CIJ
;
2122 MONO_DELETE_INS(bb
, last
);
2124 case OP_COMPARE_IMM
:
2125 case OP_LCOMPARE_IMM
:
2126 ins
->backend
.data
= (gpointer
) last
->inst_imm
;
2128 ins
->opcode
= OP_S390_CLGIJ
;
2130 ins
->opcode
= OP_S390_CGIJ
;
2131 MONO_DELETE_INS(bb
, last
);
2137 /*========================= End of Function ========================*/
2139 /*------------------------------------------------------------------*/
2141 /* Name - mono_arch_peephole_pass_1 */
2143 /* Function - Form a peephole pass at the code looking for */
2144 /* simple optimizations. */
2146 /*------------------------------------------------------------------*/
2149 mono_arch_peephole_pass_1 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2153 MONO_BB_FOR_EACH_INS_SAFE (bb
, n
, ins
) {
2154 switch (ins
->opcode
) {
2157 compare_and_branch(bb
, ins
, S390_CC_EQ
, FALSE
);
2161 compare_and_branch(bb
, ins
, S390_CC_NE
, TRUE
);
2165 compare_and_branch(bb
, ins
, S390_CC_LT
, FALSE
);
2169 compare_and_branch(bb
, ins
, S390_CC_LT
, TRUE
);
2173 compare_and_branch(bb
, ins
, S390_CC_GT
, FALSE
);
2177 compare_and_branch(bb
, ins
, S390_CC_GT
, TRUE
);
2181 compare_and_branch(bb
, ins
, S390_CC_GE
, FALSE
);
2185 compare_and_branch(bb
, ins
, S390_CC_GE
, TRUE
);
2189 compare_and_branch(bb
, ins
, S390_CC_LE
, FALSE
);
2193 compare_and_branch(bb
, ins
, S390_CC_LE
, TRUE
);
2197 // mono_peephole_ins (bb, ins);
2202 /*========================= End of Function ========================*/
2204 /*------------------------------------------------------------------*/
2206 /* Name - mono_arch_peephole_pass_2 */
2208 /* Function - Form a peephole pass at the code looking for */
2209 /* simple optimizations. */
2211 /*------------------------------------------------------------------*/
2214 mono_arch_peephole_pass_2 (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2216 MonoInst
*ins
, *n
, *last_ins
= NULL
;
2218 MONO_BB_FOR_EACH_INS_SAFE (bb
, n
, ins
) {
2219 switch (ins
->opcode
) {
2220 case OP_LOADU4_MEMBASE
:
2221 case OP_LOADI4_MEMBASE
:
2222 if (last_ins
&& (last_ins
->opcode
== OP_STOREI4_MEMBASE_REG
) &&
2223 ins
->inst_basereg
== last_ins
->inst_destbasereg
&&
2224 ins
->inst_offset
== last_ins
->inst_offset
) {
2225 ins
->opcode
= (ins
->opcode
== OP_LOADI4_MEMBASE
) ? OP_ICONV_TO_I4
: OP_ICONV_TO_U4
;
2226 ins
->sreg1
= last_ins
->sreg1
;
2230 mono_peephole_ins (bb
, ins
);
2234 /*========================= End of Function ========================*/
2236 /*------------------------------------------------------------------*/
2238 /* Name - mono_arch_lowering_pass. */
2240 /*------------------------------------------------------------------*/
2243 mono_arch_lowering_pass (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2245 MonoInst
*ins
, *next
;
2247 MONO_BB_FOR_EACH_INS_SAFE (bb
, next
, ins
) {
2248 switch (ins
->opcode
) {
2253 case OP_IDIV_UN_IMM
:
2254 case OP_IREM_UN_IMM
:
2259 case OP_LOCALLOC_IMM
:
2260 mono_decompose_op_imm (cfg
, bb
, ins
);
2263 if (!s390_is_imm16 (ins
->inst_imm
))
2264 /* This is created by the memcpy code which ignores is_inst_imm */
2265 mono_decompose_op_imm (cfg
, bb
, ins
);
2272 bb
->max_vreg
= cfg
->next_vreg
;
2275 /*========================= End of Function ========================*/
2277 /*------------------------------------------------------------------*/
2279 /* Name - emit_float_to_int */
2281 /* Function - Create instructions which will convert a floating */
2282 /* point value to integer. */
2284 /*------------------------------------------------------------------*/
2287 emit_float_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
2289 /* sreg is a float, dreg is an integer reg. */
2291 s390_cgebr (code
, dreg
, 5, sreg
);
2294 s390_ltgr (code
, dreg
, dreg
);
2296 s390_oill (code
, dreg
, 0x80);
2297 s390_lghi (code
, s390_r0
, 0xff);
2298 s390_ngr (code
, dreg
, s390_r0
);
2301 s390_ltgr (code
, dreg
, dreg
);
2303 s390_oill (code
, dreg
, 0x8000);
2304 s390_llill(code
, s390_r0
, 0xffff);
2305 s390_ngr (code
, dreg
, s390_r0
);
2310 S390_SET (code
, s390_r13
, 0x4f000000u
);
2311 s390_ldgr (code
, s390_f14
, s390_r13
);
2312 s390_ler (code
, s390_f15
, sreg
);
2313 s390_cebr (code
, s390_f15
, s390_f14
);
2314 s390_jl (code
, 0); CODEPTR (code
, o
[0]);
2315 S390_SET (code
, s390_r13
, 0x4f800000u
);
2316 s390_ldgr (code
, s390_f14
, s390_r13
);
2317 s390_sebr (code
, s390_f15
, s390_f14
);
2318 s390_cfebr (code
, dreg
, 7, s390_f15
);
2320 PTRSLOT (code
, o
[0]);
2321 s390_cfebr (code
, dreg
, 5, sreg
);
2324 s390_lghi (code
, s390_r0
, 0xff);
2325 s390_ngr (code
, dreg
, s390_r0
);
2328 s390_llill(code
, s390_r0
, 0xffff);
2329 s390_ngr (code
, dreg
, s390_r0
);
2336 /*========================= End of Function ========================*/
2338 /*------------------------------------------------------------------*/
2340 /* Name - emit_double_to_int */
2342 /* Function - Create instructions which will convert a floating */
2343 /* point value to integer. */
2345 /*------------------------------------------------------------------*/
2348 emit_double_to_int (MonoCompile
*cfg
, guchar
*code
, int dreg
, int sreg
, int size
, gboolean is_signed
)
2350 /* sreg is a float, dreg is an integer reg. */
2352 s390_cgdbr (code
, dreg
, 5, sreg
);
2355 s390_ltgr (code
, dreg
, dreg
);
2357 s390_oill (code
, dreg
, 0x80);
2358 s390_lghi (code
, s390_r0
, 0xff);
2359 s390_ngr (code
, dreg
, s390_r0
);
2362 s390_ltgr (code
, dreg
, dreg
);
2364 s390_oill (code
, dreg
, 0x8000);
2365 s390_llill(code
, s390_r0
, 0xffff);
2366 s390_ngr (code
, dreg
, s390_r0
);
2371 S390_SET (code
, s390_r13
, 0x41e0000000000000llu
);
2372 s390_ldgr (code
, s390_f14
, s390_r13
);
2373 s390_ldr (code
, s390_f15
, sreg
);
2374 s390_cdbr (code
, s390_f15
, s390_f14
);
2375 s390_jl (code
, 0); CODEPTR (code
, o
[0]);
2376 S390_SET (code
, s390_r13
, 0x41f0000000000000llu
);
2377 s390_ldgr (code
, s390_f14
, s390_r13
);
2378 s390_sdbr (code
, s390_f15
, s390_f14
);
2379 s390_cfdbr (code
, dreg
, 7, s390_f15
);
2381 PTRSLOT (code
, o
[0]);
2382 s390_cfdbr (code
, dreg
, 5, sreg
);
2385 s390_lghi (code
, s390_r0
, 0xff);
2386 s390_ngr (code
, dreg
, s390_r0
);
2389 s390_llill(code
, s390_r0
, 0xffff);
2390 s390_ngr (code
, dreg
, s390_r0
);
2397 /*========================= End of Function ========================*/
2399 /*------------------------------------------------------------------*/
2401 /* Name - is_unsigned. */
2403 /* Function - Return TRUE if next opcode is checking for un- */
2406 /*------------------------------------------------------------------*/
2409 is_unsigned (MonoInst
*next
)
2412 (((next
->opcode
>= OP_IBNE_UN
) &&
2413 (next
->opcode
<= OP_IBLT_UN
)) ||
2414 ((next
->opcode
>= OP_LBNE_UN
) &&
2415 (next
->opcode
<= OP_LBLT_UN
)) ||
2416 ((next
->opcode
>= OP_COND_EXC_NE_UN
) &&
2417 (next
->opcode
<= OP_COND_EXC_LT_UN
)) ||
2418 ((next
->opcode
>= OP_COND_EXC_INE_UN
) &&
2419 (next
->opcode
<= OP_COND_EXC_ILT_UN
)) ||
2420 ((next
->opcode
== OP_CLT_UN
) ||
2421 (next
->opcode
== OP_CGT_UN
) ||
2422 (next
->opcode
== OP_ICGE_UN
) ||
2423 (next
->opcode
== OP_ICLE_UN
)) ||
2424 ((next
->opcode
== OP_ICLT_UN
) ||
2425 (next
->opcode
== OP_ICGT_UN
) ||
2426 (next
->opcode
== OP_LCLT_UN
) ||
2427 (next
->opcode
== OP_LCGT_UN
))))
2433 /*========================= End of Function ========================*/
2435 /*------------------------------------------------------------------*/
2437 /* Name - mono_arch_output_basic_block */
2439 /* Function - Perform the "real" work of emitting instructions */
2440 /* that will do the work of in the basic block. */
2442 /*------------------------------------------------------------------*/
2445 mono_arch_output_basic_block (MonoCompile
*cfg
, MonoBasicBlock
*bb
)
2449 guint8
*code
= cfg
->native_code
+ cfg
->code_len
;
2452 /* we don't align basic blocks of loops on s390 */
2454 if (cfg
->verbose_level
> 2)
2455 g_print ("Basic block %d starting at offset 0x%x\n", bb
->block_num
, bb
->native_offset
);
2457 MONO_BB_FOR_EACH_INS (bb
, ins
) {
2458 const guint offset
= code
- cfg
->native_code
;
2459 set_code_cursor (cfg
, code
);
2460 int max_len
= ins_get_size (ins
->opcode
);
2461 code
= realloc_code (cfg
, max_len
);
2463 mono_debug_record_line_number (cfg
, ins
, offset
);
2465 switch (ins
->opcode
) {
2466 case OP_STOREI1_MEMBASE_IMM
: {
2467 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2468 S390_LONG (code
, stcy
, stc
, s390_r0
, 0,
2469 ins
->inst_destbasereg
, ins
->inst_offset
);
2472 case OP_STOREI2_MEMBASE_IMM
: {
2473 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2474 S390_LONG (code
, sthy
, sth
, s390_r0
, 0,
2475 ins
->inst_destbasereg
, ins
->inst_offset
);
2478 case OP_STOREI4_MEMBASE_IMM
: {
2479 s390_lgfi (code
, s390_r0
, ins
->inst_imm
);
2480 S390_LONG (code
, sty
, st
, s390_r0
, 0,
2481 ins
->inst_destbasereg
, ins
->inst_offset
);
2484 case OP_STORE_MEMBASE_IMM
:
2485 case OP_STOREI8_MEMBASE_IMM
: {
2486 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2487 S390_LONG (code
, stg
, stg
, s390_r0
, 0,
2488 ins
->inst_destbasereg
, ins
->inst_offset
);
2491 case OP_STOREI1_MEMBASE_REG
: {
2492 S390_LONG (code
, stcy
, stc
, ins
->sreg1
, 0,
2493 ins
->inst_destbasereg
, ins
->inst_offset
);
2496 case OP_STOREI2_MEMBASE_REG
: {
2497 S390_LONG (code
, sthy
, sth
, ins
->sreg1
, 0,
2498 ins
->inst_destbasereg
, ins
->inst_offset
);
2501 case OP_STOREI4_MEMBASE_REG
: {
2502 S390_LONG (code
, sty
, st
, ins
->sreg1
, 0,
2503 ins
->inst_destbasereg
, ins
->inst_offset
);
2506 case OP_STORE_MEMBASE_REG
:
2507 case OP_STOREI8_MEMBASE_REG
: {
2508 S390_LONG (code
, stg
, stg
, ins
->sreg1
, 0,
2509 ins
->inst_destbasereg
, ins
->inst_offset
);
2513 g_assert_not_reached ();
2515 case OP_LOAD_MEMBASE
:
2516 case OP_LOADI8_MEMBASE
: {
2517 S390_LONG (code
, lg
, lg
, ins
->dreg
, 0,
2518 ins
->inst_basereg
, ins
->inst_offset
);
2521 case OP_LOADI4_MEMBASE
: {
2522 S390_LONG (code
, lgf
, lgf
, ins
->dreg
, 0,
2523 ins
->inst_basereg
, ins
->inst_offset
);
2526 case OP_LOADU4_MEMBASE
: {
2527 S390_LONG (code
, llgf
, llgf
, ins
->dreg
, 0,
2528 ins
->inst_basereg
, ins
->inst_offset
);
2531 case OP_LOADU1_MEMBASE
: {
2532 S390_LONG (code
, llgc
, llgc
, ins
->dreg
, 0,
2533 ins
->inst_basereg
, ins
->inst_offset
);
2536 case OP_LOADI1_MEMBASE
: {
2537 S390_LONG (code
, lgb
, lgb
, ins
->dreg
, 0,
2538 ins
->inst_basereg
, ins
->inst_offset
);
2541 case OP_LOADU2_MEMBASE
: {
2542 S390_LONG (code
, llgh
, llgh
, ins
->dreg
, 0,
2543 ins
->inst_basereg
, ins
->inst_offset
);
2546 case OP_LOADI2_MEMBASE
: {
2547 S390_LONG (code
, lgh
, lgh
, ins
->dreg
, 0,
2548 ins
->inst_basereg
, ins
->inst_offset
);
2551 case OP_LCONV_TO_I1
: {
2552 s390_lgbr (code
, ins
->dreg
, ins
->sreg1
);
2555 case OP_LCONV_TO_I2
: {
2556 s390_lghr (code
, ins
->dreg
, ins
->sreg1
);
2559 case OP_LCONV_TO_U1
: {
2560 s390_llgcr (code
, ins
->dreg
, ins
->sreg1
);
2563 case OP_LCONV_TO_U2
: {
2564 s390_llghr (code
, ins
->dreg
, ins
->sreg1
);
2567 case OP_ICONV_TO_I1
: {
2568 s390_lgbr (code
, ins
->dreg
, ins
->sreg1
);
2571 case OP_ICONV_TO_I2
: {
2572 s390_lghr (code
, ins
->dreg
, ins
->sreg1
);
2575 case OP_ICONV_TO_U1
: {
2576 s390_llgcr (code
, ins
->dreg
, ins
->sreg1
);
2579 case OP_ICONV_TO_U2
: {
2580 s390_llghr (code
, ins
->dreg
, ins
->sreg1
);
2583 case OP_ICONV_TO_U4
: {
2584 s390_llgfr (code
, ins
->dreg
, ins
->sreg1
);
2587 case OP_ICONV_TO_I4
: {
2588 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
2593 if (is_unsigned (ins
->next
))
2594 s390_clgr (code
, ins
->sreg1
, ins
->sreg2
);
2596 s390_cgr (code
, ins
->sreg1
, ins
->sreg2
);
2600 if (is_unsigned (ins
->next
))
2601 s390_clr (code
, ins
->sreg1
, ins
->sreg2
);
2603 s390_cr (code
, ins
->sreg1
, ins
->sreg2
);
2606 case OP_COMPARE_IMM
:
2607 case OP_LCOMPARE_IMM
: {
2608 gboolean branchUn
= is_unsigned (ins
->next
);
2609 if ((ins
->inst_imm
== 0) && (!branchUn
)) {
2610 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
2612 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2614 s390_clgr (code
, ins
->sreg1
, s390_r0
);
2616 s390_cgr (code
, ins
->sreg1
, s390_r0
);
2620 case OP_ICOMPARE_IMM
: {
2621 gboolean branchUn
= is_unsigned (ins
->next
);
2622 if ((ins
->inst_imm
== 0) && (!branchUn
)) {
2623 s390_ltr (code
, ins
->sreg1
, ins
->sreg1
);
2625 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2627 s390_clr (code
, ins
->sreg1
, s390_r0
);
2629 s390_cr (code
, ins
->sreg1
, s390_r0
);
2634 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
2635 MONO_PATCH_INFO_JIT_ICALL_ID
,
2636 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break
));
2637 S390_CALL_TEMPLATE (code
, s390_r14
);
2641 if (mono_hwcap_s390x_has_mlt
) {
2642 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2645 s390_agr (code
, ins
->dreg
, src2
);
2650 if (mono_hwcap_s390x_has_mlt
) {
2651 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2654 s390_agr (code
, ins
->dreg
, src2
);
2660 s390_alcgr (code
, ins
->dreg
, src2
);
2664 if (mono_hwcap_s390x_has_mlt
) {
2665 if (s390_is_imm16 (ins
->inst_imm
)) {
2666 s390_aghik(code
, ins
->dreg
, ins
->sreg1
, ins
->inst_imm
);
2668 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2669 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2672 if (ins
->dreg
!= ins
->sreg1
) {
2673 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2675 if (s390_is_imm16 (ins
->inst_imm
)) {
2676 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
2677 } else if (s390_is_imm32 (ins
->inst_imm
)) {
2678 s390_agfi (code
, ins
->dreg
, ins
->inst_imm
);
2680 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2681 s390_agr (code
, ins
->dreg
, s390_r0
);
2687 if (ins
->dreg
!= ins
->sreg1
) {
2688 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2690 if (s390_is_imm32 (ins
->inst_imm
)) {
2691 s390_agfi (code
, ins
->dreg
, ins
->inst_imm
);
2693 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2694 s390_agr (code
, ins
->dreg
, s390_r0
);
2699 if (ins
->dreg
!= ins
->sreg1
) {
2700 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2702 if (s390_is_imm16 (ins
->inst_imm
)) {
2703 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2704 s390_alcgr (code
, ins
->dreg
, s390_r0
);
2706 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2707 s390_alcgr (code
, ins
->dreg
, s390_r0
);
2712 case OP_S390_IADD_OVF
: {
2714 s390_ar (code
, ins
->dreg
, src2
);
2715 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2716 s390_lgfr (code
, ins
->dreg
, ins
->dreg
);
2719 case OP_IADD_OVF_UN
:
2720 case OP_S390_IADD_OVF_UN
: {
2722 s390_algr (code
, ins
->dreg
, src2
);
2723 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
2724 s390_llgfr (code
, ins
->dreg
, ins
->dreg
);
2727 case OP_ADD_OVF_CARRY
: {
2729 s390_lghi (code
, s390_r0
, 0);
2730 s390_lgr (code
, s390_r1
, s390_r0
);
2731 s390_alcgr (code
, s390_r0
, s390_r1
);
2732 s390_agr (code
, ins
->dreg
, src2
);
2733 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2734 s390_agr (code
, ins
->dreg
, s390_r0
);
2735 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2738 case OP_ADD_OVF_UN_CARRY
: {
2740 s390_alcgr (code
, ins
->dreg
, src2
);
2741 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
2745 if (mono_hwcap_s390x_has_mlt
) {
2746 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2749 s390_sgr (code
, ins
->dreg
, src2
);
2754 if (mono_hwcap_s390x_has_mlt
) {
2755 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2758 s390_sgr (code
, ins
->dreg
, src2
);
2764 s390_slbgr(code
, ins
->dreg
, src2
);
2768 if (ins
->dreg
!= ins
->sreg1
) {
2769 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2771 if (s390_is_imm16 (-ins
->inst_imm
)) {
2772 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
2773 } else if (s390_is_imm32 (-ins
->inst_imm
)) {
2774 s390_slgfi (code
, ins
->dreg
, ins
->inst_imm
);
2776 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2777 s390_slgr (code
, ins
->dreg
, s390_r0
);
2782 if (ins
->dreg
!= ins
->sreg1
) {
2783 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2785 if (s390_is_imm16 (-ins
->inst_imm
)) {
2786 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
2787 } else if (s390_is_imm32 (-ins
->inst_imm
)) {
2788 s390_slgfi (code
, ins
->dreg
, ins
->inst_imm
);
2790 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2791 s390_slgr (code
, ins
->dreg
, s390_r0
);
2796 if (ins
->dreg
!= ins
->sreg1
) {
2797 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2799 if (s390_is_imm16 (-ins
->inst_imm
)) {
2800 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
2801 s390_slbgr (code
, ins
->dreg
, s390_r0
);
2803 S390_SET (code
, s390_r0
, ins
->inst_imm
);
2804 s390_slbgr(code
, ins
->dreg
, s390_r0
);
2808 case OP_SUB_OVF_CARRY
: {
2810 s390_lghi (code
, s390_r0
, 0);
2811 s390_lgr (code
, s390_r1
, s390_r0
);
2812 s390_slbgr (code
, s390_r0
, s390_r1
);
2813 s390_sgr (code
, ins
->dreg
, src2
);
2814 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2815 s390_agr (code
, ins
->dreg
, s390_r0
);
2816 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
2819 case OP_SUB_OVF_UN_CARRY
: {
2821 s390_slbgr (code
, ins
->dreg
, src2
);
2822 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
2826 if (mono_hwcap_s390x_has_mlt
) {
2827 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2829 if (ins
->sreg1
== ins
->dreg
) {
2830 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
2832 if (ins
->sreg2
== ins
->dreg
) {
2833 s390_ngr (code
, ins
->dreg
, ins
->sreg1
);
2835 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2836 s390_ngr (code
, ins
->dreg
, ins
->sreg2
);
2843 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
2844 if (mono_hwcap_s390x_has_mlt
) {
2845 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2847 if (ins
->dreg
!= ins
->sreg1
) {
2848 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2850 s390_ngr (code
, ins
->dreg
, s390_r0
);
2855 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2856 s390_dsgr (code
, s390_r0
, ins
->sreg2
);
2857 s390_lgr (code
, ins
->dreg
, s390_r1
);
2861 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2862 s390_lghi (code
, s390_r0
, 0);
2863 s390_dlgr (code
, s390_r0
, ins
->sreg2
);
2864 s390_lgr (code
, ins
->dreg
, s390_r1
);
2868 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2869 s390_dsgr (code
, s390_r0
, ins
->sreg2
);
2870 s390_lgr (code
, ins
->dreg
, s390_r0
);
2874 if (s390_is_imm16 (ins
->inst_imm
)) {
2875 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
2877 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
2879 s390_lgr (code
, s390_r0
, ins
->sreg1
);
2880 s390_dsgr (code
, s390_r0
, s390_r13
);
2881 s390_lgfr (code
, ins
->dreg
, s390_r0
);
2885 s390_lgr (code
, s390_r1
, ins
->sreg1
);
2886 s390_lghi (code
, s390_r0
, 0);
2887 s390_dlgr (code
, s390_r0
, ins
->sreg2
);
2888 s390_lgr (code
, ins
->dreg
, s390_r0
);
2892 if (mono_hwcap_s390x_has_mlt
) {
2893 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2895 if (ins
->sreg1
== ins
->dreg
) {
2896 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
2898 if (ins
->sreg2
== ins
->dreg
) {
2899 s390_ogr (code
, ins
->dreg
, ins
->sreg1
);
2901 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2902 s390_ogr (code
, ins
->dreg
, ins
->sreg2
);
2909 S390_SET_MASK(code
, s390_r0
, ins
->inst_imm
);
2910 if (mono_hwcap_s390x_has_mlt
) {
2911 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2913 if (ins
->dreg
!= ins
->sreg1
) {
2914 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2916 s390_ogr (code
, ins
->dreg
, s390_r0
);
2921 if (mono_hwcap_s390x_has_mlt
) {
2922 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
2924 if (ins
->sreg1
== ins
->dreg
) {
2925 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
2928 if (ins
->sreg2
== ins
->dreg
) {
2929 s390_xgr (code
, ins
->dreg
, ins
->sreg1
);
2932 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2933 s390_xgr (code
, ins
->dreg
, ins
->sreg2
);
2940 S390_SET_MASK(code
, s390_r0
, ins
->inst_imm
);
2941 if (mono_hwcap_s390x_has_mlt
) {
2942 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
2944 if (ins
->dreg
!= ins
->sreg1
) {
2945 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2947 s390_xgr (code
, ins
->dreg
, s390_r0
);
2953 s390_sllg (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
2958 if (ins
->sreg1
!= ins
->dreg
) {
2959 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2961 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
2966 s390_srag (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
2971 if (ins
->sreg1
!= ins
->dreg
) {
2972 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2974 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
2978 case OP_LSHR_UN_IMM
: {
2979 if (ins
->sreg1
!= ins
->dreg
) {
2980 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2982 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, (ins
->inst_imm
& 0x3f));
2987 s390_srlg (code
, ins
->dreg
, ins
->dreg
, src2
, 0);
2991 if (ins
->sreg1
!= ins
->dreg
) {
2992 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
2994 s390_lghi (code
, s390_r0
, -1);
2995 s390_xgr (code
, ins
->dreg
, s390_r0
);
2999 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
3004 s390_msgr (code
, ins
->dreg
, src2
);
3009 if (ins
->dreg
!= ins
->sreg1
) {
3010 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3012 if ((mono_hwcap_s390x_has_gie
) &&
3013 (s390_is_imm32 (ins
->inst_imm
))) {
3014 s390_msgfi (code
, ins
->dreg
, ins
->inst_imm
);
3016 if (s390_is_imm16 (ins
->inst_imm
)) {
3017 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3018 } else if (s390_is_imm32 (ins
->inst_imm
)) {
3019 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3021 S390_SET (code
, s390_r13
, ins
->inst_imm
);
3023 s390_msgr (code
, ins
->dreg
, s390_r13
);
3029 if (mono_hwcap_s390x_has_mie2
) {
3030 s390_msgrkc (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3031 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3033 s390_ltgr (code
, s390_r1
, ins
->sreg1
);
3034 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3035 s390_ltgr (code
, s390_r0
, ins
->sreg2
);
3037 s390_lghi (code
, s390_r1
, 0);
3038 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3039 s390_xgr (code
, s390_r0
, s390_r1
);
3040 s390_msgr (code
, s390_r1
, ins
->sreg2
);
3041 s390_xgr (code
, s390_r0
, s390_r1
);
3042 s390_srlg (code
, s390_r0
, s390_r0
, 0, 63);
3043 s390_ltgr (code
, s390_r0
, s390_r0
);
3044 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3045 PTRSLOT (code
, o
[0]);
3046 PTRSLOT (code
, o
[1]);
3047 s390_lgr (code
, ins
->dreg
, s390_r1
);
3051 case OP_LMUL_OVF_UN
: {
3052 s390_lghi (code
, s390_r0
, 0);
3053 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3054 s390_mlgr (code
, s390_r0
, ins
->sreg2
);
3055 s390_ltgr (code
, s390_r0
, s390_r0
);
3056 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3057 s390_lgr (code
, ins
->dreg
, s390_r1
);
3061 g_assert_not_reached ();
3063 s390_algr (code
, ins
->dreg
, src2
);
3068 s390_agr (code
, ins
->dreg
, src2
);
3072 g_assert_not_reached ();
3074 s390_alcgr (code
, ins
->dreg
, src2
);
3078 if (ins
->dreg
!= ins
->sreg1
) {
3079 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3081 if (s390_is_imm16 (ins
->inst_imm
)) {
3082 s390_aghi (code
, ins
->dreg
, ins
->inst_imm
);
3084 s390_afi (code
, ins
->dreg
, ins
->inst_imm
);
3089 if (ins
->dreg
!= ins
->sreg1
) {
3090 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3092 if (s390_is_imm16 (ins
->inst_imm
)) {
3093 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3094 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3096 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3097 s390_alcgr (code
, ins
->dreg
, s390_r0
);
3102 case OP_S390_LADD_OVF
: {
3103 if (mono_hwcap_s390x_has_mlt
) {
3104 s390_agrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3107 s390_agr (code
, ins
->dreg
, src2
);
3109 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3112 case OP_LADD_OVF_UN
:
3113 case OP_S390_LADD_OVF_UN
: {
3114 if (mono_hwcap_s390x_has_mlt
) {
3115 s390_algrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3118 s390_algr (code
, ins
->dreg
, src2
);
3120 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, "OverflowException");
3124 if (mono_hwcap_s390x_has_mlt
) {
3125 s390_slgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3127 CHECK_SRCDST_NCOM_I
;
3128 s390_slgr (code
, ins
->dreg
, src2
);
3133 if (mono_hwcap_s390x_has_mlt
) {
3134 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3136 CHECK_SRCDST_NCOM_I
;
3137 s390_sgr (code
, ins
->dreg
, src2
);
3142 CHECK_SRCDST_NCOM_I
;
3143 s390_slbgr (code
, ins
->dreg
, src2
);
3147 if (ins
->dreg
!= ins
->sreg1
) {
3148 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3150 if (s390_is_imm16 (-ins
->inst_imm
)) {
3151 s390_aghi (code
, ins
->dreg
, -ins
->inst_imm
);
3153 s390_agfi (code
, ins
->dreg
, -ins
->inst_imm
);
3158 S390_SET (code
, s390_r0
, ins
->inst_imm
);
3159 s390_slgfr (code
, ins
->dreg
, s390_r0
);
3163 case OP_S390_ISUB_OVF
: {
3164 if (mono_hwcap_s390x_has_mlt
) {
3165 s390_srk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3166 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3169 s390_sr (code
, ins
->dreg
, src2
);
3170 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3171 s390_lgfr (code
, ins
->dreg
, ins
->dreg
);
3175 case OP_ISUB_OVF_UN
:
3176 case OP_S390_ISUB_OVF_UN
: {
3177 if (mono_hwcap_s390x_has_mlt
) {
3178 s390_slrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3181 s390_slr (code
, ins
->dreg
, src2
);
3183 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3184 s390_llgfr(code
, ins
->dreg
, ins
->dreg
);
3188 case OP_S390_LSUB_OVF
: {
3189 if (mono_hwcap_s390x_has_mlt
) {
3190 s390_sgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3193 s390_sgr (code
, ins
->dreg
, src2
);
3195 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, "OverflowException");
3198 case OP_LSUB_OVF_UN
:
3199 case OP_S390_LSUB_OVF_UN
: {
3201 s390_slgr (code
, ins
->dreg
, src2
);
3202 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, "OverflowException");
3206 if (mono_hwcap_s390x_has_mlt
) {
3207 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3209 CHECK_SRCDST_NCOM_I
;
3210 s390_ngr (code
, ins
->dreg
, src2
);
3215 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3216 if (mono_hwcap_s390x_has_mlt
) {
3217 s390_ngrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3219 if (ins
->dreg
!= ins
->sreg1
) {
3220 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3222 s390_ngr (code
, ins
->dreg
, s390_r0
);
3227 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3228 s390_srda (code
, s390_r0
, 0, 32);
3229 s390_dr (code
, s390_r0
, ins
->sreg2
);
3230 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3234 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3235 s390_srdl (code
, s390_r0
, 0, 32);
3236 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3237 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3241 if (s390_is_imm16 (ins
->inst_imm
)) {
3242 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3244 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3246 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3247 s390_srda (code
, s390_r0
, 0, 32);
3248 s390_dr (code
, s390_r0
, ins
->sreg2
);
3249 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3253 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3254 s390_srda (code
, s390_r0
, 0, 32);
3255 s390_dr (code
, s390_r0
, ins
->sreg2
);
3256 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3259 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3260 s390_srdl (code
, s390_r0
, 0, 32);
3261 s390_dlr (code
, s390_r0
, ins
->sreg2
);
3262 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3266 if (s390_is_imm16 (ins
->inst_imm
)) {
3267 s390_lghi (code
, s390_r13
, ins
->inst_imm
);
3269 s390_lgfi (code
, s390_r13
, ins
->inst_imm
);
3271 s390_lgfr (code
, s390_r0
, ins
->sreg1
);
3272 s390_srda (code
, s390_r0
, 0, 32);
3273 s390_dr (code
, s390_r0
, ins
->sreg2
);
3274 s390_lgfr (code
, ins
->dreg
, s390_r0
);
3278 if (mono_hwcap_s390x_has_mlt
) {
3279 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3282 s390_ogr (code
, ins
->dreg
, src2
);
3287 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3288 if (mono_hwcap_s390x_has_mlt
) {
3289 s390_ogrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3291 if (ins
->dreg
!= ins
->sreg1
) {
3292 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3294 s390_ogr (code
, ins
->dreg
, s390_r0
);
3299 if (mono_hwcap_s390x_has_mlt
) {
3300 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, ins
->sreg2
);
3303 s390_xgr (code
, ins
->dreg
, src2
);
3308 S390_SET_MASK (code
, s390_r0
, ins
->inst_imm
);
3309 if (mono_hwcap_s390x_has_mlt
) {
3310 s390_xgrk (code
, ins
->dreg
, ins
->sreg1
, s390_r0
);
3312 if (ins
->dreg
!= ins
->sreg1
) {
3313 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3315 s390_xgr (code
, ins
->dreg
, s390_r0
);
3321 s390_sll (code
, ins
->dreg
, src2
, 0);
3325 if (ins
->sreg1
!= ins
->dreg
) {
3326 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3328 s390_sll (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3333 s390_sra (code
, ins
->dreg
, src2
, 0);
3337 if (ins
->sreg1
!= ins
->dreg
) {
3338 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3340 s390_sra (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3343 case OP_ISHR_UN_IMM
: {
3344 if (ins
->sreg1
!= ins
->dreg
) {
3345 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3347 s390_srl (code
, ins
->dreg
, 0, (ins
->inst_imm
& 0x1f));
3352 s390_srl (code
, ins
->dreg
, src2
, 0);
3356 if (ins
->sreg1
!= ins
->dreg
) {
3357 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3359 s390_lghi (code
, s390_r0
, -1);
3360 s390_xgr (code
, ins
->dreg
, s390_r0
);
3364 s390_lcgr (code
, ins
->dreg
, ins
->sreg1
);
3369 s390_msr (code
, ins
->dreg
, src2
);
3373 if (ins
->dreg
!= ins
->sreg1
) {
3374 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3376 if (s390_is_imm16 (ins
->inst_imm
)) {
3377 s390_lghi (code
, s390_r0
, ins
->inst_imm
);
3379 s390_lgfi (code
, s390_r0
, ins
->inst_imm
);
3381 s390_msr (code
, ins
->dreg
, s390_r0
);
3386 s390_ltr (code
, s390_r1
, ins
->sreg1
);
3387 s390_jz (code
, 0); CODEPTR(code
, o
[0]);
3388 s390_ltr (code
, s390_r0
, ins
->sreg2
);
3390 s390_lhi (code
, s390_r1
, 0);
3391 s390_j (code
, 0); CODEPTR(code
, o
[1]);
3392 s390_xr (code
, s390_r0
, s390_r1
);
3393 s390_msr (code
, s390_r1
, ins
->sreg2
);
3394 s390_xr (code
, s390_r0
, s390_r1
);
3395 s390_srl (code
, s390_r0
, 0, 31);
3396 s390_ltr (code
, s390_r0
, s390_r0
);
3397 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3398 PTRSLOT (code
, o
[0]);
3399 PTRSLOT (code
, o
[1]);
3400 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3403 case OP_IMUL_OVF_UN
: {
3404 s390_lhi (code
, s390_r0
, 0);
3405 s390_lr (code
, s390_r1
, ins
->sreg1
);
3406 s390_mlr (code
, s390_r0
, ins
->sreg2
);
3407 s390_ltr (code
, s390_r0
, s390_r0
);
3408 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ
, "OverflowException");
3409 s390_lgfr (code
, ins
->dreg
, s390_r1
);
3414 S390_SET (code
, ins
->dreg
, ins
->inst_c0
);
3418 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3419 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
3420 S390_LOAD_TEMPLATE (code
, ins
->dreg
);
3423 case OP_JUMP_TABLE
: {
3424 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3425 (MonoJumpInfoType
)ins
->inst_i1
, ins
->inst_p0
);
3426 S390_LOAD_TEMPLATE (code
, ins
->dreg
);
3430 if (ins
->dreg
!= ins
->sreg1
) {
3431 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
3435 case OP_LCONV_TO_I8
:
3437 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3439 case OP_LCONV_TO_I4
:
3440 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3443 case OP_LCONV_TO_U8
:
3444 case OP_LCONV_TO_U4
:
3446 s390_llgfr (code
, ins
->dreg
, ins
->sreg1
);
3448 case OP_LCONV_TO_OVF_U4
:
3449 S390_SET (code
, s390_r0
, 4294967295);
3450 s390_clgr (code
, ins
->sreg1
, s390_r0
);
3451 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, "OverflowException");
3452 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
3453 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, "OverflowException");
3454 s390_llgfr(code
, ins
->dreg
, ins
->sreg1
);
3456 case OP_LCONV_TO_OVF_I4_UN
:
3457 S390_SET (code
, s390_r0
, 2147483647);
3458 s390_cgr (code
, ins
->sreg1
, s390_r0
);
3459 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, "OverflowException");
3460 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
3461 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, "OverflowException");
3462 s390_lgfr (code
, ins
->dreg
, ins
->sreg1
);
3465 if (ins
->dreg
!= ins
->sreg1
) {
3466 s390_ldr (code
, ins
->dreg
, ins
->sreg1
);
3469 case OP_MOVE_F_TO_I8
:
3470 s390_lgdr (code
, ins
->dreg
, ins
->sreg1
);
3472 case OP_MOVE_I8_TO_F
:
3473 s390_ldgr (code
, ins
->dreg
, ins
->sreg1
);
3475 case OP_MOVE_F_TO_I4
:
3476 s390_ledbr (code
, s390_f0
, ins
->sreg1
);
3477 s390_lgdr (code
, ins
->dreg
, s390_f0
);
3478 s390_srag (code
, ins
->dreg
, ins
->dreg
, 0, 32);
3480 case OP_MOVE_I4_TO_F
:
3481 s390_slag (code
, s390_r0
, ins
->sreg1
, 0, 32);
3482 s390_ldgr (code
, ins
->dreg
, s390_r0
);
3484 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
3486 case OP_FCONV_TO_R4
:
3487 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
3489 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
3491 case OP_S390_SETF4RET
:
3493 s390_ledbr (code
, ins
->dreg
, ins
->sreg1
);
3496 if (s390_is_imm16 (ins
->inst_offset
)) {
3497 s390_lghi (code
, s390_r13
, ins
->inst_offset
);
3498 } else if (s390_is_imm32 (ins
->inst_offset
)) {
3499 s390_lgfi (code
, s390_r13
, ins
->inst_offset
);
3501 S390_SET (code
, s390_r13
, ins
->inst_offset
);
3503 s390_ear (code
, s390_r1
, 0);
3504 s390_sllg(code
, s390_r1
, s390_r1
, 0, 32);
3505 s390_ear (code
, s390_r1
, 1);
3506 s390_lg (code
, ins
->dreg
, s390_r13
, s390_r1
, 0);
3510 if (s390_is_imm16 (ins
->inst_offset
)) {
3511 s390_lghi (code
, s390_r13
, ins
->inst_offset
);
3512 } else if (s390_is_imm32 (ins
->inst_offset
)) {
3513 s390_lgfi (code
, s390_r13
, ins
->inst_offset
);
3515 S390_SET (code
, s390_r13
, ins
->inst_offset
);
3517 s390_ear (code
, s390_r1
, 0);
3518 s390_sllg(code
, s390_r1
, s390_r1
, 0, 32);
3519 s390_ear (code
, s390_r1
, 1);
3520 s390_stg (code
, ins
->sreg1
, s390_r13
, s390_r1
, 0);
3523 case OP_TAILCALL_PARAMETER
:
3524 // This opcode helps compute sizes, i.e.
3525 // of the subsequent OP_TAILCALL, but contributes no code.
3526 g_assert (ins
->next
);
3529 case OP_TAILCALL_MEMBASE
: {
3530 MonoCallInst
*call
= (MonoCallInst
*) ins
;
3531 MonoMethod
*method
= call
->method
;
3532 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
3533 CallInfo
*cinfo
= get_call_info (NULL
, sig
);
3534 int32_t stackUsage
= (cinfo
->sz
.stack_size
- S390_MINIMAL_STACK_SIZE
),
3535 stackOffset
= S390_MINIMAL_STACK_SIZE
;
3537 if (cfg
->method
->save_lmf
)
3538 restoreLMF(code
, cfg
->frame_reg
, cfg
->stack_usage
);
3540 s390_lgr (code
, s390_r12
, cfg
->frame_reg
);
3541 code
= backUpStackPtr(cfg
, code
);
3543 while (stackUsage
> 256) {
3544 s390_mvc (code
, 256, STK_BASE
, stackOffset
,
3545 s390_r12
, stackOffset
);
3551 s390_mvc (code
, stackUsage
, STK_BASE
, stackOffset
,
3552 s390_r12
, stackOffset
);
3554 s390_lmg (code
, s390_r6
, s390_r13
, STK_BASE
, S390_REG_SAVE_OFFSET
);
3556 if (cfg
->arch
.used_fp_regs
!= 0) {
3557 int32_t fpOffset
= sizeof(double);
3558 for (int i
=8; i
<16; i
++) {
3559 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
3560 s390_ld (code
, i
, cfg
->arch
.fpSize
, STK_BASE
, fpOffset
);
3561 fpOffset
+= sizeof(double);
3566 s390_lg (code
, s390_r14
, 0, STK_BASE
, S390_RET_ADDR_OFFSET
);
3567 if (ins
->opcode
== OP_TAILCALL_MEMBASE
) {
3568 if (mono_hwcap_s390x_has_mie2
) {
3569 s390_bi (code
, 0, ins
->sreg1
, ins
->inst_offset
);
3571 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3572 s390_br (code
, s390_r1
);
3575 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
3576 MONO_PATCH_INFO_METHOD_JUMP
,
3578 s390_jcl (code
, S390_CC_UN
, 0);
3584 case OP_CHECK_THIS
: {
3585 /* ensure ins->sreg1 is not NULL */
3586 s390_lg (code
, s390_r0
, 0, ins
->sreg1
, 0);
3587 s390_ltgr (code
, s390_r0
, s390_r0
);
3588 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3592 const int offset
= cfg
->sig_cookie
+ cfg
->stack_usage
;
3594 if (s390_is_imm16 (offset
)) {
3595 s390_lghi (code
, s390_r0
, offset
);
3596 } else if (s390_is_imm32 (offset
)) {
3597 s390_lgfi (code
, s390_r0
, offset
);
3599 S390_SET (code
, s390_r0
, offset
);
3601 s390_agr (code
, s390_r0
, cfg
->frame_reg
);
3602 s390_stg (code
, s390_r0
, 0, ins
->sreg1
, 0);
3606 call
= (MonoCallInst
*)ins
;
3608 mono_call_add_patch_info (cfg
, call
, code
- cfg
->native_code
);
3609 S390_CALL_TEMPLATE (code
, s390_r14
);
3610 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
3611 s390_ldebr (code
, s390_f0
, s390_f0
);
3620 call
= (MonoCallInst
*)ins
;
3621 mono_call_add_patch_info (cfg
, call
, code
- cfg
->native_code
);
3622 S390_CALL_TEMPLATE (code
, s390_r14
);
3625 case OP_FCALL_REG
: {
3626 call
= (MonoCallInst
*)ins
;
3627 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3628 s390_basr (code
, s390_r14
, s390_r1
);
3629 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
3630 s390_ldebr (code
, s390_f0
, s390_f0
);
3636 case OP_VOIDCALL_REG
:
3639 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3640 s390_basr (code
, s390_r14
, s390_r1
);
3643 case OP_FCALL_MEMBASE
: {
3644 call
= (MonoCallInst
*)ins
;
3645 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3646 s390_basr (code
, s390_r14
, s390_r1
);
3647 if (!cfg
->r4fp
&& call
->signature
->ret
->type
== MONO_TYPE_R4
)
3648 s390_ldebr (code
, s390_f0
, s390_f0
);
3651 case OP_LCALL_MEMBASE
:
3652 case OP_VCALL_MEMBASE
:
3653 case OP_VCALL2_MEMBASE
:
3654 case OP_VOIDCALL_MEMBASE
:
3655 case OP_RCALL_MEMBASE
:
3656 case OP_CALL_MEMBASE
: {
3657 s390_lg (code
, s390_r1
, 0, ins
->sreg1
, ins
->inst_offset
);
3658 s390_basr (code
, s390_r14
, s390_r1
);
3665 if (cfg
->param_area
== 0)
3666 alloca_skip
= S390_MINIMAL_STACK_SIZE
;
3668 alloca_skip
= cfg
->param_area
;
3670 area_offset
= S390_ALIGN(alloca_skip
, S390_STACK_ALIGNMENT
);
3671 s390_lgr (code
, s390_r1
, ins
->sreg1
);
3672 if (ins
->flags
& MONO_INST_INIT
)
3673 s390_lgr (code
, s390_r0
, ins
->sreg1
);
3674 s390_aghi (code
, s390_r1
, 14);
3675 s390_srlg (code
, s390_r1
, s390_r1
, 0, 3);
3676 s390_sllg (code
, s390_r1
, s390_r1
, 0, 3);
3677 if (cfg
->method
->save_lmf
) {
3678 /*----------------------------------*/
3679 /* we have to adjust lmf ebp value */
3680 /*----------------------------------*/
3681 int lmfOffset
= cfg
->stack_usage
- sizeof(MonoLMF
);
3683 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
3684 if (s390_is_imm16(lmfOffset
)) {
3685 s390_aghi (code
, s390_r13
, lmfOffset
);
3686 } else if (s390_is_imm32(lmfOffset
)) {
3687 s390_agfi (code
, s390_r13
, lmfOffset
);
3689 S390_SET (code
, s390_r13
, lmfOffset
);
3691 s390_lgr (code
, s390_r14
, STK_BASE
);
3692 s390_sgr (code
, s390_r14
, s390_r1
);
3693 s390_stg (code
, s390_r14
, 0, s390_r13
,
3694 G_STRUCT_OFFSET(MonoLMF
, ebp
));
3696 s390_lg (code
, s390_r13
, 0, STK_BASE
, 0);
3697 s390_sgr (code
, STK_BASE
, s390_r1
);
3698 s390_stg (code
, s390_r13
, 0, STK_BASE
, 0);
3699 s390_la (code
, ins
->dreg
, 0, STK_BASE
, area_offset
);
3700 s390_srlg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
3701 s390_sllg (code
, ins
->dreg
, ins
->dreg
, 0, 3);
3702 if (ins
->flags
& MONO_INST_INIT
) {
3703 s390_lgr (code
, s390_r1
, s390_r0
);
3704 s390_lgr (code
, s390_r0
, ins
->dreg
);
3705 s390_lgr (code
, s390_r14
, s390_r12
);
3706 s390_lghi (code
, s390_r13
, 0);
3707 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
3709 s390_lgr (code
, s390_r12
, s390_r14
);
3714 s390_lgr (code
, s390_r2
, ins
->sreg1
);
3715 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
3716 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_throw_exception
));
3717 S390_CALL_TEMPLATE(code
, s390_r14
);
3721 s390_lgr (code
, s390_r2
, ins
->sreg1
);
3722 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
3723 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception
));
3724 S390_CALL_TEMPLATE(code
, s390_r14
);
3727 case OP_START_HANDLER
: {
3728 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
3730 S390_LONG (code
, stg
, stg
, s390_r14
, 0,
3731 spvar
->inst_basereg
,
3732 spvar
->inst_offset
);
3735 case OP_ENDFILTER
: {
3736 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
3738 if (ins
->sreg1
!= s390_r2
)
3739 s390_lgr(code
, s390_r2
, ins
->sreg1
);
3740 S390_LONG (code
, lg
, lg
, s390_r14
, 0,
3741 spvar
->inst_basereg
,
3742 spvar
->inst_offset
);
3743 s390_br (code
, s390_r14
);
3746 case OP_ENDFINALLY
: {
3747 MonoInst
*spvar
= mono_find_spvar_for_region (cfg
, bb
->region
);
3749 S390_LONG (code
, lg
, lg
, s390_r14
, 0,
3750 spvar
->inst_basereg
,
3751 spvar
->inst_offset
);
3752 s390_br (code
, s390_r14
);
3755 case OP_CALL_HANDLER
: {
3756 mono_add_patch_info (cfg
, code
-cfg
->native_code
,
3757 MONO_PATCH_INFO_BB
, ins
->inst_target_bb
);
3758 s390_brasl (code
, s390_r14
, 0);
3759 for (GList
*tmp
= ins
->inst_eh_blocks
; tmp
!= bb
->clause_holes
; tmp
= tmp
->prev
)
3760 mono_cfg_add_try_hole (cfg
, ((MonoLeaveClause
*) tmp
->data
)->clause
, code
, bb
);
3764 ins
->inst_c0
= code
- cfg
->native_code
;
3767 case OP_RELAXED_NOP
:
3770 case OP_DUMMY_ICONST
:
3771 case OP_DUMMY_I8CONST
:
3772 case OP_DUMMY_R8CONST
:
3773 case OP_DUMMY_R4CONST
:
3774 case OP_NOT_REACHED
:
3778 case OP_IL_SEQ_POINT
:
3779 mono_add_seq_point (cfg
, bb
, ins
, code
- cfg
->native_code
);
3781 case OP_SEQ_POINT
: {
3784 if (cfg
->compile_aot
)
3788 * Read from the single stepping trigger page. This will cause a
3789 * SIGSEGV when single stepping is enabled.
3790 * We do this _before_ the breakpoint, so single stepping after
3791 * a breakpoint is hit will step to the next IL offset.
3793 if (ins
->flags
& MONO_INST_SINGLE_STEP_LOC
) {
3794 breakpointCode
.pTrigger
= ss_trigger_page
;
3795 memcpy(code
, (void *) &breakpointCode
, BREAKPOINT_SIZE
);
3796 code
+= BREAKPOINT_SIZE
;
3799 mono_add_seq_point (cfg
, bb
, ins
, code
- cfg
->native_code
);
3802 * A placeholder for a possible breakpoint inserted by
3803 * mono_arch_set_breakpoint ().
3805 for (i
= 0; i
< (BREAKPOINT_SIZE
/ S390X_NOP_SIZE
); ++i
)
3809 * Add an additional nop so skipping the bp doesn't cause the ip to point
3810 * to another IL offset.
3816 case OP_GENERIC_CLASS_INIT
: {
3817 static int byte_offset
= -1;
3818 static guint8 bitmask
;
3821 g_assert (ins
->sreg1
== S390_FIRST_ARG_REG
);
3823 if (byte_offset
< 0)
3824 mono_marshal_find_bitfield_offset (MonoVTable
, initialized
, &byte_offset
, &bitmask
);
3826 s390_tm (code
, ins
->sreg1
, byte_offset
, bitmask
);
3827 s390_jo (code
, 0); CODEPTR(code
, jump
);
3829 mono_add_patch_info (cfg
, code
-cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
3830 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_generic_class_init
));
3831 S390_CALL_TEMPLATE(code
, s390_r14
);
3833 PTRSLOT (code
, jump
);
3835 ins
->flags
|= MONO_INST_GC_CALLSITE
;
3836 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
3840 EMIT_UNCOND_BRANCH(ins
);
3843 s390_br (code
, ins
->sreg1
);
3849 s390_lghi(code
, ins
->dreg
, 1);
3851 s390_lghi(code
, ins
->dreg
, 0);
3857 s390_lghi(code
, ins
->dreg
, 1);
3859 s390_lghi(code
, ins
->dreg
, 0);
3865 s390_lghi(code
, ins
->dreg
, 1);
3867 s390_lghi(code
, ins
->dreg
, 0);
3873 s390_lghi(code
, ins
->dreg
, 1);
3875 s390_lghi(code
, ins
->dreg
, 0);
3881 s390_lghi(code
, ins
->dreg
, 1);
3883 s390_lghi(code
, ins
->dreg
, 0);
3887 s390_lghi(code
, ins
->dreg
, 1);
3889 s390_lghi(code
, ins
->dreg
, 0);
3893 s390_lghi(code
, ins
->dreg
, 1);
3895 s390_lghi(code
, ins
->dreg
, 0);
3899 s390_lghi(code
, ins
->dreg
, 1);
3901 s390_lghi(code
, ins
->dreg
, 0);
3905 s390_lghi(code
, ins
->dreg
, 1);
3907 s390_lghi(code
, ins
->dreg
, 0);
3911 s390_lghi(code
, ins
->dreg
, 1);
3913 s390_lghi(code
, ins
->dreg
, 0);
3916 case OP_COND_EXC_EQ
:
3917 case OP_COND_EXC_IEQ
:
3918 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ
, ins
->inst_p1
);
3920 case OP_COND_EXC_NE_UN
:
3921 case OP_COND_EXC_INE_UN
:
3922 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE
, ins
->inst_p1
);
3924 case OP_COND_EXC_LT
:
3925 case OP_COND_EXC_ILT
:
3926 case OP_COND_EXC_LT_UN
:
3927 case OP_COND_EXC_ILT_UN
:
3928 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT
, ins
->inst_p1
);
3930 case OP_COND_EXC_GT
:
3931 case OP_COND_EXC_IGT
:
3932 case OP_COND_EXC_GT_UN
:
3933 case OP_COND_EXC_IGT_UN
:
3934 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT
, ins
->inst_p1
);
3936 case OP_COND_EXC_GE
:
3937 case OP_COND_EXC_IGE
:
3938 case OP_COND_EXC_GE_UN
:
3939 case OP_COND_EXC_IGE_UN
:
3940 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE
, ins
->inst_p1
);
3942 case OP_COND_EXC_LE
:
3943 case OP_COND_EXC_ILE
:
3944 case OP_COND_EXC_LE_UN
:
3945 case OP_COND_EXC_ILE_UN
:
3946 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE
, ins
->inst_p1
);
3948 case OP_COND_EXC_OV
:
3949 case OP_COND_EXC_IOV
:
3950 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV
, ins
->inst_p1
);
3952 case OP_COND_EXC_NO
:
3953 case OP_COND_EXC_INO
:
3954 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO
, ins
->inst_p1
);
3957 case OP_COND_EXC_IC
:
3958 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY
, ins
->inst_p1
);
3960 case OP_COND_EXC_NC
:
3961 case OP_COND_EXC_INC
:
3962 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC
, ins
->inst_p1
);
3966 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
3970 EMIT_COND_BRANCH (ins
, S390_CC_NE
);
3976 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
3982 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
3988 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
3994 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
3998 EMIT_COMP_AND_BRANCH(ins
, crj
, cr
);
4002 EMIT_COMP_AND_BRANCH(ins
, clrj
, clr
);
4006 EMIT_COMP_AND_BRANCH(ins
, cgrj
, cgr
);
4010 EMIT_COMP_AND_BRANCH(ins
, clgrj
, clgr
);
4014 EMIT_COMP_AND_BRANCH_IMM(ins
, crj
, cr
, ltr
, FALSE
);
4018 EMIT_COMP_AND_BRANCH_IMM(ins
, clrj
, clr
, ltr
, TRUE
);
4022 EMIT_COMP_AND_BRANCH_IMM(ins
, cgrj
, cgr
, ltgr
, FALSE
);
4026 EMIT_COMP_AND_BRANCH_IMM(ins
, clgrj
, clgr
, ltgr
, TRUE
);
4029 /* floating point opcodes */
4031 if (*((double *) ins
->inst_p0
) == 0) {
4032 s390_lzdr (code
, ins
->dreg
);
4034 S390_SET (code
, s390_r13
, ins
->inst_p0
);
4035 s390_ld (code
, ins
->dreg
, 0, s390_r13
, 0);
4040 if (*((float *) ins
->inst_p0
) == 0) {
4042 s390_lzer (code
, ins
->dreg
);
4044 s390_lzdr (code
, ins
->dreg
);
4046 S390_SET (code
, s390_r13
, ins
->inst_p0
);
4048 S390_LONG (code
, ley
, le
, ins
->dreg
, 0, s390_r13
, 0);
4050 s390_ldeb (code
, ins
->dreg
, 0, s390_r13
, 0);
4055 case OP_STORER8_MEMBASE_REG
: {
4056 S390_LONG (code
, stdy
, std
, ins
->sreg1
, 0,
4057 ins
->inst_destbasereg
, ins
->inst_offset
);
4060 case OP_LOADR8_MEMBASE
: {
4061 S390_LONG (code
, ldy
, ld
, ins
->dreg
, 0,
4062 ins
->inst_basereg
, ins
->inst_offset
);
4065 case OP_STORER4_MEMBASE_REG
: {
4067 S390_LONG (code
, stey
, ste
, ins
->sreg1
, 0,
4068 ins
->inst_destbasereg
, ins
->inst_offset
);
4070 s390_ledbr (code
, s390_f15
, ins
->sreg1
);
4071 S390_LONG (code
, stey
, ste
, s390_f15
, 0,
4072 ins
->inst_destbasereg
, ins
->inst_offset
);
4076 case OP_LOADR4_MEMBASE
: {
4078 S390_LONG (code
, ley
, le
, ins
->dreg
, 0,
4079 ins
->inst_basereg
, ins
->inst_offset
);
4081 S390_LONG (code
, ley
, le
, s390_f15
, 0,
4082 ins
->inst_basereg
, ins
->inst_offset
);
4083 s390_ldebr (code
, ins
->dreg
, s390_f15
);
4087 case OP_ICONV_TO_R_UN
: {
4088 if (mono_hwcap_s390x_has_fpe
) {
4089 s390_cdlfbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4091 s390_llgfr (code
, s390_r0
, ins
->sreg1
);
4092 s390_cdgbr (code
, ins
->dreg
, s390_r0
);
4096 case OP_LCONV_TO_R_UN
: {
4097 if (mono_hwcap_s390x_has_fpe
) {
4098 s390_cdlgbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4101 s390_cxgbr (code
, s390_f12
, ins
->sreg1
);
4102 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4103 s390_jnl (code
, 0); CODEPTR(code
, jump
);
4104 S390_SET (code
, s390_r13
, 0x403f000000000000llu
);
4105 s390_lgdr (code
, s390_f13
, s390_r13
);
4106 s390_lzdr (code
, s390_f15
);
4107 s390_axbr (code
, s390_f12
, s390_f13
);
4108 PTRSLOT(code
, jump
);
4109 s390_ldxbr (code
, s390_f13
, s390_f12
);
4110 s390_ldr (code
, ins
->dreg
, s390_f13
);
4114 case OP_LCONV_TO_R4
:
4115 case OP_ICONV_TO_R4
: {
4116 s390_cegbr (code
, ins
->dreg
, ins
->sreg1
);
4118 s390_ldebr (code
, ins
->dreg
, ins
->dreg
);
4121 case OP_LCONV_TO_R8
:
4122 case OP_ICONV_TO_R8
: {
4123 s390_cdgbr (code
, ins
->dreg
, ins
->sreg1
);
4126 case OP_FCONV_TO_I1
:
4127 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4128 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4130 s390_oill (code
, ins
->dreg
, 0x80);
4131 s390_lghi (code
, s390_r0
, 0xff);
4132 s390_ngr (code
, ins
->dreg
, s390_r0
);
4134 case OP_FCONV_TO_U1
:
4135 if (mono_hwcap_s390x_has_fpe
) {
4136 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4137 s390_lghi (code
, s390_r0
, 0xff);
4138 s390_ngr (code
, ins
->dreg
, s390_r0
);
4140 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4143 case OP_FCONV_TO_I2
:
4144 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4145 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4147 s390_oill (code
, ins
->dreg
, 0x8000);
4148 s390_llill (code
, s390_r0
, 0xffff);
4149 s390_ngr (code
, ins
->dreg
, s390_r0
);
4151 case OP_FCONV_TO_U2
:
4152 if (mono_hwcap_s390x_has_fpe
) {
4153 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4154 s390_llill (code
, s390_r0
, 0xffff);
4155 s390_ngr (code
, ins
->dreg
, s390_r0
);
4157 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4160 case OP_FCONV_TO_I4
:
4162 s390_cfdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4164 case OP_FCONV_TO_U4
:
4166 if (mono_hwcap_s390x_has_fpe
) {
4167 s390_clfdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4169 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4172 case OP_FCONV_TO_I8
:
4173 s390_cgdbr (code
, ins
->dreg
, 5, ins
->sreg1
);
4175 case OP_FCONV_TO_U8
:
4176 if (mono_hwcap_s390x_has_fpe
) {
4177 s390_clgdbr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4179 code
= emit_double_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 8, FALSE
);
4182 case OP_RCONV_TO_I1
:
4183 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4184 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4186 s390_oill (code
, ins
->dreg
, 0x80);
4187 s390_lghi (code
, s390_r0
, 0xff);
4188 s390_ngr (code
, ins
->dreg
, s390_r0
);
4190 case OP_RCONV_TO_U1
:
4191 if (mono_hwcap_s390x_has_fpe
) {
4192 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4193 s390_lghi (code
, s390_r0
, 0xff);
4194 s390_ngr (code
, ins
->dreg
, s390_r0
);
4196 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 1, FALSE
);
4199 case OP_RCONV_TO_I2
:
4200 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4201 s390_ltgr (code
, ins
->dreg
, ins
->dreg
);
4203 s390_oill (code
, ins
->dreg
, 0x8000);
4204 s390_llill (code
, s390_r0
, 0xffff);
4205 s390_ngr (code
, ins
->dreg
, s390_r0
);
4207 case OP_RCONV_TO_U2
:
4208 if (mono_hwcap_s390x_has_fpe
) {
4209 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4210 s390_llill (code
, s390_r0
, 0xffff);
4211 s390_ngr (code
, ins
->dreg
, s390_r0
);
4213 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 2, FALSE
);
4216 case OP_RCONV_TO_I4
:
4218 s390_cfebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4220 case OP_RCONV_TO_U4
:
4221 if (mono_hwcap_s390x_has_fpe
) {
4222 s390_clfebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4224 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 4, FALSE
);
4227 case OP_RCONV_TO_I8
:
4228 s390_cgebr (code
, ins
->dreg
, 5, ins
->sreg1
);
4230 case OP_RCONV_TO_U8
:
4231 if (mono_hwcap_s390x_has_fpe
) {
4232 s390_clgebr (code
, ins
->dreg
, 5, ins
->sreg1
, 0);
4234 code
= emit_float_to_int (cfg
, code
, ins
->dreg
, ins
->sreg1
, 8, FALSE
);
4237 case OP_LCONV_TO_OVF_I
: {
4238 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4240 s390_ltgr (code
, ins
->sreg2
, ins
->sreg2
);
4241 s390_jnl (code
, 0); CODEPTR(code
, o
[0]);
4242 s390_ltgr (code
, ins
->sreg1
, ins
->sreg1
);
4243 s390_jnl (code
, 0); CODEPTR(code
, o
[1]);
4244 s390_lhi (code
, s390_r13
, -1);
4245 s390_cgr (code
, ins
->sreg1
, s390_r13
);
4246 s390_jnz (code
, 0); CODEPTR(code
, o
[2]);
4247 if (ins
->dreg
!= ins
->sreg2
)
4248 s390_lgr (code
, ins
->dreg
, ins
->sreg2
);
4249 s390_j (code
, 0); CODEPTR(code
, o
[3]);
4250 PTRSLOT(code
, o
[0]);
4251 s390_jz (code
, 0); CODEPTR(code
, o
[4]);
4252 PTRSLOT(code
, o
[1]);
4253 PTRSLOT(code
, o
[2]);
4254 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4255 MONO_PATCH_INFO_EXC
, "OverflowException");
4256 s390_brasl (code
, s390_r14
, 0);
4257 PTRSLOT(code
, o
[3]);
4258 PTRSLOT(code
, o
[4]);
4262 s390_lpdbr (code
, ins
->dreg
, ins
->sreg1
);
4266 s390_sqdbr (code
, ins
->dreg
, ins
->sreg1
);
4271 s390_adbr (code
, ins
->dreg
, src2
);
4276 s390_aebr (code
, ins
->dreg
, src2
);
4280 CHECK_SRCDST_NCOM_F
;
4281 s390_sdbr (code
, ins
->dreg
, src2
);
4285 CHECK_SRCDST_NCOM_F
;
4286 s390_sebr (code
, ins
->dreg
, src2
);
4291 s390_mdbr (code
, ins
->dreg
, src2
);
4296 s390_meer (code
, ins
->dreg
, src2
);
4300 CHECK_SRCDST_NCOM_F
;
4301 s390_ddbr (code
, ins
->dreg
, src2
);
4305 CHECK_SRCDST_NCOM_F
;
4306 s390_debr (code
, ins
->dreg
, src2
);
4310 s390_lcdbr (code
, ins
->dreg
, ins
->sreg1
);
4314 s390_lcebr (code
, ins
->dreg
, ins
->sreg1
);
4318 CHECK_SRCDST_NCOM_F
;
4319 s390_didbr (code
, ins
->dreg
, src2
, 5, s390_f15
);
4323 CHECK_SRCDST_NCOM_F
;
4324 s390_diebr (code
, ins
->dreg
, src2
, 5, s390_f15
);
4328 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4332 s390_cebr (code
, ins
->sreg1
, ins
->sreg2
);
4336 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4337 s390_lghi (code
, ins
->dreg
, 1);
4339 s390_lghi (code
, ins
->dreg
, 0);
4343 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4344 s390_lghi (code
, ins
->dreg
, 1);
4346 s390_lghi (code
, ins
->dreg
, 0);
4350 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4351 s390_lghi (code
, ins
->dreg
, 1);
4353 s390_lghi (code
, ins
->dreg
, 0);
4357 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4358 s390_lghi (code
, ins
->dreg
, 1);
4360 s390_lghi (code
, ins
->dreg
, 0);
4364 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4365 s390_lghi (code
, ins
->dreg
, 1);
4367 s390_lghi (code
, ins
->dreg
, 0);
4371 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4372 s390_lghi (code
, ins
->dreg
, 1);
4374 s390_lghi (code
, ins
->dreg
, 0);
4378 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4379 s390_lghi (code
, ins
->dreg
, 1);
4381 s390_lghi (code
, ins
->dreg
, 0);
4385 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4386 s390_lghi (code
, ins
->dreg
, 1);
4388 s390_lghi (code
, ins
->dreg
, 0);
4392 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4393 s390_lghi (code
, ins
->dreg
, 1);
4395 s390_lghi (code
, ins
->dreg
, 0);
4399 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4400 s390_lghi (code
, ins
->dreg
, 1);
4402 s390_lghi (code
, ins
->dreg
, 0);
4406 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4407 s390_lghi (code
, ins
->dreg
, 1);
4409 s390_lghi (code
, ins
->dreg
, 0);
4413 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4414 s390_lghi (code
, ins
->dreg
, 1);
4416 s390_lghi (code
, ins
->dreg
, 0);
4420 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4421 s390_lghi (code
, ins
->dreg
, 1);
4423 s390_lghi (code
, ins
->dreg
, 0);
4427 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4428 s390_lghi (code
, ins
->dreg
, 1);
4430 s390_lghi (code
, ins
->dreg
, 0);
4434 s390_cdbr (code
, ins
->sreg1
, ins
->sreg2
);
4435 s390_lghi (code
, ins
->dreg
, 1);
4437 s390_lghi (code
, ins
->dreg
, 0);
4441 s390_cebr (code
, ins
->sreg1
, ins
->sreg2
);
4442 s390_lghi (code
, ins
->dreg
, 1);
4444 s390_lghi (code
, ins
->dreg
, 0);
4449 s390_jo (code
, 0); CODEPTR(code
, o
);
4450 EMIT_COND_BRANCH (ins
, S390_CC_EQ
);
4455 EMIT_COND_BRANCH (ins
, S390_CC_NE
|S390_CC_OV
);
4459 s390_jo (code
, 0); CODEPTR(code
, o
);
4460 EMIT_COND_BRANCH (ins
, S390_CC_LT
);
4465 EMIT_COND_BRANCH (ins
, S390_CC_LT
|S390_CC_OV
);
4469 s390_jo (code
, 0); CODEPTR(code
, o
);
4470 EMIT_COND_BRANCH (ins
, S390_CC_GT
);
4475 EMIT_COND_BRANCH (ins
, S390_CC_GT
|S390_CC_OV
);
4479 s390_jo (code
, 0); CODEPTR(code
, o
);
4480 EMIT_COND_BRANCH (ins
, S390_CC_GE
);
4485 EMIT_COND_BRANCH (ins
, S390_CC_GE
|S390_CC_OV
);
4489 s390_jo (code
, 0); CODEPTR(code
, o
);
4490 EMIT_COND_BRANCH (ins
, S390_CC_LE
);
4495 EMIT_COND_BRANCH (ins
, S390_CC_LE
|S390_CC_OV
);
4499 s390_lhi (code
, s390_r13
, 0x7f);
4500 s390_tcdb (code
, ins
->sreg1
, 0, s390_r13
, 0);
4501 s390_jz (code
, 0); CODEPTR(code
, o
);
4502 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
4503 MONO_PATCH_INFO_EXC
, "OverflowException");
4504 s390_brasl (code
, s390_r14
,0);
4508 case OP_S390_MOVE
: {
4509 if (ins
->backend
.size
> 0) {
4510 if (ins
->backend
.size
<= 256) {
4511 s390_mvc (code
, ins
->backend
.size
, ins
->dreg
,
4512 ins
->inst_offset
, ins
->sreg1
, ins
->inst_imm
);
4514 s390_lgr (code
, s390_r0
, ins
->dreg
);
4515 if (ins
->inst_offset
> 0) {
4516 if (s390_is_imm16 (ins
->inst_offset
)) {
4517 s390_aghi (code
, s390_r0
, ins
->inst_offset
);
4518 } else if (s390_is_imm32 (ins
->inst_offset
)) {
4519 s390_agfi (code
, s390_r0
, ins
->inst_offset
);
4521 S390_SET (code
, s390_r13
, ins
->inst_offset
);
4522 s390_agr (code
, s390_r0
, s390_r13
);
4525 s390_lgr (code
, s390_r12
, ins
->sreg1
);
4526 if (ins
->inst_imm
> 0) {
4527 if (s390_is_imm16 (ins
->inst_imm
)) {
4528 s390_aghi (code
, s390_r12
, ins
->inst_imm
);
4529 } else if (s390_is_imm32 (ins
->inst_imm
)) {
4530 s390_agfi (code
, s390_r12
, ins
->inst_imm
);
4532 S390_SET (code
, s390_r13
, ins
->inst_imm
);
4533 s390_agr (code
, s390_r12
, s390_r13
);
4536 if (s390_is_imm16 (ins
->backend
.size
)) {
4537 s390_lghi (code
, s390_r1
, ins
->backend
.size
);
4538 } else if (s390_is_imm32 (ins
->inst_offset
)) {
4539 s390_agfi (code
, s390_r1
, ins
->backend
.size
);
4541 S390_SET (code
, s390_r13
, ins
->backend
.size
);
4542 s390_agr (code
, s390_r1
, s390_r13
);
4544 s390_lgr (code
, s390_r13
, s390_r1
);
4545 s390_mvcle(code
, s390_r0
, s390_r12
, 0, 0);
4551 case OP_ATOMIC_ADD_I8
: {
4552 if (mono_hwcap_s390x_has_ia
) {
4553 s390_laag (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4554 s390_agr (code
, ins
->dreg
, ins
->sreg2
);
4556 s390_lgr (code
, s390_r1
, ins
->sreg2
);
4557 s390_lg (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4558 s390_agr (code
, s390_r1
, s390_r0
);
4559 s390_csg (code
, s390_r0
, s390_r1
, ins
->inst_basereg
, ins
->inst_offset
);
4560 s390_jnz (code
, -10);
4561 s390_lgr (code
, ins
->dreg
, s390_r1
);
4565 case OP_ATOMIC_EXCHANGE_I8
: {
4566 s390_lg (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4567 s390_csg (code
, s390_r0
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4568 s390_jnz (code
, -6);
4569 s390_lgr (code
, ins
->dreg
, s390_r0
);
4572 case OP_ATOMIC_ADD_I4
: {
4573 if (mono_hwcap_s390x_has_ia
) {
4574 s390_laa (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4575 s390_ar (code
, ins
->dreg
, ins
->sreg2
);
4577 s390_lgfr(code
, s390_r1
, ins
->sreg2
);
4578 s390_lgf (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4579 s390_agr (code
, s390_r1
, s390_r0
);
4580 s390_cs (code
, s390_r0
, s390_r1
, ins
->inst_basereg
, ins
->inst_offset
);
4581 s390_jnz (code
, -9);
4582 s390_lgfr(code
, ins
->dreg
, s390_r1
);
4586 case OP_ATOMIC_EXCHANGE_I4
: {
4587 s390_l (code
, s390_r0
, 0, ins
->inst_basereg
, ins
->inst_offset
);
4588 s390_cs (code
, s390_r0
, ins
->sreg2
, ins
->inst_basereg
, ins
->inst_offset
);
4589 s390_jnz (code
, -4);
4590 s390_lgfr(code
, ins
->dreg
, s390_r0
);
4593 case OP_S390_BKCHAIN
: {
4594 s390_lgr (code
, ins
->dreg
, ins
->sreg1
);
4595 if (s390_is_imm16 (cfg
->stack_offset
)) {
4596 s390_aghi (code
, ins
->dreg
, cfg
->stack_offset
);
4597 } else if (s390_is_imm32 (cfg
->stack_offset
)) {
4598 s390_agfi (code
, ins
->dreg
, cfg
->stack_offset
);
4600 S390_SET (code
, s390_r13
, cfg
->stack_offset
);
4601 s390_agr (code
, ins
->dreg
, s390_r13
);
4605 case OP_MEMORY_BARRIER
:
4608 case OP_LIVERANGE_START
: {
4609 if (cfg
->verbose_level
> 1)
4610 printf ("R%d START=0x%x\n", MONO_VARINFO (cfg
, ins
->inst_c0
)->vreg
, (int)(code
- cfg
->native_code
));
4611 MONO_VARINFO (cfg
, ins
->inst_c0
)->live_range_start
= code
- cfg
->native_code
;
4614 case OP_LIVERANGE_END
: {
4615 if (cfg
->verbose_level
> 1)
4616 printf ("R%d END=0x%x\n", MONO_VARINFO (cfg
, ins
->inst_c0
)->vreg
, (int)(code
- cfg
->native_code
));
4617 MONO_VARINFO (cfg
, ins
->inst_c0
)->live_range_end
= code
- cfg
->native_code
;
4620 case OP_GC_SAFE_POINT
: {
4623 s390_ltg (code
, s390_r0
, 0, ins
->sreg1
, 0);
4624 s390_jz (code
, 0); CODEPTR(code
, br
);
4625 mono_add_patch_info (cfg
, code
- cfg
->native_code
, MONO_PATCH_INFO_JIT_ICALL_ID
,
4626 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll
));
4627 S390_CALL_TEMPLATE (code
, s390_r14
);
4631 case OP_GC_LIVENESS_DEF
:
4632 case OP_GC_LIVENESS_USE
:
4633 case OP_GC_PARAM_SLOT_LIVENESS_DEF
:
4634 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
4636 case OP_GC_SPILL_SLOT_LIVENESS_DEF
:
4637 ins
->backend
.pc_offset
= code
- cfg
->native_code
;
4638 bb
->spill_slot_defs
= g_slist_prepend_mempool (cfg
->mempool
, bb
->spill_slot_defs
, ins
);
4640 #ifdef MONO_ARCH_SIMD_INTRINSICS
4642 s390x_addps (code
, ins
->sreg1
, ins
->sreg2
);
4645 s390x_divps (code
, ins
->sreg1
, ins
->sreg2
);
4648 s390x_mulps (code
, ins
->sreg1
, ins
->sreg2
);
4651 s390x_subps (code
, ins
->sreg1
, ins
->sreg2
);
4654 s390x_maxps (code
, ins
->sreg1
, ins
->sreg2
);
4657 s390x_minps (code
, ins
->sreg1
, ins
->sreg2
);
4660 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 7);
4661 s390x_cmpps_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4664 s390x_andps (code
, ins
->sreg1
, ins
->sreg2
);
4667 s390x_andnps (code
, ins
->sreg1
, ins
->sreg2
);
4670 s390x_orps (code
, ins
->sreg1
, ins
->sreg2
);
4673 s390x_xorps (code
, ins
->sreg1
, ins
->sreg2
);
4676 s390x_sqrtps (code
, ins
->dreg
, ins
->sreg1
);
4679 s390x_rsqrtps (code
, ins
->dreg
, ins
->sreg1
);
4682 s390x_rcpps (code
, ins
->dreg
, ins
->sreg1
);
4685 s390x_addsubps (code
, ins
->sreg1
, ins
->sreg2
);
4688 s390x_haddps (code
, ins
->sreg1
, ins
->sreg2
);
4691 s390x_hsubps (code
, ins
->sreg1
, ins
->sreg2
);
4694 s390x_movshdup (code
, ins
->dreg
, ins
->sreg1
);
4697 s390x_movsldup (code
, ins
->dreg
, ins
->sreg1
);
4700 case OP_PSHUFLEW_HIGH
:
4701 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4702 s390x_pshufhw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
4704 case OP_PSHUFLEW_LOW
:
4705 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4706 s390x_pshuflw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
4709 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4710 s390x_pshufd_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
4713 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0xFF);
4714 s390x_shufps_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4717 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 0x3);
4718 s390x_shufpd_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4722 s390x_addpd (code
, ins
->sreg1
, ins
->sreg2
);
4725 s390x_divpd (code
, ins
->sreg1
, ins
->sreg2
);
4728 s390x_mulpd (code
, ins
->sreg1
, ins
->sreg2
);
4731 s390x_subpd (code
, ins
->sreg1
, ins
->sreg2
);
4734 s390x_maxpd (code
, ins
->sreg1
, ins
->sreg2
);
4737 s390x_minpd (code
, ins
->sreg1
, ins
->sreg2
);
4740 g_assert (ins
->inst_c0
>= 0 && ins
->inst_c0
<= 7);
4741 s390x_cmppd_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
4744 s390x_andpd (code
, ins
->sreg1
, ins
->sreg2
);
4747 s390x_andnpd (code
, ins
->sreg1
, ins
->sreg2
);
4750 s390x_orpd (code
, ins
->sreg1
, ins
->sreg2
);
4753 s390x_xorpd (code
, ins
->sreg1
, ins
->sreg2
);
4756 s390x_sqrtpd (code
, ins
->dreg
, ins
->sreg1
);
4759 s390x_addsubpd (code
, ins
->sreg1
, ins
->sreg2
);
4762 s390x_haddpd (code
, ins
->sreg1
, ins
->sreg2
);
4765 s390x_hsubpd (code
, ins
->sreg1
, ins
->sreg2
);
4768 s390x_movddup (code
, ins
->dreg
, ins
->sreg1
);
4771 case OP_EXTRACT_MASK
:
4772 s390x_pmovmskb (code
, ins
->dreg
, ins
->sreg1
);
4776 s390x_pand (code
, ins
->sreg1
, ins
->sreg2
);
4779 s390x_por (code
, ins
->sreg1
, ins
->sreg2
);
4782 s390x_pxor (code
, ins
->sreg1
, ins
->sreg2
);
4786 s390x_paddb (code
, ins
->sreg1
, ins
->sreg2
);
4789 s390x_paddw (code
, ins
->sreg1
, ins
->sreg2
);
4792 s390x_paddd (code
, ins
->sreg1
, ins
->sreg2
);
4795 s390x_paddq (code
, ins
->sreg1
, ins
->sreg2
);
4799 s390x_psubb (code
, ins
->sreg1
, ins
->sreg2
);
4802 s390x_psubw (code
, ins
->sreg1
, ins
->sreg2
);
4805 s390x_psubd (code
, ins
->sreg1
, ins
->sreg2
);
4808 s390x_psubq (code
, ins
->sreg1
, ins
->sreg2
);
4812 s390x_pmaxub (code
, ins
->sreg1
, ins
->sreg2
);
4815 s390x_pmaxuw (code
, ins
->sreg1
, ins
->sreg2
);
4818 s390x_pmaxud (code
, ins
->sreg1
, ins
->sreg2
);
4822 s390x_pmaxsb (code
, ins
->sreg1
, ins
->sreg2
);
4825 s390x_pmaxsw (code
, ins
->sreg1
, ins
->sreg2
);
4828 s390x_pmaxsd (code
, ins
->sreg1
, ins
->sreg2
);
4832 s390x_pavgb (code
, ins
->sreg1
, ins
->sreg2
);
4835 s390x_pavgw (code
, ins
->sreg1
, ins
->sreg2
);
4839 s390x_pminub (code
, ins
->sreg1
, ins
->sreg2
);
4842 s390x_pminuw (code
, ins
->sreg1
, ins
->sreg2
);
4845 s390x_pminud (code
, ins
->sreg1
, ins
->sreg2
);
4849 s390x_pminsb (code
, ins
->sreg1
, ins
->sreg2
);
4852 s390x_pminsw (code
, ins
->sreg1
, ins
->sreg2
);
4855 s390x_pminsd (code
, ins
->sreg1
, ins
->sreg2
);
4859 s390x_pcmpeqb (code
, ins
->sreg1
, ins
->sreg2
);
4862 s390x_pcmpeqw (code
, ins
->sreg1
, ins
->sreg2
);
4865 s390x_pcmpeqd (code
, ins
->sreg1
, ins
->sreg2
);
4868 s390x_pcmpeqq (code
, ins
->sreg1
, ins
->sreg2
);
4872 s390x_pcmpgtb (code
, ins
->sreg1
, ins
->sreg2
);
4875 s390x_pcmpgtw (code
, ins
->sreg1
, ins
->sreg2
);
4878 s390x_pcmpgtd (code
, ins
->sreg1
, ins
->sreg2
);
4881 s390x_pcmpgtq (code
, ins
->sreg1
, ins
->sreg2
);
4884 case OP_PSUM_ABS_DIFF
:
4885 s390x_psadbw (code
, ins
->sreg1
, ins
->sreg2
);
4888 case OP_UNPACK_LOWB
:
4889 s390x_punpcklbw (code
, ins
->sreg1
, ins
->sreg2
);
4891 case OP_UNPACK_LOWW
:
4892 s390x_punpcklwd (code
, ins
->sreg1
, ins
->sreg2
);
4894 case OP_UNPACK_LOWD
:
4895 s390x_punpckldq (code
, ins
->sreg1
, ins
->sreg2
);
4897 case OP_UNPACK_LOWQ
:
4898 s390x_punpcklqdq (code
, ins
->sreg1
, ins
->sreg2
);
4900 case OP_UNPACK_LOWPS
:
4901 s390x_unpcklps (code
, ins
->sreg1
, ins
->sreg2
);
4903 case OP_UNPACK_LOWPD
:
4904 s390x_unpcklpd (code
, ins
->sreg1
, ins
->sreg2
);
4907 case OP_UNPACK_HIGHB
:
4908 s390x_punpckhbw (code
, ins
->sreg1
, ins
->sreg2
);
4910 case OP_UNPACK_HIGHW
:
4911 s390x_punpckhwd (code
, ins
->sreg1
, ins
->sreg2
);
4913 case OP_UNPACK_HIGHD
:
4914 s390x_punpckhdq (code
, ins
->sreg1
, ins
->sreg2
);
4916 case OP_UNPACK_HIGHQ
:
4917 s390x_punpckhqdq (code
, ins
->sreg1
, ins
->sreg2
);
4919 case OP_UNPACK_HIGHPS
:
4920 s390x_unpckhps (code
, ins
->sreg1
, ins
->sreg2
);
4922 case OP_UNPACK_HIGHPD
:
4923 s390x_unpckhpd (code
, ins
->sreg1
, ins
->sreg2
);
4927 s390x_packsswb (code
, ins
->sreg1
, ins
->sreg2
);
4930 s390x_packssdw (code
, ins
->sreg1
, ins
->sreg2
);
4933 s390x_packuswb (code
, ins
->sreg1
, ins
->sreg2
);
4936 s390x_packusdw (code
, ins
->sreg1
, ins
->sreg2
);
4939 case OP_PADDB_SAT_UN
:
4940 s390x_paddusb (code
, ins
->sreg1
, ins
->sreg2
);
4942 case OP_PSUBB_SAT_UN
:
4943 s390x_psubusb (code
, ins
->sreg1
, ins
->sreg2
);
4945 case OP_PADDW_SAT_UN
:
4946 s390x_paddusw (code
, ins
->sreg1
, ins
->sreg2
);
4948 case OP_PSUBW_SAT_UN
:
4949 s390x_psubusw (code
, ins
->sreg1
, ins
->sreg2
);
4953 s390x_paddsb (code
, ins
->sreg1
, ins
->sreg2
);
4956 s390x_psubsb (code
, ins
->sreg1
, ins
->sreg2
);
4959 s390x_paddsw (code
, ins
->sreg1
, ins
->sreg2
);
4962 s390x_psubsw (code
, ins
->sreg1
, ins
->sreg2
);
4966 s390x_pmullw (code
, ins
->sreg1
, ins
->sreg2
);
4969 s390x_pmulld (code
, ins
->sreg1
, ins
->sreg2
);
4972 s390x_pmuludq (code
, ins
->sreg1
, ins
->sreg2
);
4974 case OP_PMULW_HIGH_UN
:
4975 s390x_pmulhuw (code
, ins
->sreg1
, ins
->sreg2
);
4978 s390x_pmulhw (code
, ins
->sreg1
, ins
->sreg2
);
4982 s390x_psrlw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
4985 s390x_psrlw (code
, ins
->dreg
, ins
->sreg2
);
4989 s390x_psraw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
4992 s390x_psraw (code
, ins
->dreg
, ins
->sreg2
);
4996 s390x_psllw_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
4999 s390x_psllw (code
, ins
->dreg
, ins
->sreg2
);
5003 s390x_psrld_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5006 s390x_psrld (code
, ins
->dreg
, ins
->sreg2
);
5010 s390x_psrad_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5013 s390x_psrad (code
, ins
->dreg
, ins
->sreg2
);
5017 s390x_pslld_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5020 s390x_pslld (code
, ins
->dreg
, ins
->sreg2
);
5024 s390x_psrlq_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5027 s390x_psrlq (code
, ins
->dreg
, ins
->sreg2
);
5030 /*TODO: This is appart of the sse spec but not added
5032 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5035 s390x_psraq (code, ins->dreg, ins->sreg2);
5040 s390x_psllq_reg_imm (code
, ins
->dreg
, ins
->inst_imm
);
5043 s390x_psllq (code
, ins
->dreg
, ins
->sreg2
);
5046 s390x_cvtdq2pd (code
, ins
->dreg
, ins
->sreg1
);
5049 s390x_cvtdq2ps (code
, ins
->dreg
, ins
->sreg1
);
5052 s390x_cvtpd2dq (code
, ins
->dreg
, ins
->sreg1
);
5055 s390x_cvtpd2ps (code
, ins
->dreg
, ins
->sreg1
);
5058 s390x_cvtps2dq (code
, ins
->dreg
, ins
->sreg1
);
5061 s390x_cvtps2pd (code
, ins
->dreg
, ins
->sreg1
);
5064 s390x_cvttpd2dq (code
, ins
->dreg
, ins
->sreg1
);
5067 s390x_cvttps2dq (code
, ins
->dreg
, ins
->sreg1
);
5071 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5074 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5078 amd64_movhlps (code
, MONO_ARCH_FP_SCRATCH_REG
, ins
->sreg1
);
5079 amd64_movd_reg_xreg_size (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
, 8);
5081 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 8);
5086 amd64_movd_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5088 amd64_shift_reg_imm (code
, X86_SHR
, ins
->dreg
, ins
->inst_c0
* 8);
5089 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, ins
->opcode
== OP_EXTRACT_I1
, FALSE
);
5093 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5095 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5096 s390x_pextrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5097 amd64_widen_reg_size (code
, ins
->dreg
, ins
->dreg
, ins
->opcode
== OP_EXTRACT_I2
, TRUE
, 4);
5101 amd64_movhlps (code
, ins
->dreg
, ins
->sreg1
);
5103 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5106 s390x_pinsrw_imm (code
, ins
->sreg1
, ins
->sreg2
, ins
->inst_c0
);
5108 case OP_EXTRACTX_U2
:
5109 s390x_pextrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
);
5111 case OP_INSERTX_U1_SLOW
:
5112 /*sreg1 is the extracted ireg (scratch)
5113 /sreg2 is the to be inserted ireg (scratch)
5114 /dreg is the xreg to receive the value*/
5116 /*clear the bits from the extracted word*/
5117 amd64_alu_reg_imm (code
, X86_AND
, ins
->sreg1
, ins
->inst_c0
& 1 ? 0x00FF : 0xFF00);
5118 /*shift the value to insert if needed*/
5119 if (ins
->inst_c0
& 1)
5120 amd64_shift_reg_imm_size (code
, X86_SHL
, ins
->sreg2
, 8, 4);
5121 /*join them together*/
5122 amd64_alu (code
, X86_OR
, ins
->sreg1
, ins
->sreg2
);
5123 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_c0
/ 2);
5125 case OP_INSERTX_I4_SLOW
:
5126 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_c0
* 2);
5127 amd64_shift_reg_imm (code
, X86_SHR
, ins
->sreg2
, 16);
5128 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg2
, ins
->inst_c0
* 2 + 1);
5130 case OP_INSERTX_I8_SLOW
:
5131 amd64_movd_xreg_reg_size(code
, MONO_ARCH_FP_SCRATCH_REG
, ins
->sreg2
, 8);
5133 amd64_movlhps (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
);
5135 s390x_movsd (code
, ins
->dreg
, MONO_ARCH_FP_SCRATCH_REG
);
5138 case OP_INSERTX_R4_SLOW
:
5139 switch (ins
->inst_c0
) {
5142 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5144 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5147 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(1, 0, 2, 3));
5149 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5151 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5152 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(1, 0, 2, 3));
5155 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(2, 1, 0, 3));
5157 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5159 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5160 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(2, 1, 0, 3));
5163 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(3, 1, 2, 0));
5165 s390x_movss (code
, ins
->dreg
, ins
->sreg2
);
5167 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->sreg2
);
5168 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, mono_simd_shuffle_mask(3, 1, 2, 0));
5172 case OP_INSERTX_R8_SLOW
:
5174 amd64_movlhps (code
, ins
->dreg
, ins
->sreg2
);
5176 s390x_movsd (code
, ins
->dreg
, ins
->sreg2
);
5178 case OP_STOREX_MEMBASE_REG
:
5179 case OP_STOREX_MEMBASE
:
5180 s390x_movups_membase_reg (code
, ins
->dreg
, ins
->inst_offset
, ins
->sreg1
);
5182 case OP_LOADX_MEMBASE
:
5183 s390x_movups_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5185 case OP_LOADX_ALIGNED_MEMBASE
:
5186 s390x_movaps_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5188 case OP_STOREX_ALIGNED_MEMBASE_REG
:
5189 s390x_movaps_membase_reg (code
, ins
->dreg
, ins
->inst_offset
, ins
->sreg1
);
5191 case OP_STOREX_NTA_MEMBASE_REG
:
5192 s390x_movntps_reg_membase (code
, ins
->dreg
, ins
->sreg1
, ins
->inst_offset
);
5194 case OP_PREFETCH_MEMBASE
:
5195 s390x_prefetch_reg_membase (code
, ins
->backend
.arg_info
, ins
->sreg1
, ins
->inst_offset
);
5199 /*FIXME the peephole pass should have killed this*/
5200 if (ins
->dreg
!= ins
->sreg1
)
5201 s390x_movaps (code
, ins
->dreg
, ins
->sreg1
);
5204 s390x_pxor (code
, ins
->dreg
, ins
->dreg
);
5206 case OP_ICONV_TO_R4_RAW
:
5207 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5210 case OP_FCONV_TO_R8_X
:
5211 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5214 case OP_XCONV_R8_TO_I4
:
5215 s390x_cvttsd2si_reg_xreg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5216 switch (ins
->backend
.source_opcode
) {
5217 case OP_FCONV_TO_I1
:
5218 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, TRUE
, FALSE
);
5220 case OP_FCONV_TO_U1
:
5221 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, FALSE
, FALSE
);
5223 case OP_FCONV_TO_I2
:
5224 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, TRUE
, TRUE
);
5226 case OP_FCONV_TO_U2
:
5227 amd64_widen_reg (code
, ins
->dreg
, ins
->dreg
, FALSE
, TRUE
);
5233 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, 0);
5234 s390x_pinsrw_imm (code
, ins
->dreg
, ins
->sreg1
, 1);
5235 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5238 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 4);
5239 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5242 amd64_movd_xreg_reg_size (code
, ins
->dreg
, ins
->sreg1
, 8);
5243 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0x44);
5247 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5249 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5250 s390x_cvtsd2ss (code
, ins
->dreg
, ins
->dreg
);
5252 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0);
5255 s390x_movsd (code
, ins
->dreg
, ins
->sreg1
);
5256 s390x_pshufd_imm (code
, ins
->dreg
, ins
->dreg
, 0x44);
5260 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins
->opcode
), __FUNCTION__
);
5261 g_assert_not_reached ();
5264 if ((cfg
->opt
& MONO_OPT_BRANCH
) && ((code
- cfg
->native_code
- offset
) > max_len
)) {
5265 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5266 mono_inst_name (ins
->opcode
), max_len
, code
- cfg
->native_code
- offset
);
5267 g_assert_not_reached ();
5271 set_code_cursor (cfg
, code
);
5274 /*========================= End of Function ========================*/
5276 /*------------------------------------------------------------------*/
5278 /* Name - mono_arch_register_lowlevel_calls */
5280 /* Function - Register routines to help with --trace operation. */
5282 /*------------------------------------------------------------------*/
5285 mono_arch_register_lowlevel_calls (void)
5289 /*========================= End of Function ========================*/
5291 /*------------------------------------------------------------------*/
5293 /* Name - mono_arch_patch_code */
5295 /* Function - Process the patch data created during the */
5296 /* instruction build process. This resolves jumps, */
5297 /* calls, variables etc. */
5299 /*------------------------------------------------------------------*/
5302 mono_arch_patch_code (MonoCompile
*cfg
, MonoMethod
*method
, MonoDomain
*domain
,
5303 guint8
*code
, MonoJumpInfo
*ji
, gboolean run_cctors
,
5306 MonoJumpInfo
*patch_info
;
5310 for (patch_info
= ji
; patch_info
; patch_info
= patch_info
->next
) {
5311 unsigned char *ip
= patch_info
->ip
.i
+ code
;
5312 gconstpointer target
= NULL
;
5314 target
= mono_resolve_patch_target (method
, domain
, code
,
5315 patch_info
, run_cctors
, error
);
5316 return_if_nok (error
);
5318 switch (patch_info
->type
) {
5319 case MONO_PATCH_INFO_IP
:
5320 case MONO_PATCH_INFO_LDSTR
:
5321 case MONO_PATCH_INFO_TYPE_FROM_HANDLE
:
5322 case MONO_PATCH_INFO_LDTOKEN
:
5323 case MONO_PATCH_INFO_EXC
:
5324 s390_patch_addr (ip
, (guint64
) target
);
5326 case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR
:
5327 case MONO_PATCH_INFO_METHOD
:
5328 case MONO_PATCH_INFO_JIT_ICALL_ID
:
5329 case MONO_PATCH_INFO_JIT_ICALL_ADDR
:
5330 case MONO_PATCH_INFO_RGCTX_FETCH
:
5331 case MONO_PATCH_INFO_ABS
: {
5332 S390_EMIT_CALL (ip
, target
);
5335 case MONO_PATCH_INFO_SWITCH
:
5336 /*----------------------------------*/
5337 /* ip points at the basr r13,0/j +4 */
5338 /* instruction the vtable value */
5339 /* follows this (i.e. ip+6) */
5340 /*----------------------------------*/
5341 S390_EMIT_LOAD (ip
, target
);
5343 case MONO_PATCH_INFO_METHODCONST
:
5344 case MONO_PATCH_INFO_CLASS
:
5345 case MONO_PATCH_INFO_IMAGE
:
5346 case MONO_PATCH_INFO_FIELD
:
5347 case MONO_PATCH_INFO_IID
:
5348 case MONO_PATCH_INFO_EXC_NAME
:
5349 target
= S390_RELATIVE(target
, ip
);
5350 s390_patch_rel (ip
, (guint64
) target
);
5352 case MONO_PATCH_INFO_R4
:
5353 case MONO_PATCH_INFO_R8
:
5354 g_assert_not_reached ();
5357 target
= S390_RELATIVE(target
, ip
);
5359 s390_patch_rel (ip
, (guint64
) target
);
5360 case MONO_PATCH_INFO_NONE
:
5366 /*========================= End of Function ========================*/
5368 /*------------------------------------------------------------------*/
5370 /* Name - mono_arch_emit_prolog */
5372 /* Function - Create the instruction sequence for a function */
5375 /*------------------------------------------------------------------*/
5378 mono_arch_emit_prolog (MonoCompile
*cfg
)
5380 MonoMethod
*method
= cfg
->method
;
5382 MonoMethodSignature
*sig
;
5384 long alloc_size
, pos
, max_offset
, i
, cfa_offset
= 0;
5388 int argsClobbered
= 0,
5392 cfg
->code_size
= 512;
5394 if (method
->save_lmf
)
5395 cfg
->code_size
+= 200;
5397 cfg
->native_code
= code
= g_malloc (cfg
->code_size
);
5399 mono_emit_unwind_op_def_cfa (cfg
, code
, STK_BASE
, 0);
5400 emit_unwind_regs(cfg
, code
, s390_r6
, s390_r14
, S390_REG_SAVE_OFFSET
);
5401 s390_stmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5402 mono_emit_unwind_op_offset (cfg
, code
, s390_r14
, S390_RET_ADDR_OFFSET
);
5403 mini_gc_set_slot_type_from_cfa (cfg
, S390_RET_ADDR_OFFSET
, SLOT_NOREF
);
5404 if (cfg
->arch
.bkchain_reg
!= -1)
5405 s390_lgr (code
, cfg
->arch
.bkchain_reg
, STK_BASE
);
5407 if (cfg
->flags
& MONO_CFG_HAS_ALLOCA
) {
5408 cfg
->used_int_regs
|= 1 << s390_r11
;
5411 if ((cfg
->arch
.used_fp_regs
& S390_FP_SAVE_MASK
) != 0) {
5412 for (int i
=8; i
<16; i
++) {
5413 if (cfg
->arch
.used_fp_regs
& (1 << i
))
5414 fpOffset
+= sizeof(double);
5416 fpOffset
= S390_ALIGN(fpOffset
, 16);
5418 cfg
->arch
.fpSize
= fpOffset
;
5420 alloc_size
= cfg
->stack_offset
+ fpOffset
;
5422 cfg
->stack_usage
= cfa_offset
= alloc_size
;
5423 s390_lgr (code
, s390_r11
, STK_BASE
);
5424 if (s390_is_imm16 (alloc_size
)) {
5425 s390_aghi (code
, STK_BASE
, -alloc_size
);
5426 } else if (s390_is_imm32 (alloc_size
)) {
5427 s390_agfi (code
, STK_BASE
, -alloc_size
);
5429 int stackSize
= alloc_size
;
5430 while (stackSize
> INT_MAX
) {
5431 s390_agfi (code
, STK_BASE
, -INT_MAX
);
5432 stackSize
-= INT_MAX
;
5434 s390_agfi (code
, STK_BASE
, -stackSize
);
5436 s390_stg (code
, s390_r11
, 0, STK_BASE
, 0);
5441 s390_lgr (code
, s390_r1
, s390_r11
);
5442 s390_aghi (code
, s390_r1
, -fpOffset
);
5443 for (int i
=8; i
<16; i
++) {
5444 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
5445 emit_unwind_regs(cfg
, code
, 16+i
, 16+i
, stkOffset
+fpOffset
);
5446 s390_std (code
, i
, 0, s390_r1
, stkOffset
);
5447 stkOffset
+= sizeof(double);
5452 mono_emit_unwind_op_def_cfa_offset (cfg
, code
, alloc_size
);
5454 if (cfg
->frame_reg
!= STK_BASE
)
5455 s390_lgr (code
, s390_r11
, STK_BASE
);
5457 mono_emit_unwind_op_def_cfa_reg (cfg
, code
, cfg
->frame_reg
);
5459 /* store runtime generic context */
5460 if (cfg
->rgctx_var
) {
5461 g_assert (cfg
->rgctx_var
->opcode
== OP_REGOFFSET
);
5463 s390_stg (code
, MONO_ARCH_RGCTX_REG
, 0,
5464 cfg
->rgctx_var
->inst_basereg
,
5465 cfg
->rgctx_var
->inst_offset
);
5468 /* compute max_offset in order to use short forward jumps
5469 * we always do it on s390 because the immediate displacement
5470 * for jumps is too small
5473 for (bb
= cfg
->bb_entry
; bb
; bb
= bb
->next_bb
) {
5475 bb
->max_offset
= max_offset
;
5477 MONO_BB_FOR_EACH_INS (bb
, ins
)
5478 max_offset
+= ins_get_size (ins
->opcode
);
5481 /* load arguments allocated to register from the stack */
5482 sig
= mono_method_signature_internal (method
);
5485 cinfo
= get_call_info (cfg
->mempool
, sig
);
5487 if (cinfo
->struct_ret
) {
5488 ArgInfo
*ainfo
= &cinfo
->ret
;
5489 inst
= cfg
->vret_addr
;
5490 inst
->backend
.size
= ainfo
->vtsize
;
5491 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5494 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
5495 ArgInfo
*ainfo
= cinfo
->args
+ i
;
5496 inst
= cfg
->args
[pos
];
5498 if (inst
->opcode
== OP_VTARG_ADDR
)
5499 inst
= inst
->inst_left
;
5501 if (inst
->opcode
== OP_REGVAR
) {
5502 if (ainfo
->regtype
== RegTypeGeneral
)
5503 s390_lgr (code
, inst
->dreg
, ainfo
->reg
);
5504 else if (ainfo
->regtype
== RegTypeFP
) {
5505 if (inst
->dreg
!= ainfo
->reg
) {
5506 s390_ldr (code
, inst
->dreg
, ainfo
->reg
);
5508 } else if (ainfo
->regtype
== RegTypeFPR4
) {
5510 s390_ledbr (code
, inst
->dreg
, ainfo
->reg
);
5511 } else if (ainfo
->regtype
== RegTypeBase
) {
5512 s390_lgr (code
, s390_r13
, STK_BASE
);
5513 s390_aghi (code
, s390_r13
, alloc_size
);
5514 s390_lg (code
, inst
->dreg
, 0, s390_r13
, ainfo
->offset
);
5516 g_assert_not_reached ();
5518 if (cfg
->verbose_level
> 2)
5519 g_print ("Argument %d assigned to register %s\n",
5520 pos
, mono_arch_regname (inst
->dreg
));
5522 if (ainfo
->regtype
== RegTypeGeneral
) {
5523 if (!((ainfo
->reg
>= 2) && (ainfo
->reg
<= 6)))
5524 g_assert_not_reached();
5525 switch (ainfo
->size
) {
5527 s390_stc (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5530 s390_sth (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5533 s390_st (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5536 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5539 } else if (ainfo
->regtype
== RegTypeBase
) {
5540 } else if (ainfo
->regtype
== RegTypeFP
) {
5541 s390_std (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5542 } else if (ainfo
->regtype
== RegTypeFPR4
) {
5543 s390_ste (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5544 } else if (ainfo
->regtype
== RegTypeStructByVal
) {
5545 int doffset
= inst
->inst_offset
;
5547 if (ainfo
->reg
!= STK_BASE
)
5551 s390_lgr (code
, s390_r13
, STK_BASE
);
5552 s390_aghi (code
, s390_r13
, alloc_size
);
5555 size
= (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
5556 ? mono_class_native_size(mono_class_from_mono_type_internal (inst
->inst_vtype
), NULL
)
5561 if (ainfo
->reg
== STK_BASE
)
5562 s390_ic (code
, reg
, 0, s390_r13
, ainfo
->offset
+7);
5563 s390_stc (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5566 if (ainfo
->reg
== STK_BASE
)
5567 s390_lh (code
, reg
, 0, s390_r13
, ainfo
->offset
+6);
5568 s390_sth (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5571 if (ainfo
->reg
== STK_BASE
)
5572 s390_l (code
, reg
, 0, s390_r13
, ainfo
->offset
+4);
5573 s390_st (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5576 if (ainfo
->reg
== STK_BASE
)
5577 s390_lg (code
, reg
, 0, s390_r13
, ainfo
->offset
);
5578 s390_stg (code
, reg
, 0, inst
->inst_basereg
, doffset
);
5581 } else if (ainfo
->regtype
== RegTypeStructByAddr
) {
5582 s390_stg (code
, ainfo
->reg
, 0, inst
->inst_basereg
, inst
->inst_offset
);
5583 } else if (ainfo
->regtype
== RegTypeStructByAddrOnStack
) {
5585 g_assert_not_reached ();
5590 if (method
->save_lmf
) {
5591 /*---------------------------------------------------------------*/
5592 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5593 /*---------------------------------------------------------------*/
5594 lmfOffset
= alloc_size
- sizeof(MonoLMF
);
5596 s390_lgr (code
, s390_r13
, cfg
->frame_reg
);
5597 s390_aghi (code
, s390_r13
, lmfOffset
);
5599 /*---------------------------------------------------------------*/
5600 /* Preserve the parameter registers while we fix up the lmf */
5601 /*---------------------------------------------------------------*/
5602 s390_stmg (code
, s390_r2
, s390_r6
, s390_r13
,
5603 G_STRUCT_OFFSET(MonoLMF
, pregs
[0]));
5605 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[0]), SLOT_NOREF
);
5606 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[1]), SLOT_NOREF
);
5607 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[2]), SLOT_NOREF
);
5608 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[3]), SLOT_NOREF
);
5609 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, pregs
[4]), SLOT_NOREF
);
5611 /*---------------------------------------------------------------*/
5612 /* On return from this call r2 have the address of the &lmf */
5613 /*---------------------------------------------------------------*/
5614 mono_add_patch_info (cfg
, code
- cfg
->native_code
,
5615 MONO_PATCH_INFO_JIT_ICALL_ID
,
5616 GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr
));
5617 S390_CALL_TEMPLATE(code
, s390_r1
);
5619 /*---------------------------------------------------------------*/
5620 /* Set lmf.lmf_addr = jit_tls->lmf */
5621 /*---------------------------------------------------------------*/
5622 s390_stg (code
, s390_r2
, 0, s390_r13
,
5623 G_STRUCT_OFFSET(MonoLMF
, lmf_addr
));
5624 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, lmf_addr
), SLOT_NOREF
);
5626 /*---------------------------------------------------------------*/
5627 /* Get current lmf */
5628 /*---------------------------------------------------------------*/
5629 s390_lg (code
, s390_r0
, 0, s390_r2
, 0);
5631 /*---------------------------------------------------------------*/
5632 /* Set our lmf as the current lmf */
5633 /*---------------------------------------------------------------*/
5634 s390_stg (code
, s390_r13
, 0, s390_r2
, 0);
5636 /*---------------------------------------------------------------*/
5637 /* Have our lmf.previous_lmf point to the last lmf */
5638 /*---------------------------------------------------------------*/
5639 s390_stg (code
, s390_r0
, 0, s390_r13
,
5640 G_STRUCT_OFFSET(MonoLMF
, previous_lmf
));
5641 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, previous_lmf
), SLOT_NOREF
);
5643 /*---------------------------------------------------------------*/
5644 /* save method info */
5645 /*---------------------------------------------------------------*/
5646 S390_SET (code
, s390_r1
, method
);
5647 s390_stg (code
, s390_r1
, 0, s390_r13
,
5648 G_STRUCT_OFFSET(MonoLMF
, method
));
5649 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, method
), SLOT_NOREF
);
5651 /*---------------------------------------------------------------*/
5652 /* save the current IP */
5653 /*---------------------------------------------------------------*/
5654 s390_stg (code
, STK_BASE
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, ebp
));
5655 s390_basr (code
, s390_r1
, 0);
5656 s390_stg (code
, s390_r1
, 0, s390_r13
, G_STRUCT_OFFSET(MonoLMF
, eip
));
5657 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, ebp
), SLOT_NOREF
);
5658 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, eip
), SLOT_NOREF
);
5660 /*---------------------------------------------------------------*/
5661 /* Save general and floating point registers */
5662 /*---------------------------------------------------------------*/
5663 s390_stmg (code
, s390_r2
, s390_r12
, s390_r13
,
5664 G_STRUCT_OFFSET(MonoLMF
, gregs
[2]));
5665 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[0]), SLOT_NOREF
);
5666 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[1]), SLOT_NOREF
);
5667 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[2]), SLOT_NOREF
);
5668 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[3]), SLOT_NOREF
);
5669 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[4]), SLOT_NOREF
);
5670 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[5]), SLOT_NOREF
);
5671 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[6]), SLOT_NOREF
);
5672 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[7]), SLOT_NOREF
);
5673 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[8]), SLOT_NOREF
);
5674 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[9]), SLOT_NOREF
);
5675 mini_gc_set_slot_type_from_fp (cfg
, lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, gregs
[10]), SLOT_NOREF
);
5677 fpOffset
= lmfOffset
+ MONO_STRUCT_OFFSET (MonoLMF
, fregs
[0]);
5678 for (i
= 0; i
< 16; i
++) {
5679 s390_std (code
, i
, 0, s390_r13
,
5680 G_STRUCT_OFFSET(MonoLMF
, fregs
[i
]));
5681 mini_gc_set_slot_type_from_fp (cfg
, fpOffset
, SLOT_NOREF
);
5682 fpOffset
+= sizeof(double);
5685 /*---------------------------------------------------------------*/
5686 /* Restore the parameter registers now that we've set up the lmf */
5687 /*---------------------------------------------------------------*/
5688 s390_lmg (code
, s390_r2
, s390_r6
, s390_r13
,
5689 G_STRUCT_OFFSET(MonoLMF
, pregs
[0]));
5692 if (cfg
->method
->save_lmf
)
5693 argsClobbered
= TRUE
;
5696 * Optimize the common case of the first bblock making a call with the same
5697 * arguments as the method. This works because the arguments are still in their
5698 * original argument registers.
5700 if (!argsClobbered
) {
5701 MonoBasicBlock
*first_bb
= cfg
->bb_entry
;
5703 int filter
= FILTER_IL_SEQ_POINT
;
5705 next
= mono_bb_first_inst (first_bb
, filter
);
5706 if (!next
&& first_bb
->next_bb
) {
5707 first_bb
= first_bb
->next_bb
;
5708 next
= mono_bb_first_inst (first_bb
, filter
);
5711 if (first_bb
->in_count
> 1)
5714 for (i
= 0; next
&& i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
5715 ArgInfo
*ainfo
= cinfo
->args
+ i
;
5716 gboolean match
= FALSE
;
5718 inst
= cfg
->args
[i
];
5719 if (inst
->opcode
!= OP_REGVAR
) {
5720 switch (ainfo
->regtype
) {
5721 case RegTypeGeneral
: {
5722 if (((next
->opcode
== OP_LOAD_MEMBASE
) ||
5723 (next
->opcode
== OP_LOADI4_MEMBASE
)) &&
5724 next
->inst_basereg
== inst
->inst_basereg
&&
5725 next
->inst_offset
== inst
->inst_offset
) {
5726 if (next
->dreg
== ainfo
->reg
) {
5730 next
->opcode
= OP_MOVE
;
5731 next
->sreg1
= ainfo
->reg
;
5732 /* Only continue if the instruction doesn't change argument regs */
5733 if (next
->dreg
== ainfo
->reg
)
5743 /* Argument allocated to (non-volatile) register */
5744 switch (ainfo
->regtype
) {
5745 case RegTypeGeneral
:
5746 if (next
->opcode
== OP_MOVE
&&
5747 next
->sreg1
== inst
->dreg
&&
5748 next
->dreg
== ainfo
->reg
) {
5759 next
= mono_inst_next (next
, filter
);
5766 set_code_cursor (cfg
, code
);
5771 /*========================= End of Function ========================*/
5773 /*------------------------------------------------------------------*/
5775 /* Name - mono_arch_emit_epilog */
5777 /* Function - Emit the instructions for a function epilog. */
5779 /*------------------------------------------------------------------*/
5782 mono_arch_emit_epilog (MonoCompile
*cfg
)
5784 MonoMethod
*method
= cfg
->method
;
5786 int max_epilog_size
= 96;
5789 if (cfg
->method
->save_lmf
)
5790 max_epilog_size
+= 128;
5792 code
= realloc_code (cfg
, max_epilog_size
);
5794 if (method
->save_lmf
)
5795 restoreLMF(code
, cfg
->frame_reg
, cfg
->stack_usage
);
5797 code
= backUpStackPtr(cfg
, code
);
5799 if (cfg
->arch
.fpSize
!= 0) {
5800 fpOffset
= -cfg
->arch
.fpSize
;
5801 for (int i
=8; i
<16; i
++) {
5802 if (cfg
->arch
.used_fp_regs
& (1 << i
)) {
5803 s390_ldy (code
, i
, 0, STK_BASE
, fpOffset
);
5804 fpOffset
+= sizeof(double);
5809 s390_lmg (code
, s390_r6
, s390_r14
, STK_BASE
, S390_REG_SAVE_OFFSET
);
5810 s390_br (code
, s390_r14
);
5812 set_code_cursor (cfg
, code
);
5816 /*========================= End of Function ========================*/
5818 /*------------------------------------------------------------------*/
5820 /* Name - mono_arch_emit_exceptions */
5822 /* Function - Emit the blocks to handle exception conditions. */
5824 /*------------------------------------------------------------------*/
5827 mono_arch_emit_exceptions (MonoCompile
*cfg
)
5829 MonoJumpInfo
*patch_info
;
5835 MonoClass
*exc_classes
[MAX_EXC
];
5836 guint8
*exc_throw_start
[MAX_EXC
];
5838 for (patch_info
= cfg
->patch_info
;
5840 patch_info
= patch_info
->next
) {
5841 if (patch_info
->type
== MONO_PATCH_INFO_EXC
)
5845 code_size
= exc_count
* 48;
5847 code
= realloc_code (cfg
, code_size
);
5849 /*---------------------------------------------------------------------*/
5850 /* Add code to raise exceptions */
5851 /*---------------------------------------------------------------------*/
5852 for (patch_info
= cfg
->patch_info
; patch_info
; patch_info
= patch_info
->next
) {
5853 switch (patch_info
->type
) {
5854 case MONO_PATCH_INFO_EXC
: {
5855 guint8
*ip
= patch_info
->ip
.i
+ cfg
->native_code
;
5856 MonoClass
*exc_class
;
5859 /*-----------------------------------------------------*/
5860 /* Patch the branch in epilog to come here */
5861 /*-----------------------------------------------------*/
5862 s390_patch_rel (ip
+ 2, (guint64
) S390_RELATIVE(code
,ip
));
5864 exc_class
= mono_class_load_from_name (mono_defaults
.corlib
,
5866 patch_info
->data
.name
);
5867 throw_ip
= patch_info
->ip
.i
;
5869 for (iExc
= 0; iExc
< nThrows
; ++iExc
)
5870 if (exc_classes
[iExc
] == exc_class
)
5873 if (iExc
< nThrows
) {
5874 s390_jcl (code
, S390_CC_UN
,
5875 (guint64
) exc_throw_start
[iExc
]);
5876 patch_info
->type
= MONO_PATCH_INFO_NONE
;
5879 if (nThrows
< MAX_EXC
) {
5880 exc_classes
[nThrows
] = exc_class
;
5881 exc_throw_start
[nThrows
] = code
;
5884 /*---------------------------------------------*/
5885 /* Patch the parameter passed to the handler */
5886 /*---------------------------------------------*/
5887 S390_SET (code
, s390_r2
, m_class_get_type_token (exc_class
));
5888 /*---------------------------------------------*/
5889 /* Load return address & parameter register */
5890 /*---------------------------------------------*/
5891 s390_larl (code
, s390_r14
, (guint64
)S390_RELATIVE((patch_info
->ip
.i
+
5892 cfg
->native_code
+ 8), code
));
5893 /*---------------------------------------------*/
5894 /* Reuse the current patch to set the jump */
5895 /*---------------------------------------------*/
5896 patch_info
->type
= MONO_PATCH_INFO_JIT_ICALL_ID
;
5897 patch_info
->data
.jit_icall_id
= MONO_JIT_ICALL_mono_arch_throw_corlib_exception
;
5898 patch_info
->ip
.i
= code
- cfg
->native_code
;
5899 S390_BR_TEMPLATE (code
, s390_r1
);
5908 set_code_cursor (cfg
, code
);
5911 /*========================= End of Function ========================*/
5913 /*------------------------------------------------------------------*/
5915 /* Name - mono_arch_finish_init */
5917 /* Function - Setup the JIT's Thread Level Specific Data. */
5919 /*------------------------------------------------------------------*/
5922 mono_arch_finish_init (void)
5926 /*========================= End of Function ========================*/
5928 /*========================= End of Function ========================*/
5930 /*------------------------------------------------------------------*/
5932 /* Name - mono_arch_emit_inst_for_method */
5934 /*------------------------------------------------------------------*/
5937 mono_arch_emit_inst_for_method (MonoCompile
*cfg
, MonoMethod
*cmethod
, MonoMethodSignature
*fsig
, MonoInst
**args
)
5942 /*========================= End of Function ========================*/
5944 /*------------------------------------------------------------------*/
5946 /* Name - mono_arch_decompose_opts */
5948 /* Function - Decompose opcode into a System z opcode. */
5950 /*------------------------------------------------------------------*/
5953 mono_arch_decompose_opts (MonoCompile
*cfg
, MonoInst
*ins
)
5956 * Have to rename these to avoid being decomposed normally, since the normal
5957 * decomposition does not work on S390.
5959 switch (ins
->opcode
) {
5961 ins
->opcode
= OP_S390_ISUB_OVF
;
5963 case OP_ISUB_OVF_UN
:
5964 ins
->opcode
= OP_S390_ISUB_OVF_UN
;
5967 ins
->opcode
= OP_S390_IADD_OVF
;
5969 case OP_IADD_OVF_UN
:
5970 ins
->opcode
= OP_S390_IADD_OVF_UN
;
5973 ins
->opcode
= OP_S390_LADD_OVF
;
5975 case OP_LADD_OVF_UN
:
5976 ins
->opcode
= OP_S390_LADD_OVF_UN
;
5979 ins
->opcode
= OP_S390_LSUB_OVF
;
5981 case OP_LSUB_OVF_UN
:
5982 ins
->opcode
= OP_S390_LSUB_OVF_UN
;
5989 /*========================= End of Function ========================*/
5991 /*------------------------------------------------------------------*/
5993 /* Name - mono_arch_regalloc_cost */
5995 /* Function - Determine the cost, in the number of memory */
5996 /* references, of the action of allocating the var- */
5997 /* iable VMV into a register during global register */
6000 /* Returns - Cost */
6002 /*------------------------------------------------------------------*/
6005 mono_arch_regalloc_cost (MonoCompile
*cfg
, MonoMethodVar
*vmv
)
6011 /*========================= End of Function ========================*/
6013 /*------------------------------------------------------------------*/
6015 /* Name - mono_arch_flush_register_windows */
6021 /*------------------------------------------------------------------*/
6024 mono_arch_flush_register_windows (void)
6028 /*========================= End of Function ========================*/
6030 /*------------------------------------------------------------------*/
6032 /* Name - mono_arch_is_inst_imm */
6034 /* Function - Determine if operand qualifies as an immediate */
6035 /* value. For s390 this is a value -32768-32768 */
6037 /* Returns - True|False - is [not] immediate value. */
6039 /*------------------------------------------------------------------*/
6042 mono_arch_is_inst_imm (int opcode
, int imm_opcode
, gint64 imm
)
6044 return s390_is_imm32 (imm
);
6047 /*========================= End of Function ========================*/
6049 /*------------------------------------------------------------------*/
6051 /* Name - mono_arch_get_patch_offset */
6053 /* Function - Dummy entry point until s390x supports aot. */
6055 /* Returns - Offset for patch. */
6057 /*------------------------------------------------------------------*/
6060 mono_arch_get_patch_offset (guint8
*code
)
6065 /*========================= End of Function ========================*/
6067 /*------------------------------------------------------------------*/
6069 /* Name - mono_arch_context_get_int_reg. */
6073 /* Returns - Return a register from the context. */
6075 /*------------------------------------------------------------------*/
6078 mono_arch_context_get_int_reg (MonoContext
*ctx
, int reg
)
6080 return ctx
->uc_mcontext
.gregs
[reg
];
6083 /*========================= End of Function ========================*/
6085 /*------------------------------------------------------------------*/
6087 /* Name - mono_arch_context_set_int_reg. */
6089 /* Function - Set a value in a specified register. */
6091 /*------------------------------------------------------------------*/
6094 mono_arch_context_set_int_reg (MonoContext
*ctx
, int reg
, host_mgreg_t val
)
6096 ctx
->uc_mcontext
.gregs
[reg
] = val
;
6099 /*========================= End of Function ========================*/
6101 /*------------------------------------------------------------------*/
6103 /* Name - mono_arch_get_this_arg_from_call. */
6107 /*------------------------------------------------------------------*/
6110 mono_arch_get_this_arg_from_call (host_mgreg_t
*regs
, guint8
*code
)
6112 return (gpointer
) regs
[s390_r2
];
6115 /*========================= End of Function ========================*/
6117 /*------------------------------------------------------------------*/
6119 /* Name - get_delegate_invoke_impl. */
6123 /*------------------------------------------------------------------*/
6126 get_delegate_invoke_impl (MonoTrampInfo
**info
, gboolean has_target
, guint32 param_count
, gboolean aot
)
6128 guint8
*code
, *start
;
6133 start
= code
= mono_global_codeman_reserve (size
);
6135 /* Replace the this argument with the target */
6136 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
6137 s390_lg (code
, s390_r2
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, target
));
6138 s390_br (code
, s390_r1
);
6139 g_assert ((code
- start
) <= size
);
6141 mono_arch_flush_icache (start
, size
);
6142 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6146 size
= 32 + param_count
* 8;
6147 start
= code
= mono_global_codeman_reserve (size
);
6149 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET (MonoDelegate
, method_ptr
));
6150 /* slide down the arguments */
6151 for (i
= 0; i
< param_count
; ++i
) {
6152 s390_lgr (code
, (s390_r2
+ i
), (s390_r2
+ i
+ 1));
6154 s390_br (code
, s390_r1
);
6156 g_assert ((code
- start
) <= size
);
6158 mono_arch_flush_icache (start
, size
);
6159 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6163 *info
= mono_tramp_info_create ("delegate_invoke_impl_has_target", start
, code
- start
, NULL
, NULL
);
6165 char *name
= g_strdup_printf ("delegate_invoke_impl_target_%d", param_count
);
6166 *info
= mono_tramp_info_create (name
, start
, code
- start
, NULL
, NULL
);
6173 /*========================= End of Function ========================*/
6175 /*------------------------------------------------------------------*/
6177 /* Name - mono_arch_get_delegate_invoke_impls. */
6181 /*------------------------------------------------------------------*/
6184 mono_arch_get_delegate_invoke_impls (void)
6187 MonoTrampInfo
*info
;
6190 get_delegate_invoke_impl (&info
, TRUE
, 0, TRUE
);
6191 res
= g_slist_prepend (res
, info
);
6193 for (i
= 0; i
<= MAX_ARCH_DELEGATE_PARAMS
; ++i
) {
6194 get_delegate_invoke_impl (&info
, FALSE
, i
, TRUE
);
6195 res
= g_slist_prepend (res
, info
);
6201 /*========================= End of Function ========================*/
6203 /*------------------------------------------------------------------*/
6205 /* Name - mono_arch_get_delegate_invoke_impl. */
6209 /*------------------------------------------------------------------*/
6212 mono_arch_get_delegate_invoke_impl (MonoMethodSignature
*sig
, gboolean has_target
)
6214 guint8
*code
, *start
;
6216 /* FIXME: Support more cases */
6217 if (MONO_TYPE_ISSTRUCT (sig
->ret
))
6221 static guint8
* cached
= NULL
;
6226 if (mono_ee_features
.use_aot_trampolines
) {
6227 start
= mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6229 MonoTrampInfo
*info
;
6230 start
= get_delegate_invoke_impl (&info
, TRUE
, 0, FALSE
);
6231 mono_tramp_info_register (info
, NULL
);
6234 mono_memory_barrier ();
6238 static guint8
* cache
[MAX_ARCH_DELEGATE_PARAMS
+ 1] = {NULL
};
6241 if (sig
->param_count
> MAX_ARCH_DELEGATE_PARAMS
)
6243 for (i
= 0; i
< sig
->param_count
; ++i
)
6244 if (!mono_is_regsize_var (sig
->params
[i
]))
6248 code
= cache
[sig
->param_count
];
6252 if (mono_ee_features
.use_aot_trampolines
) {
6253 char *name
= g_strdup_printf ("delegate_invoke_impl_target_%d", sig
->param_count
);
6254 start
= mono_aot_get_trampoline (name
);
6257 MonoTrampInfo
*info
;
6258 start
= get_delegate_invoke_impl (&info
, FALSE
, sig
->param_count
, FALSE
);
6259 mono_tramp_info_register (info
, NULL
);
6262 mono_memory_barrier ();
6264 cache
[sig
->param_count
] = start
;
6269 /*========================= End of Function ========================*/
6271 /*------------------------------------------------------------------*/
6273 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6277 /*------------------------------------------------------------------*/
6280 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature
*sig
, MonoMethod
*method
,
6281 int offset
, gboolean load_imt_reg
)
6283 guint8
*code
, *start
;
6286 start
= code
= mono_global_codeman_reserve (size
);
6289 * Replace the "this" argument with the target
6291 s390_lgr (code
, s390_r1
, s390_r2
);
6292 s390_lg (code
, s390_r2
, 0, s390_r1
, MONO_STRUCT_OFFSET(MonoDelegate
, target
));
6295 * Load the IMT register, if needed
6298 s390_lg (code
, MONO_ARCH_IMT_REG
, 0, s390_r1
, MONO_STRUCT_OFFSET(MonoDelegate
, method
));
6304 s390_lg (code
, s390_r1
, 0, s390_r2
, MONO_STRUCT_OFFSET(MonoObject
, vtable
));
6306 s390_agfi(code
, s390_r1
, offset
);
6308 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6309 s390_br (code
, s390_r1
);
6311 mono_arch_flush_icache (start
, code
- start
);
6312 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE
, NULL
));
6317 /*========================= End of Function ========================*/
6319 /*------------------------------------------------------------------*/
6321 /* Name - mono_arch_build_imt_trampoline. */
6325 /*------------------------------------------------------------------*/
6328 mono_arch_build_imt_trampoline (MonoVTable
*vtable
, MonoDomain
*domain
,
6329 MonoIMTCheckItem
**imt_entries
, int count
,
6330 gpointer fail_tramp
)
6334 guchar
*code
, *start
;
6337 for (i
= 0; i
< count
; ++i
) {
6338 MonoIMTCheckItem
*item
= imt_entries
[i
];
6339 if (item
->is_equals
) {
6340 if (item
->check_target_idx
) {
6341 if (!item
->compare_done
)
6342 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
6343 if (item
->has_target_code
)
6344 item
->chunk_size
+= BR_SIZE
+ JUMP_SIZE
+ LOADCON_SIZE
;
6346 item
->chunk_size
+= BR_SIZE
+ JUMP_SIZE
+ LOADCON_SIZE
+
6350 item
->chunk_size
+= CMP_SIZE
+ 2 * BR_SIZE
+ JUMP_SIZE
+
6352 if (!item
->has_target_code
)
6353 item
->chunk_size
+= LOAD_SIZE
;
6355 item
->chunk_size
+= LOADCON_SIZE
+ LOAD_SIZE
+ BR_SIZE
;
6356 #if ENABLE_WRONG_METHOD_CHECK
6357 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
6362 item
->chunk_size
+= CMP_SIZE
+ JUMP_SIZE
;
6363 imt_entries
[item
->check_target_idx
]->compare_done
= TRUE
;
6365 size
+= item
->chunk_size
;
6369 code
= mono_method_alloc_generic_virtual_trampoline (domain
, size
);
6371 code
= mono_domain_code_reserve (domain
, size
);
6375 for (i
= 0; i
< count
; ++i
) {
6376 MonoIMTCheckItem
*item
= imt_entries
[i
];
6377 item
->code_target
= (guint8
*) code
;
6378 if (item
->is_equals
) {
6379 if (item
->check_target_idx
) {
6380 if (!item
->compare_done
) {
6381 S390_SET (code
, s390_r0
, item
->key
);
6382 s390_cgr (code
, s390_r0
, MONO_ARCH_IMT_REG
);
6384 item
->jmp_code
= (guint8
*) code
;
6385 s390_jcl (code
, S390_CC_NE
, 0);
6387 if (item
->has_target_code
) {
6388 S390_SET (code
, s390_r1
, item
->value
.target_code
);
6390 S390_SET (code
, s390_r1
, (&(vtable
->vtable
[item
->value
.vtable_slot
])));
6391 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6393 s390_br (code
, s390_r1
);
6398 S390_SET (code
, s390_r0
, item
->key
);
6399 s390_cgr (code
, s390_r0
, MONO_ARCH_IMT_REG
);
6400 item
->jmp_code
= (guint8
*) code
;
6401 s390_jcl (code
, S390_CC_NE
, 0);
6402 if (item
->has_target_code
) {
6403 S390_SET (code
, s390_r1
, item
->value
.target_code
);
6406 S390_SET (code
, s390_r1
,
6407 (&(vtable
->vtable
[item
->value
.vtable_slot
])));
6408 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6410 s390_br (code
, s390_r1
);
6411 target
= (gint64
) S390_RELATIVE(code
, item
->jmp_code
);
6412 s390_patch_rel(item
->jmp_code
+2, target
);
6413 S390_SET (code
, s390_r1
, fail_tramp
);
6414 s390_br (code
, s390_r1
);
6415 item
->jmp_code
= NULL
;
6417 /* enable the commented code to assert on wrong method */
6418 #if ENABLE_WRONG_METHOD_CHECK
6419 g_assert_not_reached ();
6421 S390_SET (code
, s390_r1
, (&(vtable
->vtable
[item
->value
.vtable_slot
])));
6422 s390_lg (code
, s390_r1
, 0, s390_r1
, 0);
6423 s390_br (code
, s390_r1
);
6427 S390_SET (code
, s390_r0
, item
->key
);
6428 s390_cgr (code
, MONO_ARCH_IMT_REG
, s390_r0
);
6429 item
->jmp_code
= (guint8
*) code
;
6430 s390_jcl (code
, S390_CC_GE
, 0);
6434 * patch the branches to get to the target items
6436 for (i
= 0; i
< count
; ++i
) {
6437 MonoIMTCheckItem
*item
= imt_entries
[i
];
6438 if (item
->jmp_code
) {
6439 if (item
->check_target_idx
) {
6441 offset
= (gint64
) S390_RELATIVE(imt_entries
[item
->check_target_idx
]->code_target
,
6443 s390_patch_rel ((guchar
*) item
->jmp_code
+ 2, (guint64
) offset
);
6448 mono_arch_flush_icache ((guint8
*)start
, (code
- start
));
6449 MONO_PROFILER_RAISE (jit_code_buffer
, (start
, code
- start
, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE
, NULL
));
6452 UnlockedAdd (&mono_stats
.imt_trampolines_size
, code
- start
);
6454 g_assert (code
- start
<= size
);
6456 snprintf(trampName
, sizeof(trampName
), "%d_imt_trampoline", domain
->domain_id
);
6457 mono_tramp_info_register (mono_tramp_info_create (trampName
, start
, code
- start
, NULL
, NULL
), domain
);
6462 /*========================= End of Function ========================*/
6464 /*------------------------------------------------------------------*/
6466 /* Name - mono_arch_find_imt_method. */
6468 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6469 /* found in the save area. */
6471 /*------------------------------------------------------------------*/
6474 mono_arch_find_imt_method (host_mgreg_t
*regs
, guint8
*code
)
6476 return ((MonoMethod
*) regs
[MONO_ARCH_IMT_REG
]);
6479 /*========================= End of Function ========================*/
6481 /*------------------------------------------------------------------*/
6483 /* Name - mono_arch_find_static_call_vtable */
6485 /* Function - Find the static call vtable. */
6487 /*------------------------------------------------------------------*/
6490 mono_arch_find_static_call_vtable (host_mgreg_t
*regs
, guint8
*code
)
6492 return (MonoVTable
*)(gsize
) regs
[MONO_ARCH_RGCTX_REG
];
6495 /*========================= End of Function ========================*/
6497 /*------------------------------------------------------------------*/
6499 /* Name - mono_arch_get_cie_program */
6501 /* Function - Find the static call vtable. */
6503 /*------------------------------------------------------------------*/
6506 mono_arch_get_cie_program (void)
6510 mono_add_unwind_op_def_cfa (l
, 0, 0, STK_BASE
, 0);
6515 /*========================= End of Function ========================*/
6517 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6519 /*------------------------------------------------------------------*/
6521 /* Name - mono_arch_set_breakpoint. */
6523 /* Function - Set a breakpoint at the native code corresponding */
6524 /* to JI at NATIVE_OFFSET. The location should */
6525 /* contain code emitted by OP_SEQ_POINT. */
6527 /*------------------------------------------------------------------*/
6530 mono_arch_set_breakpoint (MonoJitInfo
*ji
, guint8
*ip
)
6534 breakpointCode
.pTrigger
= bp_trigger_page
;
6535 memcpy(code
, (void *) &breakpointCode
, BREAKPOINT_SIZE
);
6536 code
+= BREAKPOINT_SIZE
;
6539 /*========================= End of Function ========================*/
6541 /*------------------------------------------------------------------*/
6543 /* Name - mono_arch_clear_breakpoint. */
6545 /* Function - Clear the breakpoint at IP. */
6547 /*------------------------------------------------------------------*/
6550 mono_arch_clear_breakpoint (MonoJitInfo
*ji
, guint8
*ip
)
6555 for (i
= 0; i
< (BREAKPOINT_SIZE
/ S390X_NOP_SIZE
); i
++)
6559 /*========================= End of Function ========================*/
6561 /*------------------------------------------------------------------*/
6563 /* Name - mono_arch_is_breakpoint_event. */
6567 /*------------------------------------------------------------------*/
6570 mono_arch_is_breakpoint_event (void *info
, void *sigctx
)
6572 siginfo_t
* sinfo
= (siginfo_t
*) info
;
6575 * Sometimes the address is off by 4
6577 if (sinfo
->si_addr
>= bp_trigger_page
&& (guint8
*)sinfo
->si_addr
<= (guint8
*)bp_trigger_page
+ 128)
6583 /*========================= End of Function ========================*/
6585 /*------------------------------------------------------------------*/
6587 /* Name - mono_arch_skip_breakpoint. */
6589 /* Function - Modify the CTX so the IP is placed after the */
6590 /* breakpoint instruction, so when we resume, the */
6591 /* instruction is not executed again. */
6593 /*------------------------------------------------------------------*/
6596 mono_arch_skip_breakpoint (MonoContext
*ctx
, MonoJitInfo
*ji
)
6598 MONO_CONTEXT_SET_IP (ctx
, ((guint8
*)MONO_CONTEXT_GET_IP (ctx
) + sizeof(RXY_Format
)));
6601 /*========================= End of Function ========================*/
6603 /*------------------------------------------------------------------*/
6605 /* Name - mono_arch_start_single_stepping. */
6607 /* Function - Start single stepping. */
6609 /*------------------------------------------------------------------*/
6612 mono_arch_start_single_stepping (void)
6614 mono_mprotect (ss_trigger_page
, mono_pagesize (), 0);
6617 /*========================= End of Function ========================*/
6619 /*------------------------------------------------------------------*/
6621 /* Name - mono_arch_stop_single_stepping. */
6623 /* Function - Stop single stepping. */
6625 /*------------------------------------------------------------------*/
6628 mono_arch_stop_single_stepping (void)
6630 mono_mprotect (ss_trigger_page
, mono_pagesize (), MONO_MMAP_READ
);
6633 /*========================= End of Function ========================*/
6635 /*------------------------------------------------------------------*/
6637 /* Name - mono_arch_is_single_step_event. */
6639 /* Function - Return whether the machine state in sigctx cor- */
6640 /* responds to a single step event. */
6642 /*------------------------------------------------------------------*/
6645 mono_arch_is_single_step_event (void *info
, void *sigctx
)
6647 siginfo_t
* sinfo
= (siginfo_t
*) info
;
6650 * Sometimes the address is off by 4
6652 if (sinfo
->si_addr
>= ss_trigger_page
&& (guint8
*)sinfo
->si_addr
<= (guint8
*)ss_trigger_page
+ 128)
6658 /*========================= End of Function ========================*/
6660 /*------------------------------------------------------------------*/
6662 /* Name - mono_arch_skip_single_step. */
6664 /* Function - Modify the ctx so the IP is placed after the */
6665 /* single step trigger instruction, so that the */
6666 /* instruction is not executed again. */
6668 /*------------------------------------------------------------------*/
6671 mono_arch_skip_single_step (MonoContext
*ctx
)
6673 MONO_CONTEXT_SET_IP (ctx
, (guint8
*)MONO_CONTEXT_GET_IP (ctx
) + BREAKPOINT_SIZE
);
6676 /*========================= End of Function ========================*/
6678 /*------------------------------------------------------------------*/
6680 /* Name - mono_arch_create_seq_point_info. */
6682 /* Function - Return a pointer to a data struction which is */
6683 /* used by the sequence point implementation in */
6686 /*------------------------------------------------------------------*/
6689 mono_arch_get_seq_point_info (MonoDomain
*domain
, guint8
*code
)
6695 /*========================= End of Function ========================*/
6699 /*------------------------------------------------------------------*/
6701 /* Name - mono_arch_cpu_enumerate_simd_versions. */
6703 /* Function - If this CPU supports vector operations then it */
6704 /* supports the equivalent of SSE1-4. */
6706 /*------------------------------------------------------------------*/
6709 mono_arch_cpu_enumerate_simd_versions (void)
6711 guint32 sseOpts
= 0;
6713 if (mono_hwcap_s390x_has_vec
)
6714 sseOpts
= (SIMD_VERSION_SSE1
| SIMD_VERSION_SSE2
|
6715 SIMD_VERSION_SSE3
| SIMD_VERSION_SSSE3
|
6716 SIMD_VERSION_SSE41
| SIMD_VERSION_SSE42
|
6717 SIMD_VERSION_SSE4a
);
6722 /*========================= End of Function ========================*/
6724 /*------------------------------------------------------------------*/
6726 /* Name - mono_arch_opcode_supported. */
6728 /* Function - Check if a given op code is supported. */
6730 /*------------------------------------------------------------------*/
6733 mono_arch_opcode_supported (int opcode
)
6736 case OP_ATOMIC_ADD_I4
:
6737 case OP_ATOMIC_ADD_I8
:
6738 case OP_ATOMIC_EXCHANGE_I4
:
6739 case OP_ATOMIC_EXCHANGE_I8
:
6746 /*========================= End of Function ========================*/
6748 /*------------------------------------------------------------------*/
6750 /* Name - mono_arch_tailcall_supported. */
6752 /* Function - Check if a tailcall is supported. */
6754 /*------------------------------------------------------------------*/
6759 mono_arch_tailcall_supported (MonoCompile
*cfg
, MonoMethodSignature
*caller_sig
, MonoMethodSignature
*callee_sig
, gboolean virtual_
)
6761 g_assert (caller_sig
);
6762 g_assert (callee_sig
);
6764 CallInfo
*caller_info
= get_call_info (NULL
, caller_sig
);
6765 CallInfo
*callee_info
= get_call_info (NULL
, callee_sig
);
6767 gboolean res
= IS_SUPPORTED_TAILCALL (callee_info
->stack_usage
<= caller_info
->stack_usage
)
6768 && IS_SUPPORTED_TAILCALL (callee_info
->struct_ret
== caller_info
->struct_ret
)
6769 && IS_SUPPORTED_TAILCALL (memcmp (&callee_info
->ret
, &caller_info
->ret
, sizeof (caller_info
->ret
)) == 0);
6771 // valuetypes passed semantic-byvalue ABI-byref are often to a local.
6772 // FIXME ABIs vary as to if this local is in the parameter area or not,
6773 // so this check might not be needed.
6774 ArgInfo
const * const ainfo
= callee_info
->args
+ callee_sig
->hasthis
;
6775 for (int i
= 0; res
&& i
< callee_sig
->param_count
; ++i
) {
6776 res
= IS_SUPPORTED_TAILCALL (ainfo
[i
].regtype
!= RegTypeStructByAddr
)
6777 && IS_SUPPORTED_TAILCALL (ainfo
[i
].regtype
!= RegTypeStructByAddrOnStack
);
6780 g_free (caller_info
);
6781 g_free (callee_info
);
6789 mono_arch_load_function (MonoJitICallId jit_icall_id
)
6794 /*========================= End of Function ========================*/