3 * Function - S/390 backend for the Mono code generator.
5 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Derivation - From mini-x86 & mini-ppc by -
10 * Paolo Molaro (lupus@ximian.com)
11 * Dietmar Maurer (dietmar@ximian.com)
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 #define MAX_ARCH_DELEGATE_PARAMS 7
21 #define EMIT_COND_BRANCH(ins,cond) \
23 if (ins->inst_true_bb->native_offset) { \
25 displace = ((cfg->native_code + \
26 ins->inst_true_bb->native_offset) - code) / 2; \
27 if (s390_is_imm16(displace)) { \
28 s390_brc (code, cond, displace); \
30 s390_jcl (code, cond, displace); \
33 mono_add_patch_info (cfg, code - cfg->native_code, \
34 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
35 s390_jcl (code, cond, 0); \
39 #define EMIT_UNCOND_BRANCH(ins) \
41 if (ins->inst_target_bb->native_offset) { \
43 displace = ((cfg->native_code + \
44 ins->inst_target_bb->native_offset) - code) / 2; \
45 if (s390_is_imm16(displace)) { \
46 s390_brc (code, S390_CC_UN, displace); \
48 s390_jcl (code, S390_CC_UN, displace); \
51 mono_add_patch_info (cfg, code - cfg->native_code, \
52 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
53 s390_jcl (code, S390_CC_UN, 0); \
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
59 mono_add_patch_info (cfg, code - cfg->native_code, \
60 MONO_PATCH_INFO_EXC, exc_name); \
61 s390_jcl (code, cond, 0); \
64 #define EMIT_COMP_AND_BRANCH(ins, cab, cmp) \
66 if (ins->inst_true_bb->native_offset) { \
68 displace = ((cfg->native_code + \
69 ins->inst_true_bb->native_offset) - code) / 2; \
70 if (s390_is_imm16(displace)) { \
71 s390_##cab (code, ins->sreg1, ins->sreg2, \
72 ins->sreg3, displace); \
74 s390_##cmp (code, ins->sreg1, ins->sreg2); \
75 displace = ((cfg->native_code + \
76 ins->inst_true_bb->native_offset) - code) / 2; \
77 s390_jcl (code, ins->sreg3, displace); \
80 s390_##cmp (code, ins->sreg1, ins->sreg2); \
81 mono_add_patch_info (cfg, code - cfg->native_code, \
82 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
83 s390_jcl (code, ins->sreg3, 0); \
87 #define EMIT_COMP_AND_BRANCH_IMM(ins, cab, cmp, lat, logical) \
89 if (ins->inst_true_bb->native_offset) { \
91 if ((ins->backend.data == 0) && (!logical)) { \
92 s390_##lat (code, ins->sreg1, ins->sreg1); \
93 displace = ((cfg->native_code + \
94 ins->inst_true_bb->native_offset) - code) / 2; \
95 if (s390_is_imm16(displace)) { \
96 s390_brc (code, ins->sreg3, displace); \
98 s390_jcl (code, ins->sreg3, displace); \
101 S390_SET (code, s390_r0, ins->backend.data); \
102 displace = ((cfg->native_code + \
103 ins->inst_true_bb->native_offset) - code) / 2; \
104 if (s390_is_imm16(displace)) { \
105 s390_##cab (code, ins->sreg1, s390_r0, \
106 ins->sreg3, displace); \
108 s390_##cmp (code, ins->sreg1, s390_r0); \
109 displace = ((cfg->native_code + \
110 ins->inst_true_bb->native_offset) - code) / 2; \
111 s390_jcl (code, ins->sreg3, displace); \
115 if ((ins->backend.data == 0) && (!logical)) { \
116 s390_##lat (code, ins->sreg1, ins->sreg1); \
118 S390_SET (code, s390_r0, ins->backend.data); \
119 s390_##cmp (code, ins->sreg1, s390_r0); \
121 mono_add_patch_info (cfg, code - cfg->native_code, \
122 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
123 s390_jcl (code, ins->sreg3, 0); \
127 #define CHECK_SRCDST_COM \
128 if (ins->dreg == ins->sreg2) { \
132 if (ins->dreg != ins->sreg1) { \
133 s390_lgr (code, ins->dreg, ins->sreg1); \
137 #define CHECK_SRCDST_NCOM \
138 if (ins->dreg == ins->sreg2) { \
140 s390_lgr (code, s390_r13, ins->sreg2); \
144 if (ins->dreg != ins->sreg1) { \
145 s390_lgr (code, ins->dreg, ins->sreg1); \
148 #define CHECK_SRCDST_COM_I \
149 if (ins->dreg == ins->sreg2) { \
153 if (ins->dreg != ins->sreg1) { \
154 s390_lgfr (code, ins->dreg, ins->sreg1); \
158 #define CHECK_SRCDST_NCOM_I \
159 if (ins->dreg == ins->sreg2) { \
161 s390_lgfr (code, s390_r13, ins->sreg2); \
165 if (ins->dreg != ins->sreg1) { \
166 s390_lgfr (code, ins->dreg, ins->sreg1); \
169 #define CHECK_SRCDST_COM_F \
170 if (ins->dreg == ins->sreg2) { \
174 if (ins->dreg != ins->sreg1) { \
175 s390_ldr (code, ins->dreg, ins->sreg1); \
179 #define CHECK_SRCDST_NCOM_F \
180 if (ins->dreg == ins->sreg2) { \
182 s390_ldr (code, s390_r13, ins->sreg2); \
186 if (ins->dreg != ins->sreg1) { \
187 s390_ldr (code, ins->dreg, ins->sreg1); \
190 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
193 MONO_INST_NEW (cfg, inst, OP_NOP); \
196 inst->inst_offset = offset; \
198 inst->inst_imm = imm; \
200 if (s390_is_uimm12(offset)) { \
202 inst->inst_offset = offset; \
204 dReg = mono_alloc_preg (cfg); \
205 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
206 dReg, dest, offset); \
208 inst->inst_offset = 0; \
210 if (s390_is_uimm12(imm)) { \
212 inst->inst_imm = imm; \
214 sReg = mono_alloc_preg (cfg); \
215 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
217 inst->sreg1 = sReg; \
218 inst->inst_imm = 0; \
221 inst->opcode = OP_S390_MOVE; \
222 inst->backend.size = size; \
223 MONO_ADD_INS (cfg->cbb, inst); \
226 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
227 int reg = mono_alloc_preg (cfg); \
230 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
233 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
237 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
241 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
245 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
249 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
252 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
256 tmpr = mono_alloc_preg (cfg); \
257 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
258 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
262 tmpr = mono_alloc_preg (cfg); \
263 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
265 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
269 tmpr = mono_alloc_preg (cfg); \
270 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
272 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
276 tmpr = mono_alloc_preg (cfg); \
277 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
279 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
283 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
289 #define DEBUG(a) if (cfg->verbose_level > 1) a
293 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
295 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
296 #define S390X_NOP_SIZE sizeof(RR_Format)
298 #define MAX(a, b) ((a) > (b) ? (a) : (b))
301 * imt trampoline size values
304 #define LOADCON_SIZE 20
308 #define ENABLE_WRONG_METHOD_CHECK 0
310 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
311 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
313 /*========================= End of Defines =========================*/
315 /*------------------------------------------------------------------*/
316 /* I n c l u d e s */
317 /*------------------------------------------------------------------*/
321 #include <sys/types.h>
324 #include <mono/metadata/abi-details.h>
325 #include <mono/metadata/appdomain.h>
326 #include <mono/metadata/debug-helpers.h>
327 #include <mono/metadata/profiler-private.h>
328 #include <mono/utils/mono-error.h>
329 #include <mono/utils/mono-error-internals.h>
330 #include <mono/utils/mono-math.h>
331 #include <mono/utils/mono-mmap.h>
332 #include <mono/utils/mono-hwcap.h>
333 #include <mono/utils/mono-threads.h>
335 #include "mini-s390x.h"
336 #include "cpu-s390x.h"
337 #include "support-s390x.h"
338 #include "jit-icalls.h"
343 /*========================= End of Includes ========================*/
345 /*------------------------------------------------------------------*/
346 /* T y p e d e f s */
347 /*------------------------------------------------------------------*/
359 /*------------------------------------------------------------------*/
360 /* Used by the instrument_emit_epilog */
361 /*------------------------------------------------------------------*/
372 typedef struct InstList InstList;
386 RegTypeStructByValInFP,
388 RegTypeStructByAddrOnStack
392 gint32 offset; /* offset from caller's stack */
393 gint32 offparm; /* offset from callee's stack */
394 guint16 vtsize; /* in param area */
397 guint32 size; /* Size of structure used by RegTypeStructByVal */
398 gint32 type; /* Data type of argument */
414 gint64 gr[5]; /* R2-R6 */
415 gdouble fp[3]; /* F0-F2 */
416 } __attribute__ ((__packed__)) RegParm;
424 } __attribute__ ((__packed__)) breakpoint_t;
426 /*========================= End of Typedefs ========================*/
428 /*------------------------------------------------------------------*/
429 /* P r o t o t y p e s */
430 /*------------------------------------------------------------------*/
432 static void indent (int);
433 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
434 static void decodeParm (MonoType *, void *, int);
435 static void enter_method (MonoMethod *, RegParm *, char *);
436 static void leave_method (MonoMethod *, ...);
437 static inline void add_general (guint *, size_data *, ArgInfo *);
438 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
439 static inline void add_float (guint *, size_data *, ArgInfo *);
440 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
441 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
442 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
443 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
444 static void compare_and_branch(MonoBasicBlock *, MonoInst *, int, gboolean);
446 /*========================= End of Prototypes ======================*/
448 /*------------------------------------------------------------------*/
449 /* G l o b a l V a r i a b l e s */
450 /*------------------------------------------------------------------*/
452 int mono_exc_esp_offset = 0;
454 __thread int indent_level = 0;
455 __thread FILE *trFd = NULL;
459 * The code generated for sequence points reads from this location,
460 * which is made read-only when single stepping is enabled.
462 static gpointer ss_trigger_page;
465 * Enabled breakpoints read from this trigger page
467 static gpointer bp_trigger_page;
469 breakpoint_t breakpointCode;
471 static mono_mutex_t mini_arch_mutex;
473 static const char * grNames[] = {
474 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
475 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
476 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
480 static const char * fpNames[] = {
481 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
482 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
483 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
487 static const char * vrNames[] = {
488 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
489 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
490 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
491 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
494 /*====================== End of Global Variables ===================*/
496 /*------------------------------------------------------------------*/
498 /* Name - mono_arch_regname */
500 /* Function - Returns the name of the register specified by */
501 /* the input parameter. */
503 /*------------------------------------------------------------------*/
506 mono_arch_regname (int reg)
508 if (reg >= 0 && reg < 16)
509 return grNames [reg];
514 /*========================= End of Function ========================*/
516 /*------------------------------------------------------------------*/
518 /* Name - mono_arch_fregname */
520 /* Function - Returns the name of the register specified by */
521 /* the input parameter. */
523 /*------------------------------------------------------------------*/
526 mono_arch_fregname (int reg)
528 if (reg >= 0 && reg < 16)
529 return fpNames [reg];
534 /*========================= End of Function ========================*/
536 /*------------------------------------------------------------------*/
538 /* Name - mono_arch_xregname */
540 /* Function - Returns the name of the register specified by */
541 /* the input parameter. */
543 /*------------------------------------------------------------------*/
546 mono_arch_xregname (int reg)
548 if (reg < s390_VR_NREG)
549 return vrNames [reg];
554 /*========================= End of Function ========================*/
556 /*------------------------------------------------------------------*/
558 /* Name - arch_get_argument_info */
560 /* Function - Gathers information on parameters such as size, */
561 /* alignment, and padding. arg_info should be large */
562 /* enough to hold param_count + 1 entries. */
564 /* Parameters - @csig - Method signature */
565 /* @param_count - No. of parameters to consider */
566 /* @arg_info - An array to store the result info */
568 /* Returns - Size of the activation frame */
570 /*------------------------------------------------------------------*/
573 mono_arch_get_argument_info (MonoMethodSignature *csig,
575 MonoJitArgumentInfo *arg_info)
577 int k, frame_size = 0;
578 int size, align, pad;
581 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
582 frame_size += sizeof (gpointer);
586 arg_info [0].offset = offset;
589 frame_size += sizeof (gpointer);
593 arg_info [0].size = frame_size;
595 for (k = 0; k < param_count; k++) {
598 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
600 size = mini_type_stack_size (csig->params [k], &align);
602 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
603 arg_info [k].pad = pad;
605 arg_info [k + 1].pad = 0;
606 arg_info [k + 1].size = size;
608 arg_info [k + 1].offset = offset;
612 align = MONO_ARCH_FRAME_ALIGNMENT;
613 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
614 arg_info [k].pad = pad;
619 /*========================= End of Function ========================*/
621 /*------------------------------------------------------------------*/
623 /* Name - emit_unwind_regs. */
625 /* Function - Determines if a value can be returned in one or */
628 /*------------------------------------------------------------------*/
630 static void __inline__
631 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
635 for (i = start; i < end; i++) {
636 mono_emit_unwind_op_offset (cfg, code, i, offset);
637 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
638 offset += sizeof(gulong);
642 /*========================= End of Function ========================*/
644 /*------------------------------------------------------------------*/
646 /* Name - retFitsInReg. */
648 /* Function - Determines if a value can be returned in one or */
651 /*------------------------------------------------------------------*/
653 static inline gboolean
654 retFitsInReg(guint32 size)
669 /*========================= End of Function ========================*/
671 /*------------------------------------------------------------------*/
673 /* Name - backStackPtr. */
675 /* Function - Restore Stack Pointer to previous frame. */
677 /*------------------------------------------------------------------*/
679 static inline guint8 *
680 backUpStackPtr(MonoCompile *cfg, guint8 *code)
682 int stackSize = cfg->stack_usage;
684 if (cfg->frame_reg != STK_BASE)
685 s390_lgr (code, STK_BASE, cfg->frame_reg);
687 if (s390_is_imm16 (stackSize)) {
688 s390_aghi (code, STK_BASE, stackSize);
690 while (stackSize > 32767) {
691 s390_aghi (code, STK_BASE, 32767);
694 s390_aghi (code, STK_BASE, stackSize);
699 /*========================= End of Function ========================*/
701 /*------------------------------------------------------------------*/
705 /* Function - Perform nice indenting to current level */
707 /*------------------------------------------------------------------*/
713 indent_level += diff;
715 fprintf (trFd, "%p [%3d] ",(void *)pthread_self(),v);
717 fprintf (trFd, ". ");
720 indent_level += diff;
723 /*========================= End of Function ========================*/
725 /*------------------------------------------------------------------*/
727 /* Name - cvtMonoType */
729 /* Function - Convert a mono-type to a string. */
731 /*------------------------------------------------------------------*/
734 cvtMonoType(MonoTypeEnum t)
739 return "MONO_TYPE_END";
741 return "MONO_TYPE_VOID";
742 case MONO_TYPE_BOOLEAN:
743 return "MONO_TYPE_BOOLEAN";
745 return "MONO_TYPE_CHAR";
747 return "MONO_TYPE_I1";
749 return "MONO_TYPE_U1";
751 return "MONO_TYPE_I2";
753 return "MONO_TYPE_U2";
755 return "MONO_TYPE_I4";
757 return "MONO_TYPE_U4";
759 return "MONO_TYPE_I8";
761 return "MONO_TYPE_U8";
763 return "MONO_TYPE_R4";
765 return "MONO_TYPE_R8";
766 case MONO_TYPE_STRING:
767 return "MONO_TYPE_STRING";
769 return "MONO_TYPE_PTR";
770 case MONO_TYPE_BYREF:
771 return "MONO_TYPE_BYREF";
772 case MONO_TYPE_VALUETYPE:
773 return "MONO_TYPE_VALUETYPE";
774 case MONO_TYPE_CLASS:
775 return "MONO_TYPE_CLASS";
777 return "MONO_TYPE_VAR";
778 case MONO_TYPE_ARRAY:
779 return "MONO_TYPE_ARRAY";
780 case MONO_TYPE_GENERICINST:
781 return "MONO_TYPE_GENERICINST";
782 case MONO_TYPE_TYPEDBYREF:
783 return "MONO_TYPE_TYPEDBYREF";
785 return "MONO_TYPE_I";
787 return "MONO_TYPE_U";
788 case MONO_TYPE_FNPTR:
789 return "MONO_TYPE_FNPTR";
790 case MONO_TYPE_OBJECT:
791 return "MONO_TYPE_OBJECT";
792 case MONO_TYPE_SZARRAY:
793 return "MONO_TYPE_SZARRAY";
795 return "MONO_TYPE_MVAR";
796 case MONO_TYPE_CMOD_REQD:
797 return "MONO_TYPE_CMOD_REQD";
798 case MONO_TYPE_CMOD_OPT:
799 return "MONO_TYPE_CMOD_OPT";
800 case MONO_TYPE_INTERNAL:
801 return "MONO_TYPE_INTERNAL";
802 case MONO_TYPE_MODIFIER:
803 return "MONO_TYPE_MODIFIER";
804 case MONO_TYPE_SENTINEL:
805 return "MONO_TYPE_SENTINEL";
806 case MONO_TYPE_PINNED:
807 return "MONO_TYPE_PINNED";
814 /*========================= End of Function ========================*/
816 /*------------------------------------------------------------------*/
818 /* Name - decodeParmString */
820 /* Function - Decode a parameter string for the trace. */
822 /*------------------------------------------------------------------*/
825 decodeParmString (MonoString *s)
828 char *str = mono_string_to_utf8_checked(s, &error);
829 if (is_ok (&error)) {
830 fprintf (trFd, "[STRING:%p:%s], ", s, str);
833 mono_error_cleanup (&error);
834 fprintf (trFd, "[STRING:%p:], ", s);
838 /*========================= End of Function ========================*/
840 /*------------------------------------------------------------------*/
842 /* Name - decodeParm */
844 /* Function - Decode a parameter for the trace. */
846 /*------------------------------------------------------------------*/
850 decodeParm(MonoType *type, void *curParm, int size)
855 fprintf (trFd, "[BYREF:%p], ", *((char **) curParm));
857 simpleType = mini_get_underlying_type(type)->type;
859 switch (simpleType) {
861 fprintf (trFd, "[INTPTR:%p], ", *((int **) curParm));
864 fprintf (trFd, "[UINTPTR:%p], ", *((int **) curParm));
866 case MONO_TYPE_BOOLEAN :
867 fprintf (trFd, "[BOOL:%ld], ", *((gint64 *) curParm));
869 case MONO_TYPE_CHAR :
870 fprintf (trFd, "[CHAR:%c], ", *((int *) curParm));
873 fprintf (trFd, "[INT1:%ld], ", *((gint64 *) curParm));
876 fprintf (trFd, "[INT2:%ld], ", *((gint64 *) curParm));
879 fprintf (trFd, "[INT4:%ld], ", *((gint64 *) curParm));
882 fprintf (trFd, "[UINT1:%lu], ", *((guint64 *) curParm));
885 fprintf (trFd, "[UINT2:%lu], ", *((guint64 *) curParm));
888 fprintf (trFd, "[UINT4:%lu], ", *((guint64 *) curParm));
891 fprintf (trFd, "[UINT8:%lu], ", *((guint64 *) curParm));
893 case MONO_TYPE_STRING : {
894 MonoString *s = *((MonoString **) curParm);
896 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
897 decodeParmString (s);
899 fprintf (trFd, "[STRING:null], ");
903 case MONO_TYPE_CLASS :
904 case MONO_TYPE_OBJECT : {
905 MonoObject *obj = *((MonoObject **) curParm);
907 if ((obj) && (obj->vtable)) {
908 fprintf (trFd, "[CLASS/OBJ:");
909 klass = obj->vtable->klass;
910 fprintf (trFd, "%p [%p] ",obj,curParm);
911 if (klass == mono_defaults.string_class) {
912 decodeParmString ((MonoString *)obj);
913 } else if (klass == mono_defaults.int32_class) {
914 fprintf (trFd, "[INT32:%p:%d]",
915 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
917 fprintf (trFd, "[%s.%s:%p]",
918 klass->name_space, klass->name, obj);
919 fprintf (trFd, "], ");
921 fprintf (trFd, "[OBJECT:null], ");
926 fprintf (trFd, "[PTR:%p], ", *((gpointer **) (curParm)));
928 case MONO_TYPE_FNPTR :
929 fprintf (trFd, "[FNPTR:%p], ", *((gpointer **) (curParm)));
931 case MONO_TYPE_ARRAY :
932 fprintf (trFd, "[ARRAY:%p], ", *((gpointer **) (curParm)));
934 case MONO_TYPE_SZARRAY :
935 fprintf (trFd, "[SZARRAY:%p], ", *((gpointer **) (curParm)));
938 fprintf (trFd, "[INT8:%ld], ", *((gint64 *) (curParm)));
941 fprintf (trFd, "[FLOAT4:%g], ", *((float *) (curParm)));
944 fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
946 case MONO_TYPE_VALUETYPE : {
948 MonoMarshalType *info;
950 if (type->data.klass->enumtype) {
951 simpleType = mono_class_enum_basetype (type->data.klass)->type;
952 fprintf (trFd, "{VALUETYPE} - ");
956 info = mono_marshal_load_type_info (type->data.klass);
958 if ((info->native_size == sizeof(float)) &&
959 (info->num_fields == 1) &&
960 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
961 fprintf (trFd, "[FLOAT4:%f], ", *((float *) (curParm)));
965 if ((info->native_size == sizeof(double)) &&
966 (info->num_fields == 1) &&
967 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
968 fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
972 fprintf (trFd, "[VALUETYPE:");
973 for (i = 0; i < size; i++)
974 fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
975 fprintf (trFd, "], ");
978 case MONO_TYPE_TYPEDBYREF: {
980 fprintf (trFd, "[TYPEDBYREF:");
981 for (i = 0; i < size; i++)
982 fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
987 fprintf (trFd, "[%s], ",cvtMonoType(simpleType));
992 /*========================= End of Function ========================*/
994 /*------------------------------------------------------------------*/
996 /* Name - enter_method */
998 /* Function - Perform tracing of the entry to the current */
1001 /*------------------------------------------------------------------*/
1004 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
1006 int i, oParm = 0, iParm = 0;
1009 MonoMethodSignature *sig;
1018 sprintf(buf, "/tmp/mono.%d.trc.%d", getpid(), curThreadNo++);
1019 trFd = fopen(buf, "w");
1021 fname = mono_method_full_name (method, TRUE);
1023 fprintf (trFd, "ENTER: %s ", fname);
1026 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
1027 fprintf (trFd, "ip: %p sp: %p - ", (gpointer) ip, sp);
1032 sig = mono_method_signature (method);
1034 cinfo = get_call_info (NULL, NULL, sig);
1036 if (cinfo->struct_ret) {
1037 fprintf (trFd, "[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
1042 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
1043 obj = (MonoObject *) this_arg;
1044 switch(method->klass->this_arg.type) {
1045 case MONO_TYPE_VALUETYPE:
1047 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
1048 fprintf (trFd, "this:[value:%p:%016lx], ", this_arg, *value);
1050 fprintf (trFd, "this:[NULL], ");
1052 case MONO_TYPE_STRING:
1055 klass = obj->vtable->klass;
1056 if (klass == mono_defaults.string_class) {
1057 fprintf (trFd, "this:");
1058 decodeParmString((MonoString *)obj);
1060 fprintf (trFd, "this:%p[%s.%s], ",
1061 obj, klass->name_space, klass->name);
1064 fprintf (trFd, "vtable:[NULL], ");
1066 fprintf (trFd, "this:[NULL], ");
1069 fprintf (trFd, "this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1074 for (i = 0; i < sig->param_count; ++i) {
1075 ainfo = &cinfo->args[i + oParm];
1076 switch (ainfo->regtype) {
1077 case RegTypeGeneral :
1078 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1081 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1084 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1086 case RegTypeStructByVal :
1087 if (ainfo->reg != STK_BASE) {
1088 int offset = sizeof(glong) - ainfo->size;
1089 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1092 curParm = sp+ainfo->offset;
1094 if (retFitsInReg (ainfo->vtsize))
1095 decodeParm(sig->params[i],
1099 decodeParm(sig->params[i],
1100 *((char **) curParm),
1103 case RegTypeStructByAddr :
1104 if (ainfo->reg != STK_BASE)
1105 curParm = &(rParm->gr[ainfo->reg-2]);
1107 curParm = sp+ainfo->offset;
1109 decodeParm(sig->params[i],
1110 *((char **) curParm),
1115 fprintf (trFd, "???, ");
1118 fprintf (trFd, "\n");
1122 /*========================= End of Function ========================*/
1124 /*------------------------------------------------------------------*/
1126 /* Name - leave_method */
1130 /*------------------------------------------------------------------*/
1133 leave_method (MonoMethod *method, ...)
1140 va_start(ap, method);
1142 fname = mono_method_full_name (method, TRUE);
1144 fprintf (trFd, "LEAVE: %s", fname);
1147 type = mono_method_signature (method)->ret;
1150 switch (type->type) {
1151 case MONO_TYPE_VOID:
1153 case MONO_TYPE_BOOLEAN: {
1154 int val = va_arg (ap, int);
1156 fprintf (trFd, "[TRUE:%d]", val);
1158 fprintf (trFd, "[FALSE]");
1162 case MONO_TYPE_CHAR: {
1163 int val = va_arg (ap, int);
1164 fprintf (trFd, "[CHAR:%d]", val);
1167 case MONO_TYPE_I1: {
1168 int val = va_arg (ap, int);
1169 fprintf (trFd, "[INT1:%d]", val);
1172 case MONO_TYPE_U1: {
1173 int val = va_arg (ap, int);
1174 fprintf (trFd, "[UINT1:%d]", val);
1177 case MONO_TYPE_I2: {
1178 int val = va_arg (ap, int);
1179 fprintf (trFd, "[INT2:%d]", val);
1182 case MONO_TYPE_U2: {
1183 int val = va_arg (ap, int);
1184 fprintf (trFd, "[UINT2:%d]", val);
1187 case MONO_TYPE_I4: {
1188 int val = va_arg (ap, int);
1189 fprintf (trFd, "[INT4:%d]", val);
1192 case MONO_TYPE_U4: {
1193 int val = va_arg (ap, int);
1194 fprintf (trFd, "[UINT4:%d]", val);
1198 gint64 val = va_arg (ap, gint64);
1199 fprintf (trFd, "[INT:%ld]", val);
1200 fprintf (trFd, "]");
1204 gint64 val = va_arg (ap, gint64);
1205 fprintf (trFd, "[UINT:%lu]", val);
1206 fprintf (trFd, "]");
1209 case MONO_TYPE_STRING: {
1210 MonoString *s = va_arg (ap, MonoString *);
1213 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1214 decodeParmString (s);
1216 fprintf (trFd, "[STRING:null], ");
1219 case MONO_TYPE_CLASS:
1220 case MONO_TYPE_OBJECT: {
1221 MonoObject *o = va_arg (ap, MonoObject *);
1223 if ((o) && (o->vtable)) {
1224 if (o->vtable->klass == mono_defaults.boolean_class) {
1225 fprintf (trFd, "[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1226 } else if (o->vtable->klass == mono_defaults.int32_class) {
1227 fprintf (trFd, "[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1228 } else if (o->vtable->klass == mono_defaults.int64_class) {
1229 fprintf (trFd, "[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1231 fprintf (trFd, "[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1233 fprintf (trFd, "[OBJECT:%p]", o);
1238 case MONO_TYPE_FNPTR:
1239 case MONO_TYPE_ARRAY:
1240 case MONO_TYPE_SZARRAY: {
1241 gpointer p = va_arg (ap, gpointer);
1242 fprintf (trFd, "[result=%p]", p);
1245 case MONO_TYPE_I8: {
1246 gint64 l = va_arg (ap, gint64);
1247 fprintf (trFd, "[LONG:%ld]", l);
1250 case MONO_TYPE_U8: {
1251 guint64 l = va_arg (ap, guint64);
1252 fprintf (trFd, "[ULONG:%lu]", l);
1255 case MONO_TYPE_R4: {
1256 double f = va_arg (ap, double);
1257 fprintf (trFd, "[FLOAT4:%g]\n", f);
1260 case MONO_TYPE_R8: {
1261 double f = va_arg (ap, double);
1262 fprintf (trFd, "[FLOAT8:%g]\n", f);
1265 case MONO_TYPE_VALUETYPE: {
1266 MonoMarshalType *info;
1267 if (type->data.klass->enumtype) {
1268 type = mono_class_enum_basetype (type->data.klass);
1273 info = mono_marshal_load_type_info (type->data.klass);
1275 if ((info->native_size == sizeof(float)) &&
1276 (info->num_fields == 1) &&
1277 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1278 double f = va_arg (ap, double);
1279 fprintf (trFd, "[FLOAT4:%g]\n", (double) f);
1283 if ((info->native_size == sizeof(double)) &&
1284 (info->num_fields == 1) &&
1285 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1286 double f = va_arg (ap, double);
1287 fprintf (trFd, "[FLOAT8:%g]\n", f);
1291 size = mono_type_size (type, &align);
1294 guint32 p = va_arg (ap, guint32);
1295 fprintf (trFd, "[%02x]\n",p);
1299 guint32 p = va_arg (ap, guint32);
1300 fprintf (trFd, "[%04x]\n",p);
1304 guint32 p = va_arg (ap, guint32);
1305 fprintf (trFd, "[%08x]\n",p);
1309 guint64 p = va_arg (ap, guint64);
1310 fprintf (trFd, "[%016lx]\n",p);
1314 gpointer p = va_arg (ap, gpointer);
1315 fprintf (trFd, "[VALUETYPE] %p\n",p);
1321 case MONO_TYPE_TYPEDBYREF: {
1322 guint8 *p = va_arg (ap, gpointer);
1324 size = mono_type_size (type, &align);
1330 fprintf (trFd, "[");
1331 for (j = 0; p && j < size; j++)
1332 fprintf (trFd, "%02x,", p [j]);
1333 fprintf (trFd, "]\n");
1336 fprintf (trFd, "[TYPEDBYREF]\n");
1340 case MONO_TYPE_GENERICINST: {
1341 fprintf (trFd, "[GENERICINST]\n");
1344 case MONO_TYPE_MVAR: {
1345 fprintf (trFd, "[MVAR]\n");
1348 case MONO_TYPE_CMOD_REQD: {
1349 fprintf (trFd, "[CMOD_REQD]\n");
1352 case MONO_TYPE_CMOD_OPT: {
1353 fprintf (trFd, "[CMOD_OPT]\n");
1356 case MONO_TYPE_INTERNAL: {
1357 fprintf (trFd, "[INTERNAL]\n");
1361 fprintf (trFd, "(unknown return type %x)",
1362 mono_method_signature (method)->ret->type);
1365 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1366 fprintf (trFd, " ip: %p\n", (gpointer) ip);
1370 /*========================= End of Function ========================*/
1372 /*------------------------------------------------------------------*/
1374 /* Name - mono_arch_cpu_init */
1376 /* Function - Perform CPU specific initialization to execute */
1379 /*------------------------------------------------------------------*/
1382 mono_arch_cpu_init (void)
1386 /*========================= End of Function ========================*/
1388 /*------------------------------------------------------------------*/
1390 /* Name - mono_arch_init. */
1392 /* Function - Initialize architecture specific code. */
1394 /*------------------------------------------------------------------*/
1397 mono_arch_init (void)
1401 mono_set_partial_sharing_supported (FALSE);
1402 mono_os_mutex_init_recursive (&mini_arch_mutex);
1404 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1405 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1406 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1408 code = (guint8 *) &breakpointCode;
1409 s390_basr(code, s390_r13, 0);
1411 s390_llong(code, 0);
1412 s390_lg(code, s390_r13, 0, s390_r13, 4);
1413 s390_lg(code, s390_r0, 0, s390_r13, 0);
1416 /*========================= End of Function ========================*/
1418 /*------------------------------------------------------------------*/
1420 /* Name - mono_arch_cleanup. */
1422 /* Function - Cleanup architecture specific code . */
1424 /*------------------------------------------------------------------*/
1427 mono_arch_cleanup (void)
1429 if (ss_trigger_page)
1430 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1431 if (bp_trigger_page)
1432 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1433 mono_os_mutex_destroy (&mini_arch_mutex);
1436 /*========================= End of Function ========================*/
1438 /*------------------------------------------------------------------*/
1440 /* Name - mono_arch_have_fast_tls */
1442 /* Function - Returns whether we use fast inlined thread local */
1443 /* storage managed access, instead of falling back */
1444 /* to native code. */
1446 /*------------------------------------------------------------------*/
1449 mono_arch_have_fast_tls (void)
1454 /*========================= End of Function ========================*/
1456 /*------------------------------------------------------------------*/
1458 /* Name - mono_arch_cpu_optimizations */
1460 /* Function - Returns the optimizations supported on this CPU */
1462 /*------------------------------------------------------------------*/
1465 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1469 /*----------------------------------------------------------*/
1470 /* No s390-specific optimizations yet */
1471 /*----------------------------------------------------------*/
1472 *exclude_mask = MONO_OPT_LINEARS;
1476 /*========================= End of Function ========================*/
1478 /*------------------------------------------------------------------*/
1480 /* Name - mono_arch_get_allocatable_int_vars */
1484 /*------------------------------------------------------------------*/
1487 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1492 for (i = 0; i < cfg->num_varinfo; i++) {
1493 MonoInst *ins = cfg->varinfo [i];
1494 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1497 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1500 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1501 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1504 /* we can only allocate 32 bit values */
1505 if (mono_is_regsize_var(ins->inst_vtype)) {
1506 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1507 g_assert (i == vmv->idx);
1508 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1515 /*========================= End of Function ========================*/
1517 /*------------------------------------------------------------------*/
1519 /* Name - mono_arch_global_int_regs */
1521 /* Function - Return a list of usable integer registers. */
1523 /*------------------------------------------------------------------*/
1526 mono_arch_get_global_int_regs (MonoCompile *cfg)
1529 MonoMethodHeader *header;
1532 header = cfg->header;
1533 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1534 cfg->frame_reg = s390_r11;
1537 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1539 for (i = 8; i < top; ++i) {
1540 if ((cfg->frame_reg != i) &&
1541 //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
1542 (i != MONO_ARCH_IMT_REG))
1543 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1549 /*========================= End of Function ========================*/
1551 /*------------------------------------------------------------------*/
1553 /* Name - mono_arch_flush_icache */
1555 /* Function - Flush the CPU icache. */
1557 /*------------------------------------------------------------------*/
1560 mono_arch_flush_icache (guint8 *code, gint size)
1564 /*========================= End of Function ========================*/
1566 /*------------------------------------------------------------------*/
1568 /* Name - add_general */
1570 /* Function - Determine code and stack size incremements for a */
1573 /*------------------------------------------------------------------*/
1576 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1578 if (*gr > S390_LAST_ARG_REG) {
1579 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1580 ainfo->offset = sz->stack_size;
1581 ainfo->reg = STK_BASE;
1582 ainfo->regtype = RegTypeBase;
1583 sz->stack_size += sizeof(long);
1584 sz->local_size += sizeof(long);
1585 sz->offStruct += sizeof(long);
1586 sz->code_size += 12;
1594 /*========================= End of Function ========================*/
1596 /*------------------------------------------------------------------*/
1598 /* Name - add_stackParm */
1600 /* Function - Determine code and stack size incremements for a */
1603 /*------------------------------------------------------------------*/
1606 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1608 if (*gr > S390_LAST_ARG_REG) {
1609 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1610 ainfo->reg = STK_BASE;
1611 ainfo->offset = sz->stack_size;
1612 ainfo->regtype = RegTypeStructByAddrOnStack;
1613 sz->stack_size += sizeof (gpointer);
1614 sz->parm_size += sizeof(gpointer);
1615 sz->offStruct += sizeof(gpointer);
1618 ainfo->offset = sz->stack_size;
1619 ainfo->regtype = RegTypeStructByAddr;
1622 ainfo->offparm = sz->offset;
1623 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1625 ainfo->vtsize = size;
1626 sz->parm_size += size;
1629 /*========================= End of Function ========================*/
1631 /*------------------------------------------------------------------*/
1633 /* Name - add_float */
1635 /* Function - Determine code and stack size incremements for a */
1636 /* float parameter. */
1638 /*------------------------------------------------------------------*/
1641 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1643 if ((*fr) <= S390_LAST_FPARG_REG) {
1644 ainfo->regtype = RegTypeFP;
1650 ainfo->offset = sz->stack_size;
1651 ainfo->reg = STK_BASE;
1652 ainfo->regtype = RegTypeBase;
1654 sz->stack_size += sizeof(double);
1655 sz->local_size += sizeof(double);
1656 sz->offStruct += sizeof(double);
1660 /*========================= End of Function ========================*/
1662 /*------------------------------------------------------------------*/
1664 /* Name - get_call_info */
1666 /* Function - Determine the amount of space required for code */
1667 /* and stack. In addition determine starting points */
1668 /* for stack-based parameters, and area for struct- */
1669 /* ures being returned on the stack. */
1671 /*------------------------------------------------------------------*/
1674 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1676 guint i, fr, gr, size, pstart;
1677 int nParm = sig->hasthis + sig->param_count;
1679 guint32 simpleType, align;
1680 gboolean is_pinvoke = sig->pinvoke;
1685 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1687 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1692 cinfo->struct_ret = 0;
1696 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1697 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1704 /*----------------------------------------------------------*/
1705 /* We determine the size of the return code/stack in case we*/
1706 /* need to reserve a register to be used to address a stack */
1707 /* area that the callee will use. */
1708 /*----------------------------------------------------------*/
1710 ret_type = mini_get_underlying_type (sig->ret);
1711 simpleType = ret_type->type;
1713 switch (simpleType) {
1722 case MONO_TYPE_OBJECT:
1724 case MONO_TYPE_FNPTR:
1725 cinfo->ret.reg = s390_r2;
1730 cinfo->ret.reg = s390_f0;
1735 cinfo->ret.reg = s390_r2;
1738 case MONO_TYPE_GENERICINST:
1739 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1740 cinfo->ret.reg = s390_r2;
1745 case MONO_TYPE_VALUETYPE: {
1746 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1747 if (klass->enumtype) {
1748 simpleType = mono_class_enum_basetype (klass)->type;
1751 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1753 cinfo->struct_ret = 1;
1754 cinfo->ret.size = size;
1755 cinfo->ret.vtsize = size;
1758 case MONO_TYPE_TYPEDBYREF:
1759 size = sizeof (MonoTypedRef);
1760 cinfo->struct_ret = 1;
1761 cinfo->ret.size = size;
1762 cinfo->ret.vtsize = size;
1764 case MONO_TYPE_VOID:
1767 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1773 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1774 * the first argument, allowing 'this' to be always passed in the first arg reg.
1775 * Also do this if the first argument is a reference type, since virtual calls
1776 * are sometimes made using calli without sig->hasthis set, like in the delegate
1779 if (cinfo->struct_ret && !is_pinvoke &&
1781 (sig->param_count > 0 &&
1782 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1784 cinfo->args[nParm].size = sizeof (gpointer);
1785 add_general (&gr, sz, cinfo->args + nParm);
1787 cinfo->args[nParm].size = sizeof (gpointer);
1788 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1792 cinfo->vret_arg_index = 1;
1793 cinfo->ret.reg = gr;
1798 cinfo->args[nParm].size = sizeof (gpointer);
1799 add_general (&gr, sz, cinfo->args + nParm);
1803 if (cinfo->struct_ret) {
1804 cinfo->ret.reg = gr;
1809 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1810 gr = S390_LAST_ARG_REG + 1;
1811 fr = S390_LAST_FPARG_REG + 1;
1813 /* Emit the signature cookie just before the implicit arguments */
1814 add_general (&gr, sz, &cinfo->sigCookie);
1817 /*----------------------------------------------------------*/
1818 /* We determine the size of the parameter code and stack */
1819 /* requirements by checking the types and sizes of the */
1821 /*----------------------------------------------------------*/
1823 for (i = pstart; i < sig->param_count; ++i) {
1826 /*--------------------------------------------------*/
1827 /* Handle vararg type calls. All args are put on */
1829 /*--------------------------------------------------*/
1830 if ((sig->call_convention == MONO_CALL_VARARG) &&
1831 (i == sig->sentinelpos)) {
1832 gr = S390_LAST_ARG_REG + 1;
1833 fr = S390_LAST_FPARG_REG + 1;
1834 add_general (&gr, sz, &cinfo->sigCookie);
1837 if (sig->params [i]->byref) {
1838 add_general (&gr, sz, cinfo->args+nParm);
1839 cinfo->args[nParm].size = sizeof(gpointer);
1844 ptype = mini_get_underlying_type (sig->params [i]);
1845 simpleType = ptype->type;
1846 cinfo->args[nParm].type = simpleType;
1847 switch (simpleType) {
1850 cinfo->args[nParm].size = sizeof(char);
1851 add_general (&gr, sz, cinfo->args+nParm);
1856 cinfo->args[nParm].size = sizeof(short);
1857 add_general (&gr, sz, cinfo->args+nParm);
1862 cinfo->args[nParm].size = sizeof(int);
1863 add_general (&gr, sz, cinfo->args+nParm);
1869 case MONO_TYPE_FNPTR:
1870 case MONO_TYPE_OBJECT:
1871 cinfo->args[nParm].size = sizeof(gpointer);
1872 add_general (&gr, sz, cinfo->args+nParm);
1877 cinfo->args[nParm].size = sizeof(long long);
1878 add_general (&gr, sz, cinfo->args+nParm);
1882 cinfo->args[nParm].size = sizeof(float);
1883 add_float (&fr, sz, cinfo->args+nParm);
1887 cinfo->args[nParm].size = sizeof(double);
1888 add_float (&fr, sz, cinfo->args+nParm);
1891 case MONO_TYPE_GENERICINST:
1892 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1893 cinfo->args[nParm].size = sizeof(gpointer);
1894 add_general (&gr, sz, cinfo->args+nParm);
1899 case MONO_TYPE_VALUETYPE: {
1900 MonoMarshalType *info;
1901 MonoClass *klass = mono_class_from_mono_type (ptype);
1904 size = mono_class_native_size(klass, NULL);
1906 size = mono_class_value_size(klass, NULL);
1908 if (simpleType != MONO_TYPE_GENERICINST) {
1909 info = mono_marshal_load_type_info(klass);
1911 if ((info->native_size == sizeof(float)) &&
1912 (info->num_fields == 1) &&
1913 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1914 cinfo->args[nParm].size = sizeof(float);
1915 add_float(&fr, sz, cinfo->args+nParm);
1920 if ((info->native_size == sizeof(double)) &&
1921 (info->num_fields == 1) &&
1922 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1923 cinfo->args[nParm].size = sizeof(double);
1924 add_float(&fr, sz, cinfo->args+nParm);
1930 cinfo->args[nParm].vtsize = 0;
1931 cinfo->args[nParm].size = 0;
1934 /*----------------------------------*/
1935 /* On S/390, structures of size 1, */
1936 /* 2, 4, and 8 bytes are passed in */
1937 /* (a) register(s). */
1938 /*----------------------------------*/
1944 add_general(&gr, sz, cinfo->args+nParm);
1945 cinfo->args[nParm].size = size;
1946 cinfo->args[nParm].regtype = RegTypeStructByVal;
1948 sz->local_size += sizeof(long);
1951 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1956 case MONO_TYPE_TYPEDBYREF: {
1957 int size = sizeof (MonoTypedRef);
1959 cinfo->args[nParm].vtsize = 0;
1960 cinfo->args[nParm].size = 0;
1963 /*----------------------------------*/
1964 /* On S/390, structures of size 1, */
1965 /* 2, 4, and 8 bytes are passed in */
1966 /* (a) register(s). */
1967 /*----------------------------------*/
1973 add_general(&gr, sz, cinfo->args+nParm);
1974 cinfo->args[nParm].size = size;
1975 cinfo->args[nParm].regtype = RegTypeStructByVal;
1977 sz->local_size += sizeof(long);
1980 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1986 g_error ("Can't trampoline 0x%x", ptype);
1990 /*----------------------------------------------------------*/
1991 /* Handle the case where there are no implicit arguments */
1992 /*----------------------------------------------------------*/
1993 if ((sig->call_convention == MONO_CALL_VARARG) &&
1996 (sig->param_count == sig->sentinelpos)) {
1997 gr = S390_LAST_ARG_REG + 1;
1998 fr = S390_LAST_FPARG_REG + 1;
1999 add_general (&gr, sz, &cinfo->sigCookie);
2002 /*----------------------------------------------------------*/
2003 /* If we are passing a structure back then if it won't be */
2004 /* in a register(s) then we make room at the end of the */
2005 /* parameters that may have been placed on the stack */
2006 /*----------------------------------------------------------*/
2007 if (cinfo->struct_ret) {
2008 cinfo->ret.offset = sz->stack_size;
2009 switch (cinfo->ret.size) {
2017 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
2022 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
2024 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
2029 /*========================= End of Function ========================*/
2031 /*------------------------------------------------------------------*/
2033 /* Name - mono_arch_allocate_vars */
2035 /* Function - Set var information according to the calling */
2036 /* convention for S/390. The local var stuff should */
2037 /* most likely be split in another method. */
2039 /* Parameter - @m - Compile unit. */
2041 /*------------------------------------------------------------------*/
2044 mono_arch_allocate_vars (MonoCompile *cfg)
2046 MonoMethodSignature *sig;
2047 MonoMethodHeader *header;
2050 int iParm, iVar, offset, align, size, curinst;
2051 int frame_reg = STK_BASE;
2054 header = cfg->header;
2056 cfg->flags |= MONO_CFG_HAS_SPILLUP;
2058 /*---------------------------------------------------------*/
2059 /* We use the frame register also for any method that has */
2060 /* filter clauses. This way, when the handlers are called, */
2061 /* the code will reference local variables using the frame */
2062 /* reg instead of the stack pointer: if we had to restore */
2063 /* the stack pointer, we'd corrupt the method frames that */
2064 /* are already on the stack (since filters get called */
2065 /* before stack unwinding happens) when the filter code */
2066 /* would call any method. */
2067 /*---------------------------------------------------------*/
2068 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2069 frame_reg = s390_r11;
2071 cfg->frame_reg = frame_reg;
2073 cfg->arch.bkchain_reg = -1;
2075 if (frame_reg != STK_BASE)
2076 cfg->used_int_regs |= (1LL << frame_reg);
2078 sig = mono_method_signature (cfg->method);
2080 cinfo = get_call_info (cfg, cfg->mempool, sig);
2082 if (!cinfo->struct_ret) {
2083 switch (mini_get_underlying_type (sig->ret)->type) {
2084 case MONO_TYPE_VOID:
2087 cfg->ret->opcode = OP_REGVAR;
2088 cfg->ret->dreg = s390_r2;
2093 /*--------------------------------------------------------------*/
2094 /* local vars are at a positive offset from the stack pointer */
2095 /* also note that if the function uses alloca, we use s390_r11 */
2096 /* to point at the local variables. */
2097 /* add parameter area size for called functions */
2098 /*--------------------------------------------------------------*/
2099 if (cfg->param_area == 0)
2100 offset = S390_MINIMAL_STACK_SIZE;
2102 offset = cfg->param_area;
2104 cfg->sig_cookie = 0;
2106 if (cinfo->struct_ret) {
2107 inst = cfg->vret_addr;
2108 offset = S390_ALIGN(offset, sizeof(gpointer));
2109 inst->inst_offset = offset;
2110 inst->opcode = OP_REGOFFSET;
2111 inst->inst_basereg = frame_reg;
2112 offset += sizeof(gpointer);
2113 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2114 printf ("vret_addr =");
2115 mono_print_ins (cfg->vret_addr);
2120 inst = cfg->args [0];
2121 if (inst->opcode != OP_REGVAR) {
2122 inst->opcode = OP_REGOFFSET;
2123 inst->inst_basereg = frame_reg;
2124 offset = S390_ALIGN(offset, sizeof(gpointer));
2125 inst->inst_offset = offset;
2126 offset += sizeof (gpointer);
2133 eArg = sig->param_count + sArg;
2135 if (sig->call_convention == MONO_CALL_VARARG)
2136 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2138 for (iParm = sArg; iParm < eArg; ++iParm) {
2139 inst = cfg->args [curinst];
2140 if (inst->opcode != OP_REGVAR) {
2141 switch (cinfo->args[iParm].regtype) {
2142 case RegTypeStructByAddr : {
2145 size = sizeof (gpointer);
2147 inst->opcode = OP_REGOFFSET;
2148 inst->inst_basereg = frame_reg;
2149 offset = S390_ALIGN (offset, sizeof (gpointer));
2150 inst->inst_offset = offset;
2152 /* Add a level of indirection */
2153 MONO_INST_NEW (cfg, indir, 0);
2155 inst->opcode = OP_VTARG_ADDR;
2156 inst->inst_left = indir;
2159 case RegTypeStructByAddrOnStack : {
2162 size = sizeof (gpointer);
2164 /* Similar to the == STK_BASE case below */
2165 cfg->arch.bkchain_reg = s390_r12;
2166 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2168 inst->opcode = OP_REGOFFSET;
2169 inst->dreg = mono_alloc_preg (cfg);
2170 inst->inst_basereg = cfg->arch.bkchain_reg;
2171 inst->inst_offset = cinfo->args [iParm].offset;
2173 /* Add a level of indirection */
2174 MONO_INST_NEW (cfg, indir, 0);
2176 inst->opcode = OP_VTARG_ADDR;
2177 inst->inst_left = indir;
2180 case RegTypeStructByVal :
2181 size = cinfo->args[iParm].size;
2182 offset = S390_ALIGN(offset, size);
2183 inst->opcode = OP_REGOFFSET;
2184 inst->inst_basereg = frame_reg;
2185 inst->inst_offset = offset;
2188 if (cinfo->args [iParm].reg == STK_BASE) {
2190 * These arguments are in the previous frame, so we can't
2191 * compute their offset from the current frame pointer right
2192 * now, since cfg->stack_offset is not yet known, so dedicate a
2193 * register holding the previous frame pointer.
2195 cfg->arch.bkchain_reg = s390_r12;
2196 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2198 inst->opcode = OP_REGOFFSET;
2199 inst->inst_basereg = cfg->arch.bkchain_reg;
2200 size = (cinfo->args[iParm].size < 8
2201 ? 8 - cinfo->args[iParm].size
2203 inst->inst_offset = cinfo->args [iParm].offset + size;
2204 size = sizeof (long);
2206 inst->opcode = OP_REGOFFSET;
2207 inst->inst_basereg = frame_reg;
2208 size = (cinfo->args[iParm].size < 8
2211 offset = S390_ALIGN(offset, size);
2212 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2213 inst->inst_offset = offset;
2215 inst->inst_offset = offset + (8 - size);
2219 offset += MAX(size, 8);
2224 cfg->locals_min_stack_offset = offset;
2226 curinst = cfg->locals_start;
2227 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2228 inst = cfg->varinfo [iVar];
2229 if ((inst->flags & MONO_INST_IS_DEAD) ||
2230 (inst->opcode == OP_REGVAR))
2233 /*--------------------------------------------------*/
2234 /* inst->backend.is_pinvoke indicates native sized */
2235 /* value typs this is used by the pinvoke wrappers */
2236 /* when they call functions returning structure */
2237 /*--------------------------------------------------*/
2238 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2239 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2240 (guint32 *) &align);
2242 size = mono_type_size (inst->inst_vtype, &align);
2244 offset = S390_ALIGN(offset, align);
2245 inst->inst_offset = offset;
2246 inst->opcode = OP_REGOFFSET;
2247 inst->inst_basereg = frame_reg;
2249 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2250 iVar, inst->inst_offset, size));
2253 cfg->locals_max_stack_offset = offset;
2255 /*------------------------------------------------------*/
2256 /* Allow space for the trace method stack area if needed*/
2257 /*------------------------------------------------------*/
2258 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2259 offset += S390_TRACE_STACK_SIZE;
2261 /*------------------------------------------------------*/
2262 /* Reserve space to save LMF and caller saved registers */
2263 /*------------------------------------------------------*/
2264 if (cfg->method->save_lmf)
2265 offset += sizeof (MonoLMF);
2267 /*------------------------------------------------------*/
2268 /* align the offset */
2269 /*------------------------------------------------------*/
2270 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2272 /*------------------------------------------------------*/
2273 /* Fix offsets for args whose value is in parent frame */
2274 /*------------------------------------------------------*/
2275 for (iParm = sArg; iParm < eArg; ++iParm) {
2276 inst = cfg->args [iParm];
2278 if (inst->opcode == OP_S390_STKARG) {
2279 inst->opcode = OP_REGOFFSET;
2280 inst->inst_offset += cfg->stack_offset;
2285 /*========================= End of Function ========================*/
2287 /*------------------------------------------------------------------*/
2289 /* Name - mono_arch_create_vars */
2291 /*------------------------------------------------------------------*/
2294 mono_arch_create_vars (MonoCompile *cfg)
2296 MonoMethodSignature *sig;
2299 sig = mono_method_signature (cfg->method);
2301 cinfo = get_call_info (cfg, cfg->mempool, sig);
2303 if (cinfo->struct_ret) {
2304 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2305 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2306 printf ("vret_addr = ");
2307 mono_print_ins (cfg->vret_addr);
2312 /*========================= End of Function ========================*/
2314 /*------------------------------------------------------------------*/
2316 /* Name - add_outarg_reg2. */
2318 /*------------------------------------------------------------------*/
2321 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2326 case RegTypeGeneral:
2327 MONO_INST_NEW (cfg, ins, OP_MOVE);
2328 ins->dreg = mono_alloc_ireg (cfg);
2329 ins->sreg1 = tree->dreg;
2330 MONO_ADD_INS (cfg->cbb, ins);
2331 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2334 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2335 ins->dreg = mono_alloc_freg (cfg);
2336 ins->sreg1 = tree->dreg;
2337 MONO_ADD_INS (cfg->cbb, ins);
2338 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2341 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2342 ins->dreg = mono_alloc_freg (cfg);
2343 ins->sreg1 = tree->dreg;
2344 MONO_ADD_INS (cfg->cbb, ins);
2345 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2348 g_assert_not_reached ();
2352 /*========================= End of Function ========================*/
2354 /*------------------------------------------------------------------*/
2356 /* Name - emit_sig_cookie. */
2358 /*------------------------------------------------------------------*/
2361 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2363 MonoMethodSignature *tmpSig;
2366 cfg->disable_aot = TRUE;
2368 /*----------------------------------------------------------*/
2369 /* mono_ArgIterator_Setup assumes the signature cookie is */
2370 /* passed first and all the arguments which were before it */
2371 /* passed on the stack after the signature. So compensate */
2372 /* by passing a different signature. */
2373 /*----------------------------------------------------------*/
2374 tmpSig = mono_metadata_signature_dup (call->signature);
2375 tmpSig->param_count -= call->signature->sentinelpos;
2376 tmpSig->sentinelpos = 0;
2377 if (tmpSig->param_count > 0)
2378 memcpy (tmpSig->params,
2379 call->signature->params + call->signature->sentinelpos,
2380 tmpSig->param_count * sizeof(MonoType *));
2382 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2383 sig_arg->dreg = mono_alloc_ireg (cfg);
2384 sig_arg->inst_p0 = tmpSig;
2385 MONO_ADD_INS (cfg->cbb, sig_arg);
2387 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2388 cinfo->sigCookie.offset, sig_arg->dreg);
2391 /*========================= End of Function ========================*/
2393 /*------------------------------------------------------------------*/
2395 /* Name - mono_arch_emit_call */
2397 /*------------------------------------------------------------------*/
2400 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2403 MonoMethodSignature *sig;
2405 int i, n, lParamArea;
2407 ArgInfo *ainfo = NULL;
2409 MonoMethodHeader *header;
2412 sig = call->signature;
2413 n = sig->param_count + sig->hasthis;
2414 DEBUG (g_print ("Call requires: %d parameters\n",n));
2416 cinfo = get_call_info (cfg, cfg->mempool, sig);
2418 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2419 cinfo->sz.parm_size + cinfo->sz.offset;
2420 call->stack_usage = MAX(stackSize, call->stack_usage);
2421 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2422 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2423 cfg->flags |= MONO_CFG_HAS_CALLS;
2425 if (cinfo->struct_ret) {
2426 MONO_INST_NEW (cfg, ins, OP_MOVE);
2427 ins->sreg1 = call->vret_var->dreg;
2428 ins->dreg = mono_alloc_preg (cfg);
2429 MONO_ADD_INS (cfg->cbb, ins);
2430 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2433 header = cfg->header;
2434 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2439 for (i = 0; i < n; ++i) {
2442 ainfo = cinfo->args + i;
2443 if (i >= sig->hasthis)
2444 t = sig->params [i - sig->hasthis];
2446 t = &mono_defaults.int_class->byval_arg;
2447 t = mini_get_underlying_type (t);
2449 in = call->args [i];
2451 if ((sig->call_convention == MONO_CALL_VARARG) &&
2453 (i == sig->sentinelpos)) {
2454 emit_sig_cookie (cfg, call, cinfo);
2457 switch (ainfo->regtype) {
2458 case RegTypeGeneral:
2459 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2462 if (MONO_TYPE_ISSTRUCT (t)) {
2463 /* Valuetype passed in one fp register */
2464 ainfo->regtype = RegTypeStructByValInFP;
2467 if (ainfo->size == 4)
2468 ainfo->regtype = RegTypeFPR4;
2469 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2472 case RegTypeStructByVal:
2473 case RegTypeStructByAddr:
2474 case RegTypeStructByAddrOnStack: {
2478 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2479 size = sizeof (MonoTypedRef);
2480 align = sizeof (gpointer);
2484 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2487 * Other backends use mono_type_stack_size (), but that
2488 * aligns the size to 8, which is larger than the size of
2489 * the source, leading to reads of invalid memory if the
2490 * source is at the end of address space.
2492 size = mono_class_value_size (in->klass, &align);
2495 g_assert (in->klass);
2497 ainfo->offparm += cinfo->sz.offStruct;
2499 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2500 ins->sreg1 = in->dreg;
2501 ins->klass = in->klass;
2502 ins->backend.size = ainfo->size;
2503 ins->inst_p0 = call;
2504 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2505 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2507 MONO_ADD_INS (cfg->cbb, ins);
2509 if (ainfo->regtype == RegTypeStructByAddr) {
2511 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2512 * use the normal OUTARG opcodes to pass the address of the location to
2515 int treg = mono_alloc_preg (cfg);
2516 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2517 frmReg, ainfo->offparm);
2518 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2519 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2520 /* The address of the valuetype is passed on the stack */
2521 int treg = mono_alloc_preg (cfg);
2522 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2523 frmReg, ainfo->offparm);
2524 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2525 ainfo->reg, ainfo->offset, treg);
2527 if (cfg->compute_gc_maps) {
2530 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2536 if (!t->byref && t->type == MONO_TYPE_R4) {
2537 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2538 STK_BASE, ainfo->offset + 4,
2540 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2541 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2542 STK_BASE, ainfo->offset,
2545 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2546 ins->inst_destbasereg = STK_BASE;
2547 ins->inst_offset = ainfo->offset;
2548 ins->sreg1 = in->dreg;
2549 MONO_ADD_INS (cfg->cbb, ins);
2553 g_assert_not_reached ();
2559 * Handle the case where there are no implicit arguments
2561 if ((sig->call_convention == MONO_CALL_VARARG) &&
2563 (i == sig->sentinelpos)) {
2564 emit_sig_cookie (cfg, call, cinfo);
2568 /*========================= End of Function ========================*/
2570 /*------------------------------------------------------------------*/
2572 /* Name - mono_arch_emit_outarg_vt */
2574 /*------------------------------------------------------------------*/
2577 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2579 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2580 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2581 int size = ins->backend.size;
2583 if (ainfo->regtype == RegTypeStructByVal) {
2585 arg->ins.sreg1 = ainfo->reg;
2586 arg->ins.opcode = OP_OUTARG_VT;
2587 arg->size = ainfo->size;
2588 arg->offset = ainfo->offset;
2589 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2591 if (ainfo->reg != STK_BASE) {
2592 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2594 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2597 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2598 int dreg = mono_alloc_freg (cfg);
2600 if (ainfo->size == 4) {
2601 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2602 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2604 g_assert (ainfo->size == 8);
2606 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2609 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2612 MonoMethodHeader *header;
2615 header = mono_method_get_header_checked (cfg->method, &error);
2616 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2617 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2622 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2623 src->dreg, 0, size);
2625 if (cfg->compute_gc_maps) {
2628 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2633 /*========================= End of Function ========================*/
2635 /*------------------------------------------------------------------*/
2637 /* Name - mono_arch_emit_setret */
2639 /*------------------------------------------------------------------*/
2642 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2644 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2647 if (ret->type == MONO_TYPE_R4) {
2648 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2650 } else if (ret->type == MONO_TYPE_R8) {
2651 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2656 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2659 /*========================= End of Function ========================*/
2661 /*------------------------------------------------------------------*/
2663 /* Name - mono_arch_instrument_mem_needs */
2665 /* Function - Allow tracing to work with this interface (with */
2666 /* an optional argument). */
2668 /*------------------------------------------------------------------*/
2671 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2673 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2675 /* split prolog-epilog requirements? */
2676 *code = 50; /* max bytes needed: check this number */
2679 /*========================= End of Function ========================*/
2681 /*------------------------------------------------------------------*/
2683 /* Name - mono_arch_instrument_prolog */
2685 /* Function - Create an "instrumented" prolog. */
2687 /*------------------------------------------------------------------*/
2690 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2691 gboolean enable_arguments)
2698 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2699 if (cfg->method->save_lmf)
2700 parmOffset -= sizeof(MonoLMF);
2701 fpOffset = parmOffset + (5*sizeof(gpointer));
2704 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2705 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2706 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2707 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2708 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2709 S390_SET (code, s390_r1, func);
2710 S390_SET (code, s390_r2, cfg->method);
2711 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2712 s390_lgr (code, s390_r4, STK_BASE);
2713 s390_aghi (code, s390_r4, cfg->stack_usage);
2714 s390_basr (code, s390_r14, s390_r1);
2715 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2716 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2717 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2718 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2719 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2724 /*========================= End of Function ========================*/
2726 /*------------------------------------------------------------------*/
2728 /* Name - mono_arch_instrument_epilog */
2730 /* Function - Create an epilog that will handle the returned */
2731 /* values used in instrumentation. */
2733 /*------------------------------------------------------------------*/
2736 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2739 int save_mode = SAVE_NONE,
2742 MonoMethod *method = cfg->method;
2743 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2745 offset = code - cfg->native_code;
2746 /*-----------------------------------------*/
2747 /* We need about 128 bytes of instructions */
2748 /*-----------------------------------------*/
2749 if (offset > (cfg->code_size - 128)) {
2750 cfg->code_size *= 2;
2751 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2752 code = cfg->native_code + offset;
2755 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2756 if (method->save_lmf)
2757 saveOffset -= sizeof(MonoLMF);
2761 case MONO_TYPE_VOID:
2762 /* special case string .ctor icall */
2763 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2764 save_mode = SAVE_ONE;
2766 save_mode = SAVE_NONE;
2770 save_mode = SAVE_ONE;
2773 save_mode = SAVE_R4;
2776 save_mode = SAVE_R8;
2778 case MONO_TYPE_VALUETYPE:
2779 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2780 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2783 save_mode = SAVE_STRUCT;
2786 save_mode = SAVE_ONE;
2790 switch (save_mode) {
2792 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2793 if (enable_arguments) {
2794 s390_lgr (code, s390_r3, s390_r2);
2798 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2799 if (enable_arguments) {
2800 s390_ldebr (code, s390_f0, s390_f0);
2804 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2807 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2808 if (enable_arguments) {
2809 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2810 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2818 S390_SET (code, s390_r1, func);
2819 S390_SET (code, s390_r2, cfg->method);
2820 s390_basr (code, s390_r14, s390_r1);
2822 switch (save_mode) {
2824 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2828 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2831 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2841 /*========================= End of Function ========================*/
2843 /*------------------------------------------------------------------*/
2845 /* Name - compare_and_branch */
2847 /* Function - Form a peephole pass at the code looking for */
2848 /* simple optimizations. */
2850 /*------------------------------------------------------------------*/
2853 compare_and_branch(MonoBasicBlock *bb, MonoInst *ins, int cc, gboolean logical)
2857 if (mono_hwcap_s390x_has_gie) {
2858 last = mono_inst_prev (ins, FILTER_IL_SEQ_POINT);
2859 ins->sreg1 = last->sreg1;
2860 ins->sreg2 = last->sreg2;
2862 switch(last->opcode) {
2865 ins->opcode = OP_S390_CLRJ;
2867 ins->opcode = OP_S390_CRJ;
2868 MONO_DELETE_INS(bb, last);
2873 ins->opcode = OP_S390_CLGRJ;
2875 ins->opcode = OP_S390_CGRJ;
2876 MONO_DELETE_INS(bb, last);
2878 case OP_ICOMPARE_IMM:
2879 ins->backend.data = (gpointer) last->inst_imm;
2881 ins->opcode = OP_S390_CLIJ;
2883 ins->opcode = OP_S390_CIJ;
2884 MONO_DELETE_INS(bb, last);
2886 case OP_COMPARE_IMM:
2887 case OP_LCOMPARE_IMM:
2888 ins->backend.data = (gpointer) last->inst_imm;
2890 ins->opcode = OP_S390_CLGIJ;
2892 ins->opcode = OP_S390_CGIJ;
2893 MONO_DELETE_INS(bb, last);
2899 /*========================= End of Function ========================*/
2901 /*------------------------------------------------------------------*/
2903 /* Name - mono_arch_peephole_pass_1 */
2905 /* Function - Form a peephole pass at the code looking for */
2906 /* simple optimizations. */
2908 /*------------------------------------------------------------------*/
2911 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2915 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2916 switch (ins->opcode) {
2919 compare_and_branch(bb, ins, S390_CC_EQ, FALSE);
2923 compare_and_branch(bb, ins, S390_CC_NE, TRUE);
2927 compare_and_branch(bb, ins, S390_CC_LT, FALSE);
2931 compare_and_branch(bb, ins, S390_CC_LT, TRUE);
2935 compare_and_branch(bb, ins, S390_CC_GT, FALSE);
2939 compare_and_branch(bb, ins, S390_CC_GT, TRUE);
2943 compare_and_branch(bb, ins, S390_CC_GE, FALSE);
2947 compare_and_branch(bb, ins, S390_CC_GE, TRUE);
2951 compare_and_branch(bb, ins, S390_CC_LE, FALSE);
2955 compare_and_branch(bb, ins, S390_CC_LE, TRUE);
2959 // mono_peephole_ins (bb, ins);
2964 /*========================= End of Function ========================*/
2966 /*------------------------------------------------------------------*/
2968 /* Name - mono_arch_peephole_pass_2 */
2970 /* Function - Form a peephole pass at the code looking for */
2971 /* simple optimizations. */
2973 /*------------------------------------------------------------------*/
2976 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2978 MonoInst *ins, *n, *last_ins = NULL;
2980 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2981 switch (ins->opcode) {
2982 case OP_LOADU4_MEMBASE:
2983 case OP_LOADI4_MEMBASE:
2984 if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG) &&
2985 ins->inst_basereg == last_ins->inst_destbasereg &&
2986 ins->inst_offset == last_ins->inst_offset) {
2987 ins->opcode = (ins->opcode == OP_LOADI4_MEMBASE) ? OP_ICONV_TO_I4 : OP_ICONV_TO_U4;
2988 ins->sreg1 = last_ins->sreg1;
2992 mono_peephole_ins (bb, ins);
2996 /*========================= End of Function ========================*/
2998 /*------------------------------------------------------------------*/
3000 /* Name - mono_arch_lowering_pass. */
3002 /*------------------------------------------------------------------*/
3005 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
3007 MonoInst *ins, *next;
3009 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
3010 switch (ins->opcode) {
3015 case OP_IDIV_UN_IMM:
3016 case OP_IREM_UN_IMM:
3021 case OP_LOCALLOC_IMM:
3022 mono_decompose_op_imm (cfg, bb, ins);
3025 if (!s390_is_imm16 (ins->inst_imm))
3026 /* This is created by the memcpy code which ignores is_inst_imm */
3027 mono_decompose_op_imm (cfg, bb, ins);
3034 bb->max_vreg = cfg->next_vreg;
3037 /*========================= End of Function ========================*/
3039 /*------------------------------------------------------------------*/
3041 /* Name - emit_float_to_int */
3043 /* Function - Create instructions which will convert a floating */
3044 /* point value to integer. */
3046 /*------------------------------------------------------------------*/
3049 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
3051 /* sreg is a float, dreg is an integer reg. */
3053 s390_cgdbr (code, dreg, 5, sreg);
3056 s390_ltgr (code, dreg, dreg);
3058 s390_oill (code, dreg, 0x80);
3059 s390_lghi (code, s390_r0, 0xff);
3060 s390_ngr (code, dreg, s390_r0);
3063 s390_ltgr (code, dreg, dreg);
3065 s390_oill (code, dreg, 0x8000);
3066 s390_llill(code, s390_r0, 0xffff);
3067 s390_ngr (code, dreg, s390_r0);
3072 S390_SET (code, s390_r13, 0x41e0000000000000llu);
3073 s390_ldgr (code, s390_f14, s390_r13);
3074 s390_ldr (code, s390_f15, sreg);
3075 s390_cdbr (code, s390_f15, s390_f14);
3076 s390_jl (code, 0); CODEPTR (code, o[0]);
3077 S390_SET (code, s390_r13, 0x41f0000000000000llu);
3078 s390_ldgr (code, s390_f14, s390_r13);
3079 s390_sdbr (code, s390_f15, s390_f14);
3080 s390_cfdbr (code, dreg, 7, s390_f15);
3082 PTRSLOT (code, o[0]);
3083 s390_cfdbr (code, dreg, 5, sreg);
3086 s390_lghi (code, s390_r0, 0xff);
3087 s390_ngr (code, dreg, s390_r0);
3090 s390_llill(code, s390_r0, 0xffff);
3091 s390_ngr (code, dreg, s390_r0);
3098 /*========================= End of Function ========================*/
3100 /*------------------------------------------------------------------*/
3102 /* Name - is_unsigned. */
3104 /* Function - Return TRUE if next opcode is checking for un- */
3107 /*------------------------------------------------------------------*/
3110 is_unsigned (MonoInst *next)
3113 (((next->opcode >= OP_IBNE_UN) &&
3114 (next->opcode <= OP_IBLT_UN)) ||
3115 ((next->opcode >= OP_LBNE_UN) &&
3116 (next->opcode <= OP_LBLT_UN)) ||
3117 ((next->opcode >= OP_COND_EXC_NE_UN) &&
3118 (next->opcode <= OP_COND_EXC_LT_UN)) ||
3119 ((next->opcode >= OP_COND_EXC_INE_UN) &&
3120 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
3121 ((next->opcode == OP_CLT_UN) ||
3122 (next->opcode == OP_CGT_UN) ||
3123 (next->opcode == OP_ICGE_UN) ||
3124 (next->opcode == OP_ICLE_UN)) ||
3125 ((next->opcode == OP_ICLT_UN) ||
3126 (next->opcode == OP_ICGT_UN) ||
3127 (next->opcode == OP_LCLT_UN) ||
3128 (next->opcode == OP_LCGT_UN))))
3134 /*========================= End of Function ========================*/
3136 /*------------------------------------------------------------------*/
3138 /* Name - mono_arch_output_basic_block */
3140 /* Function - Perform the "real" work of emitting instructions */
3141 /* that will do the work of in the basic block. */
3143 /*------------------------------------------------------------------*/
3146 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
3151 guint8 *code = cfg->native_code + cfg->code_len;
3152 guint last_offset = 0;
3155 /* we don't align basic blocks of loops on s390 */
3157 if (cfg->verbose_level > 2)
3158 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3160 MONO_BB_FOR_EACH_INS (bb, ins) {
3161 offset = code - cfg->native_code;
3163 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3165 if (offset > (cfg->code_size - max_len - 16)) {
3166 cfg->code_size *= 2;
3167 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3168 code = cfg->native_code + offset;
3171 mono_debug_record_line_number (cfg, ins, offset);
3173 switch (ins->opcode) {
3174 case OP_STOREI1_MEMBASE_IMM: {
3175 s390_lghi (code, s390_r0, ins->inst_imm);
3176 S390_LONG (code, stcy, stc, s390_r0, 0,
3177 ins->inst_destbasereg, ins->inst_offset);
3180 case OP_STOREI2_MEMBASE_IMM: {
3181 s390_lghi (code, s390_r0, ins->inst_imm);
3182 S390_LONG (code, sthy, sth, s390_r0, 0,
3183 ins->inst_destbasereg, ins->inst_offset);
3186 case OP_STOREI4_MEMBASE_IMM: {
3187 s390_lgfi (code, s390_r0, ins->inst_imm);
3188 S390_LONG (code, sty, st, s390_r0, 0,
3189 ins->inst_destbasereg, ins->inst_offset);
3192 case OP_STORE_MEMBASE_IMM:
3193 case OP_STOREI8_MEMBASE_IMM: {
3194 S390_SET (code, s390_r0, ins->inst_imm);
3195 S390_LONG (code, stg, stg, s390_r0, 0,
3196 ins->inst_destbasereg, ins->inst_offset);
3199 case OP_STOREI1_MEMBASE_REG: {
3200 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3201 ins->inst_destbasereg, ins->inst_offset);
3204 case OP_STOREI2_MEMBASE_REG: {
3205 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3206 ins->inst_destbasereg, ins->inst_offset);
3209 case OP_STOREI4_MEMBASE_REG: {
3210 S390_LONG (code, sty, st, ins->sreg1, 0,
3211 ins->inst_destbasereg, ins->inst_offset);
3214 case OP_STORE_MEMBASE_REG:
3215 case OP_STOREI8_MEMBASE_REG: {
3216 S390_LONG (code, stg, stg, ins->sreg1, 0,
3217 ins->inst_destbasereg, ins->inst_offset);
3221 g_assert_not_reached ();
3223 case OP_LOAD_MEMBASE:
3224 case OP_LOADI8_MEMBASE: {
3225 S390_LONG (code, lg, lg, ins->dreg, 0,
3226 ins->inst_basereg, ins->inst_offset);
3229 case OP_LOADI4_MEMBASE: {
3230 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3231 ins->inst_basereg, ins->inst_offset);
3234 case OP_LOADU4_MEMBASE: {
3235 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3236 ins->inst_basereg, ins->inst_offset);
3239 case OP_LOADU1_MEMBASE: {
3240 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3241 ins->inst_basereg, ins->inst_offset);
3244 case OP_LOADI1_MEMBASE: {
3245 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3246 ins->inst_basereg, ins->inst_offset);
3249 case OP_LOADU2_MEMBASE: {
3250 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3251 ins->inst_basereg, ins->inst_offset);
3254 case OP_LOADI2_MEMBASE: {
3255 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3256 ins->inst_basereg, ins->inst_offset);
3259 case OP_LCONV_TO_I1: {
3260 s390_lgbr (code, ins->dreg, ins->sreg1);
3263 case OP_LCONV_TO_I2: {
3264 s390_lghr (code, ins->dreg, ins->sreg1);
3267 case OP_LCONV_TO_U1: {
3268 s390_llgcr (code, ins->dreg, ins->sreg1);
3271 case OP_LCONV_TO_U2: {
3272 s390_llghr (code, ins->dreg, ins->sreg1);
3275 case OP_ICONV_TO_I1: {
3276 s390_lgbr (code, ins->dreg, ins->sreg1);
3279 case OP_ICONV_TO_I2: {
3280 s390_lghr (code, ins->dreg, ins->sreg1);
3283 case OP_ICONV_TO_U1: {
3284 s390_llgcr (code, ins->dreg, ins->sreg1);
3287 case OP_ICONV_TO_U2: {
3288 s390_llghr (code, ins->dreg, ins->sreg1);
3291 case OP_ICONV_TO_U4: {
3292 s390_llgfr (code, ins->dreg, ins->sreg1);
3295 case OP_ICONV_TO_I4: {
3296 s390_lgfr (code, ins->dreg, ins->sreg1);
3301 if (is_unsigned (ins->next))
3302 s390_clgr (code, ins->sreg1, ins->sreg2);
3304 s390_cgr (code, ins->sreg1, ins->sreg2);
3308 if (is_unsigned (ins->next))
3309 s390_clr (code, ins->sreg1, ins->sreg2);
3311 s390_cr (code, ins->sreg1, ins->sreg2);
3314 case OP_COMPARE_IMM:
3315 case OP_LCOMPARE_IMM: {
3316 gboolean branchUn = is_unsigned (ins->next);
3317 if ((ins->inst_imm == 0) && (!branchUn)) {
3318 s390_ltgr (code, ins->sreg1, ins->sreg1);
3320 S390_SET (code, s390_r0, ins->inst_imm);
3322 s390_clgr (code, ins->sreg1, s390_r0);
3324 s390_cgr (code, ins->sreg1, s390_r0);
3328 case OP_ICOMPARE_IMM: {
3329 gboolean branchUn = is_unsigned (ins->next);
3330 if ((ins->inst_imm == 0) && (!branchUn)) {
3331 s390_ltr (code, ins->sreg1, ins->sreg1);
3333 S390_SET (code, s390_r0, ins->inst_imm);
3335 s390_clr (code, ins->sreg1, s390_r0);
3337 s390_cr (code, ins->sreg1, s390_r0);
3342 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3344 S390_CALL_TEMPLATE (code, s390_r14);
3348 if (mono_hwcap_s390x_has_mlt) {
3349 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3352 s390_agr (code, ins->dreg, src2);
3357 if (mono_hwcap_s390x_has_mlt) {
3358 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3361 s390_agr (code, ins->dreg, src2);
3367 s390_alcgr (code, ins->dreg, src2);
3371 if (mono_hwcap_s390x_has_mlt) {
3372 if (s390_is_imm16 (ins->inst_imm)) {
3373 s390_aghik(code, ins->dreg, ins->sreg1, ins->inst_imm);
3375 S390_SET (code, s390_r0, ins->inst_imm);
3376 s390_agrk (code, ins->dreg, ins->sreg1, s390_r0);
3379 if (ins->dreg != ins->sreg1) {
3380 s390_lgr (code, ins->dreg, ins->sreg1);
3382 if (s390_is_imm16 (ins->inst_imm)) {
3383 s390_aghi (code, ins->dreg, ins->inst_imm);
3384 } else if (s390_is_imm32 (ins->inst_imm)) {
3385 s390_agfi (code, ins->dreg, ins->inst_imm);
3387 S390_SET (code, s390_r0, ins->inst_imm);
3388 s390_agr (code, ins->dreg, s390_r0);
3394 if (ins->dreg != ins->sreg1) {
3395 s390_lgr (code, ins->dreg, ins->sreg1);
3397 if (s390_is_imm32 (ins->inst_imm)) {
3398 s390_agfi (code, ins->dreg, ins->inst_imm);
3400 S390_SET (code, s390_r0, ins->inst_imm);
3401 s390_agr (code, ins->dreg, s390_r0);
3406 if (ins->dreg != ins->sreg1) {
3407 s390_lgr (code, ins->dreg, ins->sreg1);
3409 if (s390_is_imm16 (ins->inst_imm)) {
3410 s390_lghi (code, s390_r0, ins->inst_imm);
3411 s390_alcgr (code, ins->dreg, s390_r0);
3413 S390_SET (code, s390_r0, ins->inst_imm);
3414 s390_alcgr (code, ins->dreg, s390_r0);
3419 case OP_S390_IADD_OVF: {
3421 s390_ar (code, ins->dreg, src2);
3422 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3423 s390_lgfr (code, ins->dreg, ins->dreg);
3426 case OP_IADD_OVF_UN:
3427 case OP_S390_IADD_OVF_UN: {
3429 s390_algr (code, ins->dreg, src2);
3430 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3431 s390_llgfr (code, ins->dreg, ins->dreg);
3434 case OP_ADD_OVF_CARRY: {
3436 s390_lghi (code, s390_r0, 0);
3437 s390_lgr (code, s390_r1, s390_r0);
3438 s390_alcgr (code, s390_r0, s390_r1);
3439 s390_agr (code, ins->dreg, src2);
3440 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3441 s390_agr (code, ins->dreg, s390_r0);
3442 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3445 case OP_ADD_OVF_UN_CARRY: {
3447 s390_alcgr (code, ins->dreg, src2);
3448 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3452 if (mono_hwcap_s390x_has_mlt) {
3453 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3456 s390_sgr (code, ins->dreg, src2);
3461 if (mono_hwcap_s390x_has_mlt) {
3462 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3465 s390_sgr (code, ins->dreg, src2);
3471 s390_slbgr(code, ins->dreg, src2);
3475 if (ins->dreg != ins->sreg1) {
3476 s390_lgr (code, ins->dreg, ins->sreg1);
3478 if (s390_is_imm16 (-ins->inst_imm)) {
3479 s390_aghi (code, ins->dreg, -ins->inst_imm);
3480 } else if (s390_is_imm32 (-ins->inst_imm)) {
3481 s390_slgfi (code, ins->dreg, ins->inst_imm);
3483 S390_SET (code, s390_r0, ins->inst_imm);
3484 s390_slgr (code, ins->dreg, s390_r0);
3489 if (ins->dreg != ins->sreg1) {
3490 s390_lgr (code, ins->dreg, ins->sreg1);
3492 if (s390_is_imm16 (-ins->inst_imm)) {
3493 s390_aghi (code, ins->dreg, -ins->inst_imm);
3494 } else if (s390_is_imm32 (-ins->inst_imm)) {
3495 s390_slgfi (code, ins->dreg, ins->inst_imm);
3497 S390_SET (code, s390_r0, ins->inst_imm);
3498 s390_slgr (code, ins->dreg, s390_r0);
3503 if (ins->dreg != ins->sreg1) {
3504 s390_lgr (code, ins->dreg, ins->sreg1);
3506 if (s390_is_imm16 (-ins->inst_imm)) {
3507 s390_lghi (code, s390_r0, ins->inst_imm);
3508 s390_slbgr (code, ins->dreg, s390_r0);
3510 S390_SET (code, s390_r0, ins->inst_imm);
3511 s390_slbgr(code, ins->dreg, s390_r0);
3515 case OP_SUB_OVF_CARRY: {
3517 s390_lghi (code, s390_r0, 0);
3518 s390_lgr (code, s390_r1, s390_r0);
3519 s390_slbgr (code, s390_r0, s390_r1);
3520 s390_sgr (code, ins->dreg, src2);
3521 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3522 s390_agr (code, ins->dreg, s390_r0);
3523 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3526 case OP_SUB_OVF_UN_CARRY: {
3528 s390_slbgr (code, ins->dreg, src2);
3529 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3533 if (mono_hwcap_s390x_has_mlt) {
3534 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3536 if (ins->sreg1 == ins->dreg) {
3537 s390_ngr (code, ins->dreg, ins->sreg2);
3539 if (ins->sreg2 == ins->dreg) {
3540 s390_ngr (code, ins->dreg, ins->sreg1);
3542 s390_lgr (code, ins->dreg, ins->sreg1);
3543 s390_ngr (code, ins->dreg, ins->sreg2);
3550 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3551 if (mono_hwcap_s390x_has_mlt) {
3552 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3554 if (ins->dreg != ins->sreg1) {
3555 s390_lgr (code, ins->dreg, ins->sreg1);
3557 s390_ngr (code, ins->dreg, s390_r0);
3562 s390_lgr (code, s390_r1, ins->sreg1);
3563 s390_dsgr (code, s390_r0, ins->sreg2);
3564 s390_lgr (code, ins->dreg, s390_r1);
3568 s390_lgr (code, s390_r1, ins->sreg1);
3569 s390_lghi (code, s390_r0, 0);
3570 s390_dlgr (code, s390_r0, ins->sreg2);
3571 s390_lgr (code, ins->dreg, s390_r1);
3575 s390_lgr (code, s390_r1, ins->sreg1);
3576 s390_dsgr (code, s390_r0, ins->sreg2);
3577 s390_lgr (code, ins->dreg, s390_r0);
3581 if (s390_is_imm16 (ins->inst_imm)) {
3582 s390_lghi (code, s390_r13, ins->inst_imm);
3584 s390_lgfi (code, s390_r13, ins->inst_imm);
3586 s390_lgr (code, s390_r0, ins->sreg1);
3587 s390_dsgr (code, s390_r0, s390_r13);
3588 s390_lgfr (code, ins->dreg, s390_r0);
3592 s390_lgr (code, s390_r1, ins->sreg1);
3593 s390_lghi (code, s390_r0, 0);
3594 s390_dlgr (code, s390_r0, ins->sreg2);
3595 s390_lgr (code, ins->dreg, s390_r0);
3599 if (mono_hwcap_s390x_has_mlt) {
3600 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3602 if (ins->sreg1 == ins->dreg) {
3603 s390_ogr (code, ins->dreg, ins->sreg2);
3605 if (ins->sreg2 == ins->dreg) {
3606 s390_ogr (code, ins->dreg, ins->sreg1);
3608 s390_lgr (code, ins->dreg, ins->sreg1);
3609 s390_ogr (code, ins->dreg, ins->sreg2);
3616 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3617 if (mono_hwcap_s390x_has_mlt) {
3618 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3620 if (ins->dreg != ins->sreg1) {
3621 s390_lgr (code, ins->dreg, ins->sreg1);
3623 s390_ogr (code, ins->dreg, s390_r0);
3628 if (mono_hwcap_s390x_has_mlt) {
3629 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3631 if (ins->sreg1 == ins->dreg) {
3632 s390_xgr (code, ins->dreg, ins->sreg2);
3635 if (ins->sreg2 == ins->dreg) {
3636 s390_xgr (code, ins->dreg, ins->sreg1);
3639 s390_lgr (code, ins->dreg, ins->sreg1);
3640 s390_xgr (code, ins->dreg, ins->sreg2);
3647 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3648 if (mono_hwcap_s390x_has_mlt) {
3649 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3651 if (ins->dreg != ins->sreg1) {
3652 s390_lgr (code, ins->dreg, ins->sreg1);
3654 s390_xgr (code, ins->dreg, s390_r0);
3660 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3665 if (ins->sreg1 != ins->dreg) {
3666 s390_lgr (code, ins->dreg, ins->sreg1);
3668 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3673 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3678 if (ins->sreg1 != ins->dreg) {
3679 s390_lgr (code, ins->dreg, ins->sreg1);
3681 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3685 case OP_LSHR_UN_IMM: {
3686 if (ins->sreg1 != ins->dreg) {
3687 s390_lgr (code, ins->dreg, ins->sreg1);
3689 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3694 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3698 if (ins->sreg1 != ins->dreg) {
3699 s390_lgr (code, ins->dreg, ins->sreg1);
3701 s390_lghi (code, s390_r0, -1);
3702 s390_xgr (code, ins->dreg, s390_r0);
3706 s390_lcgr (code, ins->dreg, ins->sreg1);
3711 s390_msgr (code, ins->dreg, src2);
3716 if (ins->dreg != ins->sreg1) {
3717 s390_lgr (code, ins->dreg, ins->sreg1);
3719 if (s390_is_imm16 (ins->inst_imm)) {
3720 s390_lghi (code, s390_r13, ins->inst_imm);
3721 } else if (s390_is_imm32 (ins->inst_imm)) {
3722 s390_lgfi (code, s390_r13, ins->inst_imm);
3724 S390_SET (code, s390_r13, ins->inst_imm);
3726 s390_msgr (code, ins->dreg, s390_r13);
3731 s390_ltgr (code, s390_r1, ins->sreg1);
3732 s390_jz (code, 0); CODEPTR(code, o[0]);
3733 s390_ltgr (code, s390_r0, ins->sreg2);
3735 s390_lghi (code, s390_r1, 0);
3736 s390_j (code, 0); CODEPTR(code, o[1]);
3737 s390_xgr (code, s390_r0, s390_r1);
3738 s390_msgr (code, s390_r1, ins->sreg2);
3739 s390_xgr (code, s390_r0, s390_r1);
3740 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3741 s390_ltgr (code, s390_r0, s390_r0);
3742 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3743 PTRSLOT (code, o[0]);
3744 PTRSLOT (code, o[1]);
3745 s390_lgr (code, ins->dreg, s390_r1);
3748 case OP_LMUL_OVF_UN: {
3749 s390_lghi (code, s390_r0, 0);
3750 s390_lgr (code, s390_r1, ins->sreg1);
3751 s390_mlgr (code, s390_r0, ins->sreg2);
3752 s390_ltgr (code, s390_r0, s390_r0);
3753 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3754 s390_lgr (code, ins->dreg, s390_r1);
3758 g_assert_not_reached ();
3760 s390_algr (code, ins->dreg, src2);
3765 s390_agr (code, ins->dreg, src2);
3769 g_assert_not_reached ();
3771 s390_alcgr (code, ins->dreg, src2);
3775 if (ins->dreg != ins->sreg1) {
3776 s390_lgfr (code, ins->dreg, ins->sreg1);
3778 if (s390_is_imm16 (ins->inst_imm)) {
3779 s390_aghi (code, ins->dreg, ins->inst_imm);
3781 s390_afi (code, ins->dreg, ins->inst_imm);
3786 if (ins->dreg != ins->sreg1) {
3787 s390_lgfr (code, ins->dreg, ins->sreg1);
3789 if (s390_is_imm16 (ins->inst_imm)) {
3790 s390_lghi (code, s390_r0, ins->inst_imm);
3791 s390_alcgr (code, ins->dreg, s390_r0);
3793 S390_SET (code, s390_r0, ins->inst_imm);
3794 s390_alcgr (code, ins->dreg, s390_r0);
3799 case OP_S390_LADD_OVF: {
3801 s390_agr (code, ins->dreg, src2);
3802 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3805 case OP_LADD_OVF_UN:
3806 case OP_S390_LADD_OVF_UN: {
3808 s390_algr (code, ins->dreg, src2);
3809 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3813 CHECK_SRCDST_NCOM_I;
3814 s390_slgr (code, ins->dreg, src2);
3818 CHECK_SRCDST_NCOM_I;
3819 s390_sgr (code, ins->dreg, src2);
3823 CHECK_SRCDST_NCOM_I;
3824 s390_slbgr (code, ins->dreg, src2);
3828 if (ins->dreg != ins->sreg1) {
3829 s390_lgfr (code, ins->dreg, ins->sreg1);
3831 if (s390_is_imm16 (-ins->inst_imm)) {
3832 s390_aghi (code, ins->dreg, -ins->inst_imm);
3834 s390_agfi (code, ins->dreg, -ins->inst_imm);
3839 S390_SET (code, s390_r0, ins->inst_imm);
3840 s390_slgfr (code, ins->dreg, s390_r0);
3844 case OP_S390_ISUB_OVF: {
3846 s390_sr (code, ins->dreg, src2);
3847 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3848 s390_lgfr (code, ins->dreg, ins->dreg);
3851 case OP_ISUB_OVF_UN:
3852 case OP_S390_ISUB_OVF_UN: {
3854 s390_slr (code, ins->dreg, src2);
3855 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3856 s390_llgfr(code, ins->dreg, ins->dreg);
3860 case OP_S390_LSUB_OVF: {
3862 s390_sgr (code, ins->dreg, src2);
3863 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3866 case OP_LSUB_OVF_UN:
3867 case OP_S390_LSUB_OVF_UN: {
3869 s390_slgr (code, ins->dreg, src2);
3870 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3874 if (mono_hwcap_s390x_has_mlt) {
3875 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3877 CHECK_SRCDST_NCOM_I;
3878 s390_ngr (code, ins->dreg, src2);
3883 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3884 if (mono_hwcap_s390x_has_mlt) {
3885 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3887 if (ins->dreg != ins->sreg1) {
3888 s390_lgfr (code, ins->dreg, ins->sreg1);
3890 s390_ngr (code, ins->dreg, s390_r0);
3895 s390_lgfr (code, s390_r0, ins->sreg1);
3896 s390_srda (code, s390_r0, 0, 32);
3897 s390_dr (code, s390_r0, ins->sreg2);
3898 s390_lgfr (code, ins->dreg, s390_r1);
3902 s390_lgfr (code, s390_r0, ins->sreg1);
3903 s390_srdl (code, s390_r0, 0, 32);
3904 s390_dlr (code, s390_r0, ins->sreg2);
3905 s390_lgfr (code, ins->dreg, s390_r1);
3909 if (s390_is_imm16 (ins->inst_imm)) {
3910 s390_lghi (code, s390_r13, ins->inst_imm);
3912 s390_lgfi (code, s390_r13, ins->inst_imm);
3914 s390_lgfr (code, s390_r0, ins->sreg1);
3915 s390_srda (code, s390_r0, 0, 32);
3916 s390_dr (code, s390_r0, ins->sreg2);
3917 s390_lgfr (code, ins->dreg, s390_r1);
3921 s390_lgfr (code, s390_r0, ins->sreg1);
3922 s390_srda (code, s390_r0, 0, 32);
3923 s390_dr (code, s390_r0, ins->sreg2);
3924 s390_lgfr (code, ins->dreg, s390_r0);
3927 s390_lgfr (code, s390_r0, ins->sreg1);
3928 s390_srdl (code, s390_r0, 0, 32);
3929 s390_dlr (code, s390_r0, ins->sreg2);
3930 s390_lgfr (code, ins->dreg, s390_r0);
3934 if (s390_is_imm16 (ins->inst_imm)) {
3935 s390_lghi (code, s390_r13, ins->inst_imm);
3937 s390_lgfi (code, s390_r13, ins->inst_imm);
3939 s390_lgfr (code, s390_r0, ins->sreg1);
3940 s390_srda (code, s390_r0, 0, 32);
3941 s390_dr (code, s390_r0, ins->sreg2);
3942 s390_lgfr (code, ins->dreg, s390_r0);
3946 if (mono_hwcap_s390x_has_mlt) {
3947 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3950 s390_ogr (code, ins->dreg, src2);
3955 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3956 if (mono_hwcap_s390x_has_mlt) {
3957 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3959 if (ins->dreg != ins->sreg1) {
3960 s390_lgfr (code, ins->dreg, ins->sreg1);
3962 s390_ogr (code, ins->dreg, s390_r0);
3967 if (mono_hwcap_s390x_has_mlt) {
3968 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3971 s390_xgr (code, ins->dreg, src2);
3976 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3977 if (mono_hwcap_s390x_has_mlt) {
3978 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3980 if (ins->dreg != ins->sreg1) {
3981 s390_lgfr (code, ins->dreg, ins->sreg1);
3983 s390_xgr (code, ins->dreg, s390_r0);
3989 s390_sll (code, ins->dreg, src2, 0);
3993 if (ins->sreg1 != ins->dreg) {
3994 s390_lgfr (code, ins->dreg, ins->sreg1);
3996 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4001 s390_sra (code, ins->dreg, src2, 0);
4005 if (ins->sreg1 != ins->dreg) {
4006 s390_lgfr (code, ins->dreg, ins->sreg1);
4008 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4011 case OP_ISHR_UN_IMM: {
4012 if (ins->sreg1 != ins->dreg) {
4013 s390_lgfr (code, ins->dreg, ins->sreg1);
4015 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4020 s390_srl (code, ins->dreg, src2, 0);
4024 if (ins->sreg1 != ins->dreg) {
4025 s390_lgfr (code, ins->dreg, ins->sreg1);
4027 s390_lghi (code, s390_r0, -1);
4028 s390_xgr (code, ins->dreg, s390_r0);
4032 s390_lcgr (code, ins->dreg, ins->sreg1);
4037 s390_msr (code, ins->dreg, src2);
4041 if (ins->dreg != ins->sreg1) {
4042 s390_lgfr (code, ins->dreg, ins->sreg1);
4044 if (s390_is_imm16 (ins->inst_imm)) {
4045 s390_lghi (code, s390_r0, ins->inst_imm);
4047 s390_lgfi (code, s390_r0, ins->inst_imm);
4049 s390_msr (code, ins->dreg, s390_r0);
4054 s390_ltr (code, s390_r1, ins->sreg1);
4055 s390_jz (code, 0); CODEPTR(code, o[0]);
4056 s390_ltr (code, s390_r0, ins->sreg2);
4058 s390_lhi (code, s390_r1, 0);
4059 s390_j (code, 0); CODEPTR(code, o[1]);
4060 s390_xr (code, s390_r0, s390_r1);
4061 s390_msr (code, s390_r1, ins->sreg2);
4062 s390_xr (code, s390_r0, s390_r1);
4063 s390_srl (code, s390_r0, 0, 31);
4064 s390_ltr (code, s390_r0, s390_r0);
4065 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4066 PTRSLOT (code, o[0]);
4067 PTRSLOT (code, o[1]);
4068 s390_lgfr (code, ins->dreg, s390_r1);
4071 case OP_IMUL_OVF_UN: {
4072 s390_lhi (code, s390_r0, 0);
4073 s390_lr (code, s390_r1, ins->sreg1);
4074 s390_mlr (code, s390_r0, ins->sreg2);
4075 s390_ltr (code, s390_r0, s390_r0);
4076 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4077 s390_lgfr (code, ins->dreg, s390_r1);
4082 S390_SET (code, ins->dreg, ins->inst_c0);
4086 mono_add_patch_info (cfg, code - cfg->native_code,
4087 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4088 S390_LOAD_TEMPLATE (code, ins->dreg);
4091 case OP_JUMP_TABLE: {
4092 mono_add_patch_info (cfg, code - cfg->native_code,
4093 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4094 S390_LOAD_TEMPLATE (code, ins->dreg);
4098 if (ins->dreg != ins->sreg1) {
4099 s390_lgr (code, ins->dreg, ins->sreg1);
4103 case OP_LCONV_TO_I8:
4105 s390_lgfr (code, ins->dreg, ins->sreg1);
4107 case OP_LCONV_TO_I4:
4108 s390_lgfr (code, ins->dreg, ins->sreg1);
4111 case OP_LCONV_TO_U8:
4112 case OP_LCONV_TO_U4:
4114 s390_llgfr (code, ins->dreg, ins->sreg1);
4116 case OP_LCONV_TO_OVF_U4:
4117 S390_SET (code, s390_r0, 4294967295);
4118 s390_clgr (code, ins->sreg1, s390_r0);
4119 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4120 s390_ltgr (code, ins->sreg1, ins->sreg1);
4121 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4122 s390_llgfr(code, ins->dreg, ins->sreg1);
4124 case OP_LCONV_TO_OVF_I4_UN:
4125 S390_SET (code, s390_r0, 2147483647);
4126 s390_cgr (code, ins->sreg1, s390_r0);
4127 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4128 s390_ltgr (code, ins->sreg1, ins->sreg1);
4129 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4130 s390_lgfr (code, ins->dreg, ins->sreg1);
4133 if (ins->dreg != ins->sreg1) {
4134 s390_ldr (code, ins->dreg, ins->sreg1);
4137 case OP_MOVE_F_TO_I8:
4138 s390_lgdr (code, ins->dreg, ins->sreg1);
4140 case OP_MOVE_I8_TO_F:
4141 s390_ldgr (code, ins->dreg, ins->sreg1);
4143 case OP_MOVE_F_TO_I4:
4144 s390_ledbr (code, s390_f0, ins->sreg1);
4145 s390_lgdr (code, ins->dreg, s390_f0);
4146 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
4148 case OP_MOVE_I4_TO_F:
4149 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
4150 s390_ldgr (code, ins->dreg, s390_r0);
4151 s390_ldebr (code, ins->dreg, ins->dreg);
4153 case OP_FCONV_TO_R4:
4154 s390_ledbr (code, ins->dreg, ins->sreg1);
4155 s390_ldebr (code, ins->dreg, ins->dreg);
4157 case OP_S390_SETF4RET:
4158 s390_ledbr (code, ins->dreg, ins->sreg1);
4161 if (s390_is_imm16 (ins->inst_offset)) {
4162 s390_lghi (code, s390_r13, ins->inst_offset);
4163 } else if (s390_is_imm32 (ins->inst_offset)) {
4164 s390_lgfi (code, s390_r13, ins->inst_offset);
4166 S390_SET (code, s390_r13, ins->inst_offset);
4168 s390_ear (code, s390_r1, 0);
4169 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4170 s390_ear (code, s390_r1, 1);
4171 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
4175 if (s390_is_imm16 (ins->inst_offset)) {
4176 s390_lghi (code, s390_r13, ins->inst_offset);
4177 } else if (s390_is_imm32 (ins->inst_offset)) {
4178 s390_lgfi (code, s390_r13, ins->inst_offset);
4180 S390_SET (code, s390_r13, ins->inst_offset);
4182 s390_ear (code, s390_r1, 0);
4183 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4184 s390_ear (code, s390_r1, 1);
4185 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
4189 if (cfg->method->save_lmf)
4190 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4192 if (cfg->flags & MONO_CFG_HAS_TAIL) {
4193 code = emit_load_volatile_arguments (code, cfg);
4196 code = backUpStackPtr(cfg, code);
4197 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
4198 mono_add_patch_info (cfg, code - cfg->native_code,
4199 MONO_PATCH_INFO_METHOD_JUMP,
4201 s390_jcl (code, S390_CC_UN, 0);
4204 case OP_CHECK_THIS: {
4205 /* ensure ins->sreg1 is not NULL */
4206 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
4207 s390_ltgr (code, s390_r0, s390_r0);
4208 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4212 int offset = cfg->sig_cookie + cfg->stack_usage;
4214 if (s390_is_imm16 (offset)) {
4215 s390_lghi (code, s390_r0, offset);
4216 } else if (s390_is_imm32 (offset)) {
4217 s390_lgfi (code, s390_r0, offset);
4219 S390_SET (code, s390_r0, offset);
4221 s390_agr (code, s390_r0, cfg->frame_reg);
4222 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
4226 call = (MonoCallInst*)ins;
4227 if (ins->flags & MONO_INST_HAS_METHOD)
4228 mono_add_patch_info (cfg, code-cfg->native_code,
4229 MONO_PATCH_INFO_METHOD,
4232 mono_add_patch_info (cfg, code-cfg->native_code,
4233 MONO_PATCH_INFO_ABS,
4235 S390_CALL_TEMPLATE (code, s390_r14);
4236 if (call->signature->ret->type == MONO_TYPE_R4)
4237 s390_ldebr (code, s390_f0, s390_f0);
4245 call = (MonoCallInst*)ins;
4246 if (ins->flags & MONO_INST_HAS_METHOD)
4247 mono_add_patch_info (cfg, code-cfg->native_code,
4248 MONO_PATCH_INFO_METHOD,
4251 mono_add_patch_info (cfg, code-cfg->native_code,
4252 MONO_PATCH_INFO_ABS,
4254 S390_CALL_TEMPLATE (code, s390_r14);
4257 case OP_FCALL_REG: {
4258 call = (MonoCallInst*)ins;
4259 s390_lgr (code, s390_r1, ins->sreg1);
4260 s390_basr (code, s390_r14, s390_r1);
4261 if (call->signature->ret->type == MONO_TYPE_R4)
4262 s390_ldebr (code, s390_f0, s390_f0);
4268 case OP_VOIDCALL_REG:
4270 s390_lgr (code, s390_r1, ins->sreg1);
4271 s390_basr (code, s390_r14, s390_r1);
4274 case OP_FCALL_MEMBASE: {
4275 call = (MonoCallInst*)ins;
4276 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4277 s390_basr (code, s390_r14, s390_r1);
4278 if (call->signature->ret->type == MONO_TYPE_R4)
4279 s390_ldebr (code, s390_f0, s390_f0);
4282 case OP_LCALL_MEMBASE:
4283 case OP_VCALL_MEMBASE:
4284 case OP_VCALL2_MEMBASE:
4285 case OP_VOIDCALL_MEMBASE:
4286 case OP_CALL_MEMBASE: {
4287 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4288 s390_basr (code, s390_r14, s390_r1);
4295 if (cfg->param_area == 0)
4296 alloca_skip = S390_MINIMAL_STACK_SIZE;
4298 alloca_skip = cfg->param_area;
4300 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4301 s390_lgr (code, s390_r1, ins->sreg1);
4302 if (ins->flags & MONO_INST_INIT)
4303 s390_lgr (code, s390_r0, ins->sreg1);
4304 s390_aghi (code, s390_r1, 14);
4305 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4306 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4307 if (cfg->method->save_lmf) {
4308 /*----------------------------------*/
4309 /* we have to adjust lmf ebp value */
4310 /*----------------------------------*/
4311 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4313 s390_lgr (code, s390_r13, cfg->frame_reg);
4314 if (s390_is_imm16(lmfOffset)) {
4315 s390_aghi (code, s390_r13, lmfOffset);
4316 } else if (s390_is_imm32(lmfOffset)) {
4317 s390_agfi (code, s390_r13, lmfOffset);
4319 S390_SET (code, s390_r13, lmfOffset);
4321 s390_lgr (code, s390_r14, STK_BASE);
4322 s390_sgr (code, s390_r14, s390_r1);
4323 s390_stg (code, s390_r14, 0, s390_r13,
4324 G_STRUCT_OFFSET(MonoLMF, ebp));
4326 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4327 s390_sgr (code, STK_BASE, s390_r1);
4328 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4329 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4330 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4331 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4332 if (ins->flags & MONO_INST_INIT) {
4333 s390_lgr (code, s390_r1, s390_r0);
4334 s390_lgr (code, s390_r0, ins->dreg);
4335 s390_lgr (code, s390_r14, s390_r12);
4336 s390_lghi (code, s390_r13, 0);
4337 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4339 s390_lgr (code, s390_r12, s390_r14);
4344 s390_lgr (code, s390_r2, ins->sreg1);
4345 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4346 (gpointer) "mono_arch_throw_exception");
4347 S390_CALL_TEMPLATE(code, s390_r14);
4351 s390_lgr (code, s390_r2, ins->sreg1);
4352 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4353 (gpointer) "mono_arch_rethrow_exception");
4354 S390_CALL_TEMPLATE(code, s390_r14);
4357 case OP_START_HANDLER: {
4358 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4360 S390_LONG (code, stg, stg, s390_r14, 0,
4361 spvar->inst_basereg,
4362 spvar->inst_offset);
4365 case OP_ENDFILTER: {
4366 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4368 if (ins->sreg1 != s390_r2)
4369 s390_lgr(code, s390_r2, ins->sreg1);
4370 S390_LONG (code, lg, lg, s390_r14, 0,
4371 spvar->inst_basereg,
4372 spvar->inst_offset);
4373 s390_br (code, s390_r14);
4376 case OP_ENDFINALLY: {
4377 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4379 S390_LONG (code, lg, lg, s390_r14, 0,
4380 spvar->inst_basereg,
4381 spvar->inst_offset);
4382 s390_br (code, s390_r14);
4385 case OP_CALL_HANDLER: {
4386 mono_add_patch_info (cfg, code-cfg->native_code,
4387 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4388 s390_brasl (code, s390_r14, 0);
4389 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4393 ins->inst_c0 = code - cfg->native_code;
4396 case OP_RELAXED_NOP:
4399 case OP_DUMMY_STORE:
4400 case OP_NOT_REACHED:
4404 case OP_IL_SEQ_POINT:
4405 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4407 case OP_SEQ_POINT: {
4410 if (cfg->compile_aot)
4414 * Read from the single stepping trigger page. This will cause a
4415 * SIGSEGV when single stepping is enabled.
4416 * We do this _before_ the breakpoint, so single stepping after
4417 * a breakpoint is hit will step to the next IL offset.
4419 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4420 breakpointCode.pTrigger = ss_trigger_page;
4421 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4422 code += BREAKPOINT_SIZE;
4425 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4428 * A placeholder for a possible breakpoint inserted by
4429 * mono_arch_set_breakpoint ().
4431 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4435 * Add an additional nop so skipping the bp doesn't cause the ip to point
4436 * to another IL offset.
4442 case OP_GENERIC_CLASS_INIT: {
4443 static int byte_offset = -1;
4444 static guint8 bitmask;
4447 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4449 if (byte_offset < 0)
4450 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4452 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4453 s390_jo (code, 0); CODEPTR(code, jump);
4455 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4456 "mono_generic_class_init");
4457 S390_CALL_TEMPLATE(code, s390_r14);
4459 PTRSLOT (code, jump);
4461 ins->flags |= MONO_INST_GC_CALLSITE;
4462 ins->backend.pc_offset = code - cfg->native_code;
4466 EMIT_UNCOND_BRANCH(ins);
4469 s390_br (code, ins->sreg1);
4475 s390_lghi(code, ins->dreg, 1);
4477 s390_lghi(code, ins->dreg, 0);
4483 s390_lghi(code, ins->dreg, 1);
4485 s390_lghi(code, ins->dreg, 0);
4491 s390_lghi(code, ins->dreg, 1);
4493 s390_lghi(code, ins->dreg, 0);
4499 s390_lghi(code, ins->dreg, 1);
4501 s390_lghi(code, ins->dreg, 0);
4507 s390_lghi(code, ins->dreg, 1);
4509 s390_lghi(code, ins->dreg, 0);
4513 s390_lghi(code, ins->dreg, 1);
4515 s390_lghi(code, ins->dreg, 0);
4519 s390_lghi(code, ins->dreg, 1);
4521 s390_lghi(code, ins->dreg, 0);
4525 s390_lghi(code, ins->dreg, 1);
4527 s390_lghi(code, ins->dreg, 0);
4531 s390_lghi(code, ins->dreg, 1);
4533 s390_lghi(code, ins->dreg, 0);
4537 s390_lghi(code, ins->dreg, 1);
4539 s390_lghi(code, ins->dreg, 0);
4542 case OP_COND_EXC_EQ:
4543 case OP_COND_EXC_IEQ:
4544 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4546 case OP_COND_EXC_NE_UN:
4547 case OP_COND_EXC_INE_UN:
4548 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4550 case OP_COND_EXC_LT:
4551 case OP_COND_EXC_ILT:
4552 case OP_COND_EXC_LT_UN:
4553 case OP_COND_EXC_ILT_UN:
4554 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4556 case OP_COND_EXC_GT:
4557 case OP_COND_EXC_IGT:
4558 case OP_COND_EXC_GT_UN:
4559 case OP_COND_EXC_IGT_UN:
4560 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4562 case OP_COND_EXC_GE:
4563 case OP_COND_EXC_IGE:
4564 case OP_COND_EXC_GE_UN:
4565 case OP_COND_EXC_IGE_UN:
4566 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4568 case OP_COND_EXC_LE:
4569 case OP_COND_EXC_ILE:
4570 case OP_COND_EXC_LE_UN:
4571 case OP_COND_EXC_ILE_UN:
4572 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4574 case OP_COND_EXC_OV:
4575 case OP_COND_EXC_IOV:
4576 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4578 case OP_COND_EXC_NO:
4579 case OP_COND_EXC_INO:
4580 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4583 case OP_COND_EXC_IC:
4584 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4586 case OP_COND_EXC_NC:
4587 case OP_COND_EXC_INC:
4588 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4592 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4596 EMIT_COND_BRANCH (ins, S390_CC_NE);
4602 EMIT_COND_BRANCH (ins, S390_CC_LT);
4608 EMIT_COND_BRANCH (ins, S390_CC_GT);
4614 EMIT_COND_BRANCH (ins, S390_CC_GE);
4620 EMIT_COND_BRANCH (ins, S390_CC_LE);
4624 EMIT_COMP_AND_BRANCH(ins, crj, cr);
4628 EMIT_COMP_AND_BRANCH(ins, clrj, clr);
4632 EMIT_COMP_AND_BRANCH(ins, cgrj, cgr);
4636 EMIT_COMP_AND_BRANCH(ins, clgrj, clgr);
4640 EMIT_COMP_AND_BRANCH_IMM(ins, crj, cr, ltr, FALSE);
4644 EMIT_COMP_AND_BRANCH_IMM(ins, clrj, clr, ltr, TRUE);
4648 EMIT_COMP_AND_BRANCH_IMM(ins, cgrj, cgr, ltgr, FALSE);
4652 EMIT_COMP_AND_BRANCH_IMM(ins, clgrj, clgr, ltgr, TRUE);
4655 /* floating point opcodes */
4657 if (*((double *) ins->inst_p0) == 0) {
4658 s390_lzdr (code, ins->dreg);
4660 S390_SET (code, s390_r13, ins->inst_p0);
4661 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4666 if (*((float *) ins->inst_p0) == 0) {
4667 s390_lzdr (code, ins->dreg);
4669 S390_SET (code, s390_r13, ins->inst_p0);
4670 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4674 case OP_STORER8_MEMBASE_REG: {
4675 S390_LONG (code, stdy, std, ins->sreg1, 0,
4676 ins->inst_destbasereg, ins->inst_offset);
4679 case OP_LOADR8_MEMBASE: {
4680 S390_LONG (code, ldy, ld, ins->dreg, 0,
4681 ins->inst_basereg, ins->inst_offset);
4684 case OP_STORER4_MEMBASE_REG: {
4685 s390_ledbr (code, s390_f15, ins->sreg1);
4686 S390_LONG (code, stey, ste, s390_f15, 0,
4687 ins->inst_destbasereg, ins->inst_offset);
4690 case OP_LOADR4_MEMBASE: {
4691 S390_LONG (code, ley, le, s390_f15, 0,
4692 ins->inst_basereg, ins->inst_offset);
4693 s390_ldebr (code, ins->dreg, s390_f15);
4696 case OP_ICONV_TO_R_UN: {
4697 if (mono_hwcap_s390x_has_fpe) {
4698 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4700 s390_llgfr (code, s390_r0, ins->sreg1);
4701 s390_cdgbr (code, ins->dreg, s390_r0);
4705 case OP_LCONV_TO_R_UN: {
4706 if (mono_hwcap_s390x_has_fpe) {
4707 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4710 s390_cxgbr (code, s390_f12, ins->sreg1);
4711 s390_ltgr (code, ins->sreg1, ins->sreg1);
4712 s390_jnl (code, 0); CODEPTR(code, jump);
4713 S390_SET (code, s390_r13, 0x403f000000000000llu);
4714 s390_lgdr (code, s390_f13, s390_r13);
4715 s390_lzdr (code, s390_f15);
4716 s390_axbr (code, s390_f12, s390_f13);
4717 PTRSLOT(code, jump);
4718 s390_ldxbr (code, s390_f13, s390_f12);
4719 s390_ldr (code, ins->dreg, s390_f13);
4723 case OP_LCONV_TO_R4:
4724 case OP_ICONV_TO_R4: {
4725 s390_cegbr (code, ins->dreg, ins->sreg1);
4726 s390_ldebr (code, ins->dreg, ins->dreg);
4729 case OP_LCONV_TO_R8:
4730 case OP_ICONV_TO_R8: {
4731 s390_cdgbr (code, ins->dreg, ins->sreg1);
4734 case OP_FCONV_TO_I1:
4735 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4736 s390_ltgr (code, ins->dreg, ins->dreg);
4738 s390_oill (code, ins->dreg, 0x80);
4739 s390_lghi (code, s390_r0, 0xff);
4740 s390_ngr (code, ins->dreg, s390_r0);
4742 case OP_FCONV_TO_U1:
4743 if (mono_hwcap_s390x_has_fpe) {
4744 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4745 s390_lghi (code, s390_r0, 0xff);
4746 s390_ngr (code, ins->dreg, s390_r0);
4748 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4751 case OP_FCONV_TO_I2:
4752 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4753 s390_ltgr (code, ins->dreg, ins->dreg);
4755 s390_oill (code, ins->dreg, 0x8000);
4756 s390_llill (code, s390_r0, 0xffff);
4757 s390_ngr (code, ins->dreg, s390_r0);
4759 case OP_FCONV_TO_U2:
4760 if (mono_hwcap_s390x_has_fpe) {
4761 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4762 s390_llill (code, s390_r0, 0xffff);
4763 s390_ngr (code, ins->dreg, s390_r0);
4765 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4768 case OP_FCONV_TO_I4:
4770 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4772 case OP_FCONV_TO_U4:
4774 if (mono_hwcap_s390x_has_fpe) {
4775 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4777 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4780 case OP_FCONV_TO_I8:
4781 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4783 case OP_FCONV_TO_U8:
4784 if (mono_hwcap_s390x_has_fpe) {
4785 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4787 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4790 case OP_LCONV_TO_OVF_I: {
4791 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4793 s390_ltgr (code, ins->sreg2, ins->sreg2);
4794 s390_jnl (code, 0); CODEPTR(code, o[0]);
4795 s390_ltgr (code, ins->sreg1, ins->sreg1);
4796 s390_jnl (code, 0); CODEPTR(code, o[1]);
4797 s390_lhi (code, s390_r13, -1);
4798 s390_cgr (code, ins->sreg1, s390_r13);
4799 s390_jnz (code, 0); CODEPTR(code, o[2]);
4800 if (ins->dreg != ins->sreg2)
4801 s390_lgr (code, ins->dreg, ins->sreg2);
4802 s390_j (code, 0); CODEPTR(code, o[3]);
4803 PTRSLOT(code, o[0]);
4804 s390_jz (code, 0); CODEPTR(code, o[4]);
4805 PTRSLOT(code, o[1]);
4806 PTRSLOT(code, o[2]);
4807 mono_add_patch_info (cfg, code - cfg->native_code,
4808 MONO_PATCH_INFO_EXC, "OverflowException");
4809 s390_brasl (code, s390_r14, 0);
4810 PTRSLOT(code, o[3]);
4811 PTRSLOT(code, o[4]);
4815 s390_lpdbr (code, ins->dreg, ins->sreg1);
4819 s390_sqdbr (code, ins->dreg, ins->sreg1);
4824 s390_adbr (code, ins->dreg, src2);
4828 CHECK_SRCDST_NCOM_F;
4829 s390_sdbr (code, ins->dreg, src2);
4834 s390_mdbr (code, ins->dreg, src2);
4838 CHECK_SRCDST_NCOM_F;
4839 s390_ddbr (code, ins->dreg, src2);
4843 s390_lcdbr (code, ins->dreg, ins->sreg1);
4847 CHECK_SRCDST_NCOM_F;
4848 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4852 s390_cdbr (code, ins->sreg1, ins->sreg2);
4856 s390_cdbr (code, ins->sreg1, ins->sreg2);
4857 s390_lghi (code, ins->dreg, 1);
4859 s390_lghi (code, ins->dreg, 0);
4863 s390_cdbr (code, ins->sreg1, ins->sreg2);
4864 s390_lghi (code, ins->dreg, 1);
4866 s390_lghi (code, ins->dreg, 0);
4870 s390_cdbr (code, ins->sreg1, ins->sreg2);
4871 s390_lghi (code, ins->dreg, 1);
4873 s390_lghi (code, ins->dreg, 0);
4877 s390_cdbr (code, ins->sreg1, ins->sreg2);
4878 s390_lghi (code, ins->dreg, 1);
4880 s390_lghi (code, ins->dreg, 0);
4884 s390_cdbr (code, ins->sreg1, ins->sreg2);
4885 s390_lghi (code, ins->dreg, 1);
4887 s390_lghi (code, ins->dreg, 0);
4891 s390_cdbr (code, ins->sreg1, ins->sreg2);
4892 s390_lghi (code, ins->dreg, 1);
4894 s390_lghi (code, ins->dreg, 0);
4898 s390_cdbr (code, ins->sreg1, ins->sreg2);
4899 s390_lghi (code, ins->dreg, 1);
4901 s390_lghi (code, ins->dreg, 0);
4905 s390_cdbr (code, ins->sreg1, ins->sreg2);
4906 s390_lghi (code, ins->dreg, 1);
4908 s390_lghi (code, ins->dreg, 0);
4913 s390_jo (code, 0); CODEPTR(code, o);
4914 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4919 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4923 s390_jo (code, 0); CODEPTR(code, o);
4924 EMIT_COND_BRANCH (ins, S390_CC_LT);
4929 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4933 s390_jo (code, 0); CODEPTR(code, o);
4934 EMIT_COND_BRANCH (ins, S390_CC_GT);
4939 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4943 s390_jo (code, 0); CODEPTR(code, o);
4944 EMIT_COND_BRANCH (ins, S390_CC_GE);
4949 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4953 s390_jo (code, 0); CODEPTR(code, o);
4954 EMIT_COND_BRANCH (ins, S390_CC_LE);
4959 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4963 s390_lhi (code, s390_r13, 0x7f);
4964 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4965 s390_jz (code, 0); CODEPTR(code, o);
4966 mono_add_patch_info (cfg, code - cfg->native_code,
4967 MONO_PATCH_INFO_EXC, "OverflowException");
4968 s390_brasl (code, s390_r14,0);
4972 case OP_S390_MOVE: {
4973 if (ins->backend.size > 0) {
4974 if (ins->backend.size <= 256) {
4975 s390_mvc (code, ins->backend.size, ins->dreg,
4976 ins->inst_offset, ins->sreg1, ins->inst_imm);
4978 s390_lgr (code, s390_r0, ins->dreg);
4979 if (ins->inst_offset > 0) {
4980 if (s390_is_imm16 (ins->inst_offset)) {
4981 s390_aghi (code, s390_r0, ins->inst_offset);
4982 } else if (s390_is_imm32 (ins->inst_offset)) {
4983 s390_agfi (code, s390_r0, ins->inst_offset);
4985 S390_SET (code, s390_r13, ins->inst_offset);
4986 s390_agr (code, s390_r0, s390_r13);
4989 s390_lgr (code, s390_r12, ins->sreg1);
4990 if (ins->inst_imm > 0) {
4991 if (s390_is_imm16 (ins->inst_imm)) {
4992 s390_aghi (code, s390_r12, ins->inst_imm);
4993 } else if (s390_is_imm32 (ins->inst_imm)) {
4994 s390_agfi (code, s390_r12, ins->inst_imm);
4996 S390_SET (code, s390_r13, ins->inst_imm);
4997 s390_agr (code, s390_r12, s390_r13);
5000 if (s390_is_imm16 (ins->backend.size)) {
5001 s390_lghi (code, s390_r1, ins->backend.size);
5002 } else if (s390_is_imm32 (ins->inst_offset)) {
5003 s390_agfi (code, s390_r1, ins->backend.size);
5005 S390_SET (code, s390_r13, ins->backend.size);
5006 s390_agr (code, s390_r1, s390_r13);
5008 s390_lgr (code, s390_r13, s390_r1);
5009 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
5015 case OP_ATOMIC_ADD_I8: {
5016 if (mono_hwcap_s390x_has_ia) {
5017 s390_laag (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5018 s390_agr (code, ins->dreg, ins->sreg2);
5020 s390_lgr (code, s390_r1, ins->sreg2);
5021 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5022 s390_agr (code, s390_r1, s390_r0);
5023 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5024 s390_jnz (code, -10);
5025 s390_lgr (code, ins->dreg, s390_r1);
5029 case OP_ATOMIC_EXCHANGE_I8: {
5030 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5031 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5032 s390_jnz (code, -6);
5033 s390_lgr (code, ins->dreg, s390_r0);
5036 case OP_ATOMIC_ADD_I4: {
5037 if (mono_hwcap_s390x_has_ia) {
5038 s390_laa (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5039 s390_ar (code, ins->dreg, ins->sreg2);
5041 s390_lgfr(code, s390_r1, ins->sreg2);
5042 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5043 s390_agr (code, s390_r1, s390_r0);
5044 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5045 s390_jnz (code, -9);
5046 s390_lgfr(code, ins->dreg, s390_r1);
5050 case OP_ATOMIC_EXCHANGE_I4: {
5051 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5052 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5053 s390_jnz (code, -4);
5054 s390_lgfr(code, ins->dreg, s390_r0);
5057 case OP_S390_BKCHAIN: {
5058 s390_lgr (code, ins->dreg, ins->sreg1);
5059 if (s390_is_imm16 (cfg->stack_offset)) {
5060 s390_aghi (code, ins->dreg, cfg->stack_offset);
5061 } else if (s390_is_imm32 (cfg->stack_offset)) {
5062 s390_agfi (code, ins->dreg, cfg->stack_offset);
5064 S390_SET (code, s390_r13, cfg->stack_offset);
5065 s390_agr (code, ins->dreg, s390_r13);
5069 case OP_MEMORY_BARRIER:
5072 case OP_GC_SAFE_POINT: {
5075 g_assert (mono_threads_is_coop_enabled ());
5077 s390_ltg (code, s390_r0, 0, ins->sreg1, 0);
5078 s390_jz (code, 0); CODEPTR(code, br);
5079 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
5080 mono_threads_state_poll);
5081 S390_CALL_TEMPLATE (code, s390_r14);
5085 case OP_GC_LIVENESS_DEF:
5086 case OP_GC_LIVENESS_USE:
5087 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
5088 ins->backend.pc_offset = code - cfg->native_code;
5090 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
5091 ins->backend.pc_offset = code - cfg->native_code;
5092 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
5094 #ifdef MONO_ARCH_SIMD_INTRINSICS
5096 s390x_addps (code, ins->sreg1, ins->sreg2);
5099 s390x_divps (code, ins->sreg1, ins->sreg2);
5102 s390x_mulps (code, ins->sreg1, ins->sreg2);
5105 s390x_subps (code, ins->sreg1, ins->sreg2);
5108 s390x_maxps (code, ins->sreg1, ins->sreg2);
5111 s390x_minps (code, ins->sreg1, ins->sreg2);
5114 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5115 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5118 s390x_andps (code, ins->sreg1, ins->sreg2);
5121 s390x_andnps (code, ins->sreg1, ins->sreg2);
5124 s390x_orps (code, ins->sreg1, ins->sreg2);
5127 s390x_xorps (code, ins->sreg1, ins->sreg2);
5130 s390x_sqrtps (code, ins->dreg, ins->sreg1);
5133 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
5136 s390x_rcpps (code, ins->dreg, ins->sreg1);
5139 s390x_addsubps (code, ins->sreg1, ins->sreg2);
5142 s390x_haddps (code, ins->sreg1, ins->sreg2);
5145 s390x_hsubps (code, ins->sreg1, ins->sreg2);
5148 s390x_movshdup (code, ins->dreg, ins->sreg1);
5151 s390x_movsldup (code, ins->dreg, ins->sreg1);
5154 case OP_PSHUFLEW_HIGH:
5155 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5156 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5158 case OP_PSHUFLEW_LOW:
5159 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5160 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5163 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5164 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5167 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5168 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5171 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
5172 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5176 s390x_addpd (code, ins->sreg1, ins->sreg2);
5179 s390x_divpd (code, ins->sreg1, ins->sreg2);
5182 s390x_mulpd (code, ins->sreg1, ins->sreg2);
5185 s390x_subpd (code, ins->sreg1, ins->sreg2);
5188 s390x_maxpd (code, ins->sreg1, ins->sreg2);
5191 s390x_minpd (code, ins->sreg1, ins->sreg2);
5194 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5195 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5198 s390x_andpd (code, ins->sreg1, ins->sreg2);
5201 s390x_andnpd (code, ins->sreg1, ins->sreg2);
5204 s390x_orpd (code, ins->sreg1, ins->sreg2);
5207 s390x_xorpd (code, ins->sreg1, ins->sreg2);
5210 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
5213 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
5216 s390x_haddpd (code, ins->sreg1, ins->sreg2);
5219 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
5222 s390x_movddup (code, ins->dreg, ins->sreg1);
5225 case OP_EXTRACT_MASK:
5226 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
5230 s390x_pand (code, ins->sreg1, ins->sreg2);
5233 s390x_por (code, ins->sreg1, ins->sreg2);
5236 s390x_pxor (code, ins->sreg1, ins->sreg2);
5240 s390x_paddb (code, ins->sreg1, ins->sreg2);
5243 s390x_paddw (code, ins->sreg1, ins->sreg2);
5246 s390x_paddd (code, ins->sreg1, ins->sreg2);
5249 s390x_paddq (code, ins->sreg1, ins->sreg2);
5253 s390x_psubb (code, ins->sreg1, ins->sreg2);
5256 s390x_psubw (code, ins->sreg1, ins->sreg2);
5259 s390x_psubd (code, ins->sreg1, ins->sreg2);
5262 s390x_psubq (code, ins->sreg1, ins->sreg2);
5266 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
5269 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
5272 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
5276 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
5279 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
5282 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
5286 s390x_pavgb (code, ins->sreg1, ins->sreg2);
5289 s390x_pavgw (code, ins->sreg1, ins->sreg2);
5293 s390x_pminub (code, ins->sreg1, ins->sreg2);
5296 s390x_pminuw (code, ins->sreg1, ins->sreg2);
5299 s390x_pminud (code, ins->sreg1, ins->sreg2);
5303 s390x_pminsb (code, ins->sreg1, ins->sreg2);
5306 s390x_pminsw (code, ins->sreg1, ins->sreg2);
5309 s390x_pminsd (code, ins->sreg1, ins->sreg2);
5313 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
5316 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
5319 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
5322 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
5326 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
5329 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5332 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5335 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5338 case OP_PSUM_ABS_DIFF:
5339 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5342 case OP_UNPACK_LOWB:
5343 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5345 case OP_UNPACK_LOWW:
5346 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5348 case OP_UNPACK_LOWD:
5349 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5351 case OP_UNPACK_LOWQ:
5352 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5354 case OP_UNPACK_LOWPS:
5355 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5357 case OP_UNPACK_LOWPD:
5358 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5361 case OP_UNPACK_HIGHB:
5362 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5364 case OP_UNPACK_HIGHW:
5365 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5367 case OP_UNPACK_HIGHD:
5368 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5370 case OP_UNPACK_HIGHQ:
5371 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5373 case OP_UNPACK_HIGHPS:
5374 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5376 case OP_UNPACK_HIGHPD:
5377 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5381 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5384 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5387 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5390 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5393 case OP_PADDB_SAT_UN:
5394 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5396 case OP_PSUBB_SAT_UN:
5397 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5399 case OP_PADDW_SAT_UN:
5400 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5402 case OP_PSUBW_SAT_UN:
5403 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5407 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5410 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5413 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5416 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5420 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5423 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5426 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5428 case OP_PMULW_HIGH_UN:
5429 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5432 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5436 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5439 s390x_psrlw (code, ins->dreg, ins->sreg2);
5443 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5446 s390x_psraw (code, ins->dreg, ins->sreg2);
5450 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5453 s390x_psllw (code, ins->dreg, ins->sreg2);
5457 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5460 s390x_psrld (code, ins->dreg, ins->sreg2);
5464 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5467 s390x_psrad (code, ins->dreg, ins->sreg2);
5471 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5474 s390x_pslld (code, ins->dreg, ins->sreg2);
5478 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5481 s390x_psrlq (code, ins->dreg, ins->sreg2);
5484 /*TODO: This is appart of the sse spec but not added
5486 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5489 s390x_psraq (code, ins->dreg, ins->sreg2);
5494 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5497 s390x_psllq (code, ins->dreg, ins->sreg2);
5500 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5503 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5506 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5509 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5512 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5515 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5518 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5521 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5525 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5528 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5532 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5533 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5535 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5540 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5542 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5543 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5547 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5549 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5550 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5551 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5555 amd64_movhlps (code, ins->dreg, ins->sreg1);
5557 s390x_movsd (code, ins->dreg, ins->sreg1);
5560 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5562 case OP_EXTRACTX_U2:
5563 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5565 case OP_INSERTX_U1_SLOW:
5566 /*sreg1 is the extracted ireg (scratch)
5567 /sreg2 is the to be inserted ireg (scratch)
5568 /dreg is the xreg to receive the value*/
5570 /*clear the bits from the extracted word*/
5571 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5572 /*shift the value to insert if needed*/
5573 if (ins->inst_c0 & 1)
5574 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5575 /*join them together*/
5576 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5577 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5579 case OP_INSERTX_I4_SLOW:
5580 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5581 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5582 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5584 case OP_INSERTX_I8_SLOW:
5585 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5587 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5589 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5592 case OP_INSERTX_R4_SLOW:
5593 switch (ins->inst_c0) {
5596 s390x_movss (code, ins->dreg, ins->sreg2);
5598 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5601 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5603 s390x_movss (code, ins->dreg, ins->sreg2);
5605 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5606 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5609 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5611 s390x_movss (code, ins->dreg, ins->sreg2);
5613 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5614 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5617 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5619 s390x_movss (code, ins->dreg, ins->sreg2);
5621 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5622 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5626 case OP_INSERTX_R8_SLOW:
5628 amd64_movlhps (code, ins->dreg, ins->sreg2);
5630 s390x_movsd (code, ins->dreg, ins->sreg2);
5632 case OP_STOREX_MEMBASE_REG:
5633 case OP_STOREX_MEMBASE:
5634 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5636 case OP_LOADX_MEMBASE:
5637 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5639 case OP_LOADX_ALIGNED_MEMBASE:
5640 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5642 case OP_STOREX_ALIGNED_MEMBASE_REG:
5643 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5645 case OP_STOREX_NTA_MEMBASE_REG:
5646 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5648 case OP_PREFETCH_MEMBASE:
5649 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5653 /*FIXME the peephole pass should have killed this*/
5654 if (ins->dreg != ins->sreg1)
5655 s390x_movaps (code, ins->dreg, ins->sreg1);
5658 s390x_pxor (code, ins->dreg, ins->dreg);
5660 case OP_ICONV_TO_R4_RAW:
5661 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5664 case OP_FCONV_TO_R8_X:
5665 s390x_movsd (code, ins->dreg, ins->sreg1);
5668 case OP_XCONV_R8_TO_I4:
5669 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5670 switch (ins->backend.source_opcode) {
5671 case OP_FCONV_TO_I1:
5672 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5674 case OP_FCONV_TO_U1:
5675 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5677 case OP_FCONV_TO_I2:
5678 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5680 case OP_FCONV_TO_U2:
5681 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5687 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5688 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5689 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5692 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5693 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5696 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5697 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5701 s390x_movsd (code, ins->dreg, ins->sreg1);
5703 s390x_movsd (code, ins->dreg, ins->sreg1);
5704 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5706 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5709 s390x_movsd (code, ins->dreg, ins->sreg1);
5710 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5714 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5715 g_assert_not_reached ();
5718 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5719 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5720 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5721 g_assert_not_reached ();
5724 last_offset = offset;
5727 cfg->code_len = code - cfg->native_code;
5730 /*========================= End of Function ========================*/
5732 /*------------------------------------------------------------------*/
5734 /* Name - mono_arch_register_lowlevel_calls */
5736 /* Function - Register routines to help with --trace operation. */
5738 /*------------------------------------------------------------------*/
5741 mono_arch_register_lowlevel_calls (void)
5745 /*========================= End of Function ========================*/
5747 /*------------------------------------------------------------------*/
5749 /* Name - mono_arch_patch_code */
5751 /* Function - Process the patch data created during the */
5752 /* instruction build process. This resolves jumps, */
5753 /* calls, variables etc. */
5755 /*------------------------------------------------------------------*/
5758 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5759 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5762 MonoJumpInfo *patch_info;
5766 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5767 unsigned char *ip = patch_info->ip.i + code;
5768 gconstpointer target = NULL;
5770 target = mono_resolve_patch_target (method, domain, code,
5771 patch_info, run_cctors, error);
5772 return_if_nok (error);
5774 switch (patch_info->type) {
5775 case MONO_PATCH_INFO_IP:
5776 case MONO_PATCH_INFO_LDSTR:
5777 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5778 case MONO_PATCH_INFO_LDTOKEN:
5779 case MONO_PATCH_INFO_EXC:
5780 s390_patch_addr (ip, (guint64) target);
5782 case MONO_PATCH_INFO_METHOD:
5783 case MONO_PATCH_INFO_INTERNAL_METHOD:
5784 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5785 case MONO_PATCH_INFO_RGCTX_FETCH:
5786 case MONO_PATCH_INFO_ABS: {
5787 S390_EMIT_CALL (ip, target);
5790 case MONO_PATCH_INFO_SWITCH:
5791 /*----------------------------------*/
5792 /* ip points at the basr r13,0/j +4 */
5793 /* instruction the vtable value */
5794 /* follows this (i.e. ip+6) */
5795 /*----------------------------------*/
5796 S390_EMIT_LOAD (ip, target);
5798 case MONO_PATCH_INFO_METHODCONST:
5799 case MONO_PATCH_INFO_CLASS:
5800 case MONO_PATCH_INFO_IMAGE:
5801 case MONO_PATCH_INFO_FIELD:
5802 case MONO_PATCH_INFO_IID:
5803 case MONO_PATCH_INFO_EXC_NAME:
5804 target = S390_RELATIVE(target, ip);
5805 s390_patch_rel (ip, (guint64) target);
5807 case MONO_PATCH_INFO_R4:
5808 case MONO_PATCH_INFO_R8:
5809 case MONO_PATCH_INFO_METHOD_REL:
5810 g_assert_not_reached ();
5813 target = S390_RELATIVE(target, ip);
5815 s390_patch_rel (ip, (guint64) target);
5820 /*========================= End of Function ========================*/
5822 /*------------------------------------------------------------------*/
5824 /* Name - emit_load_volatile_arguments */
5826 /* Function - Emit the instructions to reload parameter regist- */
5827 /* registers for use with "tail" operations. */
5829 /* The register loading operations performed here */
5830 /* are the mirror of the store operations performed */
5831 /* in mono_arch_emit_prolog and need to be kept in */
5832 /* synchronization with it. */
5834 /*------------------------------------------------------------------*/
5837 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5840 MonoMethod *method = cfg->method;
5841 MonoMethodSignature *sig = mono_method_signature(method);
5845 cinfo = get_call_info (NULL, NULL, sig);
5847 if (cinfo->struct_ret) {
5848 ArgInfo *ainfo = &cinfo->ret;
5849 inst = cfg->vret_addr;
5850 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5853 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5854 ArgInfo *ainfo = cinfo->args + i;
5855 inst = cfg->args [pos];
5857 if (inst->opcode == OP_REGVAR) {
5858 if (ainfo->regtype == RegTypeGeneral)
5859 s390_lgr (code, ainfo->reg, inst->dreg);
5860 else if (ainfo->regtype == RegTypeFP) {
5861 if (inst->dreg != ainfo->reg) {
5862 if (ainfo->size == 4) {
5863 s390_ldebr (code, ainfo->reg, inst->dreg);
5865 s390_ldr (code, ainfo->reg, inst->dreg);
5869 else if (ainfo->regtype == RegTypeBase) {
5871 g_assert_not_reached ();
5873 if (ainfo->regtype == RegTypeGeneral) {
5874 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5875 g_assert_not_reached();
5876 switch (ainfo->size) {
5878 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5881 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5884 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5887 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5890 } else if (ainfo->regtype == RegTypeBase) {
5891 } else if (ainfo->regtype == RegTypeFP) {
5892 if (ainfo->size == 8)
5893 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5894 else if (ainfo->size == 4)
5895 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5897 g_assert_not_reached ();
5898 } else if (ainfo->regtype == RegTypeStructByVal) {
5899 if (ainfo->reg != STK_BASE) {
5900 switch (ainfo->size) {
5902 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5905 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5908 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5911 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5915 } else if (ainfo->regtype == RegTypeStructByAddr) {
5916 if (ainfo->reg != STK_BASE) {
5917 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5920 g_assert_not_reached ();
5928 /*========================= End of Function ========================*/
5930 /*------------------------------------------------------------------*/
5932 /* Name - mono_arch_emit_prolog */
5934 /* Function - Create the instruction sequence for a function */
5937 /*------------------------------------------------------------------*/
5940 mono_arch_emit_prolog (MonoCompile *cfg)
5942 MonoMethod *method = cfg->method;
5944 MonoMethodSignature *sig;
5946 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5955 cfg->code_size = 512;
5957 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5959 cfg->code_size += 256;
5962 if (method->save_lmf)
5963 cfg->code_size += 200;
5965 cfg->native_code = code = g_malloc (cfg->code_size);
5967 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5968 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5969 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5970 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5971 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5973 if (cfg->arch.bkchain_reg != -1)
5974 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5976 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5977 cfg->used_int_regs |= 1 << 11;
5980 alloc_size = cfg->stack_offset;
5982 cfg->stack_usage = cfa_offset = alloc_size;
5983 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5984 s390_lgr (code, s390_r11, STK_BASE);
5985 if (s390_is_imm16 (alloc_size)) {
5986 s390_aghi (code, STK_BASE, -alloc_size);
5987 } else if (s390_is_imm32 (alloc_size)) {
5988 s390_agfi (code, STK_BASE, -alloc_size);
5990 int stackSize = alloc_size;
5991 while (stackSize > INT_MAX) {
5992 s390_agfi (code, STK_BASE, -INT_MAX);
5993 stackSize -= INT_MAX;
5995 s390_agfi (code, STK_BASE, -stackSize);
5997 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5999 if (cfg->frame_reg != STK_BASE)
6000 s390_lgr (code, s390_r11, STK_BASE);
6002 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
6004 /* store runtime generic context */
6005 if (cfg->rgctx_var) {
6006 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
6008 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
6009 cfg->rgctx_var->inst_basereg,
6010 cfg->rgctx_var->inst_offset);
6013 /* compute max_offset in order to use short forward jumps
6014 * we always do it on s390 because the immediate displacement
6015 * for jumps is too small
6018 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6020 bb->max_offset = max_offset;
6022 MONO_BB_FOR_EACH_INS (bb, ins)
6023 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
6026 /* load arguments allocated to register from the stack */
6027 sig = mono_method_signature (method);
6030 cinfo = get_call_info (cfg, cfg->mempool, sig);
6032 if (cinfo->struct_ret) {
6033 ArgInfo *ainfo = &cinfo->ret;
6034 inst = cfg->vret_addr;
6035 inst->backend.size = ainfo->vtsize;
6036 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6039 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6040 ArgInfo *ainfo = cinfo->args + i;
6041 inst = cfg->args [pos];
6043 if (inst->opcode == OP_VTARG_ADDR)
6044 inst = inst->inst_left;
6046 if (inst->opcode == OP_REGVAR) {
6047 if (ainfo->regtype == RegTypeGeneral)
6048 s390_lgr (code, inst->dreg, ainfo->reg);
6049 else if (ainfo->regtype == RegTypeFP) {
6050 if (inst->dreg != ainfo->reg) {
6051 if (ainfo->size == 4) {
6052 s390_ledbr (code, inst->dreg, ainfo->reg);
6054 s390_ldr (code, inst->dreg, ainfo->reg);
6058 else if (ainfo->regtype == RegTypeBase) {
6059 s390_lgr (code, s390_r13, STK_BASE);
6060 s390_aghi (code, s390_r13, alloc_size);
6061 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
6063 g_assert_not_reached ();
6065 if (cfg->verbose_level > 2)
6066 g_print ("Argument %d assigned to register %s\n",
6067 pos, mono_arch_regname (inst->dreg));
6069 if (ainfo->regtype == RegTypeGeneral) {
6070 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
6071 g_assert_not_reached();
6072 switch (ainfo->size) {
6074 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6077 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6080 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6083 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6086 } else if (ainfo->regtype == RegTypeBase) {
6087 } else if (ainfo->regtype == RegTypeFP) {
6088 if (ainfo->size == 8)
6089 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6090 else if (ainfo->size == 4)
6091 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6093 g_assert_not_reached ();
6094 } else if (ainfo->regtype == RegTypeStructByVal) {
6095 int doffset = inst->inst_offset;
6097 if (ainfo->reg != STK_BASE)
6101 s390_lgr (code, s390_r13, STK_BASE);
6102 s390_aghi (code, s390_r13, alloc_size);
6105 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
6106 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
6111 if (ainfo->reg == STK_BASE)
6112 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
6113 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
6116 if (ainfo->reg == STK_BASE)
6117 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
6118 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
6121 if (ainfo->reg == STK_BASE)
6122 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
6123 s390_st (code, reg, 0, inst->inst_basereg, doffset);
6126 if (ainfo->reg == STK_BASE)
6127 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
6128 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
6131 } else if (ainfo->regtype == RegTypeStructByAddr) {
6132 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6133 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
6135 g_assert_not_reached ();
6140 if (method->save_lmf) {
6141 /*---------------------------------------------------------------*/
6142 /* build the MonoLMF structure on the stack - see mini-s390x.h */
6143 /*---------------------------------------------------------------*/
6144 lmfOffset = alloc_size - sizeof(MonoLMF);
6146 s390_lgr (code, s390_r13, cfg->frame_reg);
6147 s390_aghi (code, s390_r13, lmfOffset);
6149 /*---------------------------------------------------------------*/
6150 /* Preserve the parameter registers while we fix up the lmf */
6151 /*---------------------------------------------------------------*/
6152 s390_stmg (code, s390_r2, s390_r6, s390_r13,
6153 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6155 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
6156 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
6157 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
6158 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
6159 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
6161 /*---------------------------------------------------------------*/
6162 /* On return from this call r2 have the address of the &lmf */
6163 /*---------------------------------------------------------------*/
6164 mono_add_patch_info (cfg, code - cfg->native_code,
6165 MONO_PATCH_INFO_INTERNAL_METHOD,
6166 (gpointer)"mono_tls_get_lmf_addr");
6167 S390_CALL_TEMPLATE(code, s390_r1);
6169 /*---------------------------------------------------------------*/
6170 /* Set lmf.lmf_addr = jit_tls->lmf */
6171 /*---------------------------------------------------------------*/
6172 s390_stg (code, s390_r2, 0, s390_r13,
6173 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
6174 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
6176 /*---------------------------------------------------------------*/
6177 /* Get current lmf */
6178 /*---------------------------------------------------------------*/
6179 s390_lg (code, s390_r0, 0, s390_r2, 0);
6181 /*---------------------------------------------------------------*/
6182 /* Set our lmf as the current lmf */
6183 /*---------------------------------------------------------------*/
6184 s390_stg (code, s390_r13, 0, s390_r2, 0);
6186 /*---------------------------------------------------------------*/
6187 /* Have our lmf.previous_lmf point to the last lmf */
6188 /*---------------------------------------------------------------*/
6189 s390_stg (code, s390_r0, 0, s390_r13,
6190 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
6191 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
6193 /*---------------------------------------------------------------*/
6194 /* save method info */
6195 /*---------------------------------------------------------------*/
6196 S390_SET (code, s390_r1, method);
6197 s390_stg (code, s390_r1, 0, s390_r13,
6198 G_STRUCT_OFFSET(MonoLMF, method));
6199 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
6201 /*---------------------------------------------------------------*/
6202 /* save the current IP */
6203 /*---------------------------------------------------------------*/
6204 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
6205 s390_basr (code, s390_r1, 0);
6206 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
6207 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
6208 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
6210 /*---------------------------------------------------------------*/
6211 /* Save general and floating point registers */
6212 /*---------------------------------------------------------------*/
6213 s390_stmg (code, s390_r2, s390_r12, s390_r13,
6214 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
6215 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
6216 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
6217 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
6218 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
6219 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
6220 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
6221 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
6222 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
6223 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
6224 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
6225 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
6227 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
6228 for (i = 0; i < 16; i++) {
6229 s390_std (code, i, 0, s390_r13,
6230 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
6231 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
6232 fpOffset += sizeof(double);
6235 /*---------------------------------------------------------------*/
6236 /* Restore the parameter registers now that we've set up the lmf */
6237 /*---------------------------------------------------------------*/
6238 s390_lmg (code, s390_r2, s390_r6, s390_r13,
6239 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6242 if (cfg->method->save_lmf)
6243 argsClobbered = TRUE;
6246 argsClobbered = TRUE;
6247 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
6251 * Optimize the common case of the first bblock making a call with the same
6252 * arguments as the method. This works because the arguments are still in their
6253 * original argument registers.
6255 if (!argsClobbered) {
6256 MonoBasicBlock *first_bb = cfg->bb_entry;
6258 int filter = FILTER_IL_SEQ_POINT;
6260 next = mono_bb_first_inst (first_bb, filter);
6261 if (!next && first_bb->next_bb) {
6262 first_bb = first_bb->next_bb;
6263 next = mono_bb_first_inst (first_bb, filter);
6266 if (first_bb->in_count > 1)
6269 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
6270 ArgInfo *ainfo = cinfo->args + i;
6271 gboolean match = FALSE;
6273 inst = cfg->args [i];
6274 if (inst->opcode != OP_REGVAR) {
6275 switch (ainfo->regtype) {
6276 case RegTypeGeneral: {
6277 if (((next->opcode == OP_LOAD_MEMBASE) ||
6278 (next->opcode == OP_LOADI4_MEMBASE)) &&
6279 next->inst_basereg == inst->inst_basereg &&
6280 next->inst_offset == inst->inst_offset) {
6281 if (next->dreg == ainfo->reg) {
6285 next->opcode = OP_MOVE;
6286 next->sreg1 = ainfo->reg;
6287 /* Only continue if the instruction doesn't change argument regs */
6288 if (next->dreg == ainfo->reg)
6298 /* Argument allocated to (non-volatile) register */
6299 switch (ainfo->regtype) {
6300 case RegTypeGeneral:
6301 if (next->opcode == OP_MOVE &&
6302 next->sreg1 == inst->dreg &&
6303 next->dreg == ainfo->reg) {
6314 next = mono_inst_next (next, filter);
6321 cfg->code_len = code - cfg->native_code;
6322 g_assert (cfg->code_len < cfg->code_size);
6327 /*========================= End of Function ========================*/
6329 /*------------------------------------------------------------------*/
6331 /* Name - mono_arch_emit_epilog */
6333 /* Function - Emit the instructions for a function epilog. */
6335 /*------------------------------------------------------------------*/
6338 mono_arch_emit_epilog (MonoCompile *cfg)
6340 MonoMethod *method = cfg->method;
6343 int max_epilog_size = 96;
6345 if (cfg->method->save_lmf)
6346 max_epilog_size += 128;
6348 if (mono_jit_trace_calls != NULL)
6349 max_epilog_size += 128;
6351 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6352 cfg->code_size *= 2;
6353 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6354 cfg->stat_code_reallocs++;
6357 code = cfg->native_code + cfg->code_len;
6359 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6360 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6364 if (method->save_lmf)
6365 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6367 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6368 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6370 code = backUpStackPtr(cfg, code);
6372 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6373 s390_br (code, s390_r14);
6375 cfg->code_len = code - cfg->native_code;
6377 g_assert (cfg->code_len < cfg->code_size);
6381 /*========================= End of Function ========================*/
6383 /*------------------------------------------------------------------*/
6385 /* Name - mono_arch_emit_exceptions */
6387 /* Function - Emit the blocks to handle exception conditions. */
6389 /*------------------------------------------------------------------*/
6392 mono_arch_emit_exceptions (MonoCompile *cfg)
6394 MonoJumpInfo *patch_info;
6400 MonoClass *exc_classes [MAX_EXC];
6401 guint8 *exc_throw_start [MAX_EXC];
6403 for (patch_info = cfg->patch_info;
6405 patch_info = patch_info->next) {
6406 if (patch_info->type == MONO_PATCH_INFO_EXC)
6410 code_size = exc_count * 48;
6412 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6413 cfg->code_size *= 2;
6414 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6415 cfg->stat_code_reallocs++;
6418 code = cfg->native_code + cfg->code_len;
6420 /*---------------------------------------------------------------------*/
6421 /* Add code to raise exceptions */
6422 /*---------------------------------------------------------------------*/
6423 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6424 switch (patch_info->type) {
6425 case MONO_PATCH_INFO_EXC: {
6426 guint8 *ip = patch_info->ip.i + cfg->native_code;
6427 MonoClass *exc_class;
6430 /*-----------------------------------------------------*/
6431 /* Patch the branch in epilog to come here */
6432 /*-----------------------------------------------------*/
6433 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6435 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6437 patch_info->data.name);
6438 throw_ip = patch_info->ip.i;
6440 for (iExc = 0; iExc < nThrows; ++iExc)
6441 if (exc_classes [iExc] == exc_class)
6444 if (iExc < nThrows) {
6445 s390_jcl (code, S390_CC_UN,
6446 (guint64) exc_throw_start [iExc]);
6447 patch_info->type = MONO_PATCH_INFO_NONE;
6450 if (nThrows < MAX_EXC) {
6451 exc_classes [nThrows] = exc_class;
6452 exc_throw_start [nThrows] = code;
6455 /*---------------------------------------------*/
6456 /* Patch the parameter passed to the handler */
6457 /*---------------------------------------------*/
6458 S390_SET (code, s390_r2, exc_class->type_token);
6459 /*---------------------------------------------*/
6460 /* Load return address & parameter register */
6461 /*---------------------------------------------*/
6462 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6463 cfg->native_code + 8), code));
6464 /*---------------------------------------------*/
6465 /* Reuse the current patch to set the jump */
6466 /*---------------------------------------------*/
6467 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6468 patch_info->data.name = "mono_arch_throw_corlib_exception";
6469 patch_info->ip.i = code - cfg->native_code;
6470 S390_BR_TEMPLATE (code, s390_r1);
6480 cfg->code_len = code - cfg->native_code;
6482 g_assert (cfg->code_len < cfg->code_size);
6486 /*========================= End of Function ========================*/
6488 /*------------------------------------------------------------------*/
6490 /* Name - mono_arch_finish_init */
6492 /* Function - Setup the JIT's Thread Level Specific Data. */
6494 /*------------------------------------------------------------------*/
6497 mono_arch_finish_init (void)
6501 /*========================= End of Function ========================*/
6503 /*------------------------------------------------------------------*/
6505 /* Name - mono_arch_free_jit_tls_data */
6507 /* Function - Free tls data. */
6509 /*------------------------------------------------------------------*/
6512 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6516 /*========================= End of Function ========================*/
6518 /*------------------------------------------------------------------*/
6520 /* Name - mono_arch_emit_inst_for_method */
6522 /*------------------------------------------------------------------*/
6525 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6530 /*========================= End of Function ========================*/
6532 /*------------------------------------------------------------------*/
6534 /* Name - mono_arch_decompose_opts */
6536 /* Function - Decompose opcode into a System z opcode. */
6538 /*------------------------------------------------------------------*/
6541 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6544 * Have to rename these to avoid being decomposed normally, since the normal
6545 * decomposition does not work on S390.
6547 switch (ins->opcode) {
6549 ins->opcode = OP_S390_ISUB_OVF;
6551 case OP_ISUB_OVF_UN:
6552 ins->opcode = OP_S390_ISUB_OVF_UN;
6555 ins->opcode = OP_S390_IADD_OVF;
6557 case OP_IADD_OVF_UN:
6558 ins->opcode = OP_S390_IADD_OVF_UN;
6561 ins->opcode = OP_S390_LADD_OVF;
6563 case OP_LADD_OVF_UN:
6564 ins->opcode = OP_S390_LADD_OVF_UN;
6567 ins->opcode = OP_S390_LSUB_OVF;
6569 case OP_LSUB_OVF_UN:
6570 ins->opcode = OP_S390_LSUB_OVF_UN;
6577 /*========================= End of Function ========================*/
6579 /*------------------------------------------------------------------*/
6581 /* Name - mono_arch_regalloc_cost */
6583 /* Function - Determine the cost, in the number of memory */
6584 /* references, of the action of allocating the var- */
6585 /* iable VMV into a register during global register */
6588 /* Returns - Cost */
6590 /*------------------------------------------------------------------*/
6593 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6599 /*========================= End of Function ========================*/
6601 /*------------------------------------------------------------------*/
6603 /* Name - mono_arch_flush_register_windows */
6609 /*------------------------------------------------------------------*/
6612 mono_arch_flush_register_windows (void)
6616 /*========================= End of Function ========================*/
6618 /*------------------------------------------------------------------*/
6620 /* Name - mono_arch_is_inst_imm */
6622 /* Function - Determine if operand qualifies as an immediate */
6623 /* value. For s390 this is a value -32768-32768 */
6625 /* Returns - True|False - is [not] immediate value. */
6627 /*------------------------------------------------------------------*/
6630 mono_arch_is_inst_imm (gint64 imm)
6632 return s390_is_imm32 (imm);
6635 /*========================= End of Function ========================*/
6637 /*------------------------------------------------------------------*/
6639 /* Name - mono_arch_get_patch_offset */
6641 /* Function - Dummy entry point until s390x supports aot. */
6643 /* Returns - Offset for patch. */
6645 /*------------------------------------------------------------------*/
6648 mono_arch_get_patch_offset (guint8 *code)
6653 /*========================= End of Function ========================*/
6655 /*------------------------------------------------------------------*/
6657 /* Name - mono_arch_context_get_int_reg. */
6661 /* Returns - Return a register from the context. */
6663 /*------------------------------------------------------------------*/
6666 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6668 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6671 /*========================= End of Function ========================*/
6673 /*------------------------------------------------------------------*/
6675 /* Name - mono_arch_context_set_int_reg. */
6677 /* Function - Set a value in a specified register. */
6679 /*------------------------------------------------------------------*/
6682 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6684 ctx->uc_mcontext.gregs[reg] = val;
6687 /*========================= End of Function ========================*/
6689 /*------------------------------------------------------------------*/
6691 /* Name - mono_arch_get_this_arg_from_call. */
6695 /*------------------------------------------------------------------*/
6698 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6700 return (gpointer) regs [s390_r2];
6703 /*========================= End of Function ========================*/
6705 /*------------------------------------------------------------------*/
6707 /* Name - get_delegate_invoke_impl. */
6711 /*------------------------------------------------------------------*/
6714 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6716 guint8 *code, *start;
6721 start = code = mono_global_codeman_reserve (size);
6723 /* Replace the this argument with the target */
6724 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6725 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6726 s390_br (code, s390_r1);
6727 g_assert ((code - start) <= size);
6729 mono_arch_flush_icache (start, size);
6733 size = 32 + param_count * 8;
6734 start = code = mono_global_codeman_reserve (size);
6736 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6737 /* slide down the arguments */
6738 for (i = 0; i < param_count; ++i) {
6739 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6741 s390_br (code, s390_r1);
6743 g_assert ((code - start) <= size);
6745 mono_arch_flush_icache (start, size);
6749 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6751 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6752 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6759 /*========================= End of Function ========================*/
6761 /*------------------------------------------------------------------*/
6763 /* Name - mono_arch_get_delegate_invoke_impls. */
6767 /*------------------------------------------------------------------*/
6770 mono_arch_get_delegate_invoke_impls (void)
6773 MonoTrampInfo *info;
6776 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6777 res = g_slist_prepend (res, info);
6779 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6780 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6781 res = g_slist_prepend (res, info);
6787 /*========================= End of Function ========================*/
6789 /*------------------------------------------------------------------*/
6791 /* Name - mono_arch_get_delegate_invoke_impl. */
6795 /*------------------------------------------------------------------*/
6798 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6800 guint8 *code, *start;
6802 /* FIXME: Support more cases */
6803 if (MONO_TYPE_ISSTRUCT (sig->ret))
6807 static guint8* cached = NULL;
6812 if (mono_aot_only) {
6813 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6815 MonoTrampInfo *info;
6816 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6817 mono_tramp_info_register (info, NULL);
6820 mono_memory_barrier ();
6824 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6827 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6829 for (i = 0; i < sig->param_count; ++i)
6830 if (!mono_is_regsize_var (sig->params [i]))
6834 code = cache [sig->param_count];
6838 if (mono_aot_only) {
6839 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6840 start = mono_aot_get_trampoline (name);
6843 MonoTrampInfo *info;
6844 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6845 mono_tramp_info_register (info, NULL);
6848 mono_memory_barrier ();
6850 cache [sig->param_count] = start;
6855 /*========================= End of Function ========================*/
6857 /*------------------------------------------------------------------*/
6859 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6863 /*------------------------------------------------------------------*/
6866 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6867 int offset, gboolean load_imt_reg)
6869 guint8 *code, *start;
6872 start = code = mono_global_codeman_reserve (size);
6875 * Replace the "this" argument with the target
6877 s390_lgr (code, s390_r1, s390_r2);
6878 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6881 * Load the IMT register, if needed
6884 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6890 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6892 s390_agfi(code, s390_r1, offset);
6894 s390_lg (code, s390_r1, 0, s390_r1, 0);
6895 s390_br (code, s390_r1);
6900 /*========================= End of Function ========================*/
6902 /*------------------------------------------------------------------*/
6904 /* Name - mono_arch_build_imt_trampoline. */
6908 /*------------------------------------------------------------------*/
6911 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6912 MonoIMTCheckItem **imt_entries, int count,
6913 gpointer fail_tramp)
6917 guchar *code, *start;
6920 for (i = 0; i < count; ++i) {
6921 MonoIMTCheckItem *item = imt_entries [i];
6922 if (item->is_equals) {
6923 if (item->check_target_idx) {
6924 if (!item->compare_done)
6925 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6926 if (item->has_target_code)
6927 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6929 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6933 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6935 if (!item->has_target_code)
6936 item->chunk_size += LOAD_SIZE;
6938 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6939 #if ENABLE_WRONG_METHOD_CHECK
6940 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6945 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6946 imt_entries [item->check_target_idx]->compare_done = TRUE;
6948 size += item->chunk_size;
6952 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6954 code = mono_domain_code_reserve (domain, size);
6958 for (i = 0; i < count; ++i) {
6959 MonoIMTCheckItem *item = imt_entries [i];
6960 item->code_target = (guint8 *) code;
6961 if (item->is_equals) {
6962 if (item->check_target_idx) {
6963 if (!item->compare_done) {
6964 S390_SET (code, s390_r0, item->key);
6965 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6967 item->jmp_code = (guint8*) code;
6968 s390_jcl (code, S390_CC_NE, 0);
6970 if (item->has_target_code) {
6971 S390_SET (code, s390_r1, item->value.target_code);
6973 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6974 s390_lg (code, s390_r1, 0, s390_r1, 0);
6976 s390_br (code, s390_r1);
6981 S390_SET (code, s390_r0, item->key);
6982 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6983 item->jmp_code = (guint8*) code;
6984 s390_jcl (code, S390_CC_NE, 0);
6985 if (item->has_target_code) {
6986 S390_SET (code, s390_r1, item->value.target_code);
6989 S390_SET (code, s390_r1,
6990 (&(vtable->vtable [item->value.vtable_slot])));
6991 s390_lg (code, s390_r1, 0, s390_r1, 0);
6993 s390_br (code, s390_r1);
6994 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6995 s390_patch_rel(item->jmp_code+2, target);
6996 S390_SET (code, s390_r1, fail_tramp);
6997 s390_br (code, s390_r1);
6998 item->jmp_code = NULL;
7000 /* enable the commented code to assert on wrong method */
7001 #if ENABLE_WRONG_METHOD_CHECK
7002 g_assert_not_reached ();
7004 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7005 s390_lg (code, s390_r1, 0, s390_r1, 0);
7006 s390_br (code, s390_r1);
7010 S390_SET (code, s390_r0, item->key);
7011 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
7012 item->jmp_code = (guint8 *) code;
7013 s390_jcl (code, S390_CC_GE, 0);
7017 * patch the branches to get to the target items
7019 for (i = 0; i < count; ++i) {
7020 MonoIMTCheckItem *item = imt_entries [i];
7021 if (item->jmp_code) {
7022 if (item->check_target_idx) {
7024 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
7026 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
7031 mono_arch_flush_icache ((guint8*)start, (code - start));
7034 mono_stats.imt_trampolines_size += (code - start);
7036 g_assert (code - start <= size);
7038 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
7039 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
7044 /*========================= End of Function ========================*/
7046 /*------------------------------------------------------------------*/
7048 /* Name - mono_arch_find_imt_method. */
7050 /* Function - Get the method address from MONO_ARCH_IMT_REG */
7051 /* found in the save area. */
7053 /*------------------------------------------------------------------*/
7056 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
7058 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
7061 /*========================= End of Function ========================*/
7063 /*------------------------------------------------------------------*/
7065 /* Name - mono_arch_find_static_call_vtable */
7067 /* Function - Find the static call vtable. */
7069 /*------------------------------------------------------------------*/
7072 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
7074 mgreg_t *r = (mgreg_t*)regs;
7076 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
7079 /*========================= End of Function ========================*/
7081 /*------------------------------------------------------------------*/
7083 /* Name - mono_arch_get_cie_program */
7085 /* Function - Find the static call vtable. */
7087 /*------------------------------------------------------------------*/
7090 mono_arch_get_cie_program (void)
7094 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
7099 /*========================= End of Function ========================*/
7101 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7103 /*------------------------------------------------------------------*/
7105 /* Name - mono_arch_set_breakpoint. */
7107 /* Function - Set a breakpoint at the native code corresponding */
7108 /* to JI at NATIVE_OFFSET. The location should */
7109 /* contain code emitted by OP_SEQ_POINT. */
7111 /*------------------------------------------------------------------*/
7114 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
7118 breakpointCode.pTrigger = bp_trigger_page;
7119 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
7120 code += BREAKPOINT_SIZE;
7123 /*========================= End of Function ========================*/
7125 /*------------------------------------------------------------------*/
7127 /* Name - mono_arch_clear_breakpoint. */
7129 /* Function - Clear the breakpoint at IP. */
7131 /*------------------------------------------------------------------*/
7134 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
7139 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
7143 /*========================= End of Function ========================*/
7145 /*------------------------------------------------------------------*/
7147 /* Name - mono_arch_is_breakpoint_event. */
7151 /*------------------------------------------------------------------*/
7154 mono_arch_is_breakpoint_event (void *info, void *sigctx)
7156 siginfo_t* sinfo = (siginfo_t*) info;
7159 * Sometimes the address is off by 4
7161 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
7167 /*========================= End of Function ========================*/
7169 /*------------------------------------------------------------------*/
7171 /* Name - mono_arch_skip_breakpoint. */
7173 /* Function - Modify the CTX so the IP is placed after the */
7174 /* breakpoint instruction, so when we resume, the */
7175 /* instruction is not executed again. */
7177 /*------------------------------------------------------------------*/
7180 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
7182 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
7185 /*========================= End of Function ========================*/
7187 /*------------------------------------------------------------------*/
7189 /* Name - mono_arch_start_single_stepping. */
7191 /* Function - Start single stepping. */
7193 /*------------------------------------------------------------------*/
7196 mono_arch_start_single_stepping (void)
7198 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
7201 /*========================= End of Function ========================*/
7203 /*------------------------------------------------------------------*/
7205 /* Name - mono_arch_stop_single_stepping. */
7207 /* Function - Stop single stepping. */
7209 /*------------------------------------------------------------------*/
7212 mono_arch_stop_single_stepping (void)
7214 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
7217 /*========================= End of Function ========================*/
7219 /*------------------------------------------------------------------*/
7221 /* Name - mono_arch_is_single_step_event. */
7223 /* Function - Return whether the machine state in sigctx cor- */
7224 /* responds to a single step event. */
7226 /*------------------------------------------------------------------*/
7229 mono_arch_is_single_step_event (void *info, void *sigctx)
7231 siginfo_t* sinfo = (siginfo_t*) info;
7234 * Sometimes the address is off by 4
7236 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7242 /*========================= End of Function ========================*/
7244 /*------------------------------------------------------------------*/
7246 /* Name - mono_arch_skip_single_step. */
7248 /* Function - Modify the ctx so the IP is placed after the */
7249 /* single step trigger instruction, so that the */
7250 /* instruction is not executed again. */
7252 /*------------------------------------------------------------------*/
7255 mono_arch_skip_single_step (MonoContext *ctx)
7257 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7260 /*========================= End of Function ========================*/
7262 /*------------------------------------------------------------------*/
7264 /* Name - mono_arch_create_seq_point_info. */
7266 /* Function - Return a pointer to a data struction which is */
7267 /* used by the sequence point implementation in */
7270 /*------------------------------------------------------------------*/
7273 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7279 /*========================= End of Function ========================*/
7281 /*------------------------------------------------------------------*/
7283 /* Name - mono_arch_init_lmf_ext. */
7287 /*------------------------------------------------------------------*/
7290 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7292 ext->lmf.previous_lmf = prev_lmf;
7293 /* Mark that this is a MonoLMFExt */
7294 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7295 ext->lmf.ebp = (gssize)ext;
7298 /*========================= End of Function ========================*/
7302 /*------------------------------------------------------------------*/
7304 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7306 /* Function - If this CPU supports vector operations then it */
7307 /* supports the equivalent of SSE1-4. */
7309 /*------------------------------------------------------------------*/
7312 mono_arch_cpu_enumerate_simd_versions (void)
7314 guint32 sseOpts = 0;
7316 if (mono_hwcap_s390x_has_vec)
7317 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7318 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7319 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7320 SIMD_VERSION_SSE4a);
7325 /*========================= End of Function ========================*/
7327 /*------------------------------------------------------------------*/
7329 /* Name - mono_arch_opcode_supported. */
7331 /* Function - Check if a given return code is supported. */
7333 /*------------------------------------------------------------------*/
7336 mono_arch_opcode_supported (int opcode)
7339 case OP_ATOMIC_ADD_I4:
7340 case OP_ATOMIC_ADD_I8:
7341 case OP_ATOMIC_EXCHANGE_I4:
7342 case OP_ATOMIC_EXCHANGE_I8:
7349 /*========================= End of Function ========================*/