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);
2220 if ((sig->call_convention == MONO_CALL_VARARG) &&
2221 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2222 (iParm < sig->sentinelpos))
2223 cfg->sig_cookie += size;
2224 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2227 offset += MAX(size, 8);
2232 cfg->locals_min_stack_offset = offset;
2234 curinst = cfg->locals_start;
2235 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2236 inst = cfg->varinfo [iVar];
2237 if ((inst->flags & MONO_INST_IS_DEAD) ||
2238 (inst->opcode == OP_REGVAR))
2241 /*--------------------------------------------------*/
2242 /* inst->backend.is_pinvoke indicates native sized */
2243 /* value typs this is used by the pinvoke wrappers */
2244 /* when they call functions returning structure */
2245 /*--------------------------------------------------*/
2246 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2247 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2248 (guint32 *) &align);
2250 size = mono_type_size (inst->inst_vtype, &align);
2252 offset = S390_ALIGN(offset, align);
2253 inst->inst_offset = offset;
2254 inst->opcode = OP_REGOFFSET;
2255 inst->inst_basereg = frame_reg;
2257 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2258 iVar, inst->inst_offset, size));
2261 cfg->locals_max_stack_offset = offset;
2263 /*------------------------------------------------------*/
2264 /* Allow space for the trace method stack area if needed*/
2265 /*------------------------------------------------------*/
2266 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2267 offset += S390_TRACE_STACK_SIZE;
2269 /*------------------------------------------------------*/
2270 /* Reserve space to save LMF and caller saved registers */
2271 /*------------------------------------------------------*/
2272 if (cfg->method->save_lmf)
2273 offset += sizeof (MonoLMF);
2275 /*------------------------------------------------------*/
2276 /* align the offset */
2277 /*------------------------------------------------------*/
2278 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2280 /*------------------------------------------------------*/
2281 /* Fix offsets for args whose value is in parent frame */
2282 /*------------------------------------------------------*/
2283 for (iParm = sArg; iParm < eArg; ++iParm) {
2284 inst = cfg->args [iParm];
2286 if (inst->opcode == OP_S390_STKARG) {
2287 inst->opcode = OP_REGOFFSET;
2288 inst->inst_offset += cfg->stack_offset;
2293 /*========================= End of Function ========================*/
2295 /*------------------------------------------------------------------*/
2297 /* Name - mono_arch_create_vars */
2299 /*------------------------------------------------------------------*/
2302 mono_arch_create_vars (MonoCompile *cfg)
2304 MonoMethodSignature *sig;
2307 sig = mono_method_signature (cfg->method);
2309 cinfo = get_call_info (cfg, cfg->mempool, sig);
2311 if (cinfo->struct_ret) {
2312 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2313 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2314 printf ("vret_addr = ");
2315 mono_print_ins (cfg->vret_addr);
2320 /*========================= End of Function ========================*/
2322 /*------------------------------------------------------------------*/
2324 /* Name - add_outarg_reg2. */
2326 /*------------------------------------------------------------------*/
2329 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2334 case RegTypeGeneral:
2335 MONO_INST_NEW (cfg, ins, OP_MOVE);
2336 ins->dreg = mono_alloc_ireg (cfg);
2337 ins->sreg1 = tree->dreg;
2338 MONO_ADD_INS (cfg->cbb, ins);
2339 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2342 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2343 ins->dreg = mono_alloc_freg (cfg);
2344 ins->sreg1 = tree->dreg;
2345 MONO_ADD_INS (cfg->cbb, ins);
2346 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2349 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2350 ins->dreg = mono_alloc_freg (cfg);
2351 ins->sreg1 = tree->dreg;
2352 MONO_ADD_INS (cfg->cbb, ins);
2353 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2356 g_assert_not_reached ();
2360 /*========================= End of Function ========================*/
2362 /*------------------------------------------------------------------*/
2364 /* Name - emit_sig_cookie. */
2366 /*------------------------------------------------------------------*/
2369 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2371 MonoMethodSignature *tmpSig;
2374 cfg->disable_aot = TRUE;
2376 /*----------------------------------------------------------*/
2377 /* mono_ArgIterator_Setup assumes the signature cookie is */
2378 /* passed first and all the arguments which were before it */
2379 /* passed on the stack after the signature. So compensate */
2380 /* by passing a different signature. */
2381 /*----------------------------------------------------------*/
2382 tmpSig = mono_metadata_signature_dup (call->signature);
2383 tmpSig->param_count -= call->signature->sentinelpos;
2384 tmpSig->sentinelpos = 0;
2385 if (tmpSig->param_count > 0)
2386 memcpy (tmpSig->params,
2387 call->signature->params + call->signature->sentinelpos,
2388 tmpSig->param_count * sizeof(MonoType *));
2390 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2391 sig_arg->dreg = mono_alloc_ireg (cfg);
2392 sig_arg->inst_p0 = tmpSig;
2393 MONO_ADD_INS (cfg->cbb, sig_arg);
2395 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2396 cinfo->sigCookie.offset, sig_arg->dreg);
2399 /*========================= End of Function ========================*/
2401 /*------------------------------------------------------------------*/
2403 /* Name - mono_arch_emit_call */
2405 /*------------------------------------------------------------------*/
2408 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2411 MonoMethodSignature *sig;
2413 int i, n, lParamArea;
2415 ArgInfo *ainfo = NULL;
2417 MonoMethodHeader *header;
2420 sig = call->signature;
2421 n = sig->param_count + sig->hasthis;
2422 DEBUG (g_print ("Call requires: %d parameters\n",n));
2424 cinfo = get_call_info (cfg, cfg->mempool, sig);
2426 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2427 cinfo->sz.parm_size + cinfo->sz.offset;
2428 call->stack_usage = MAX(stackSize, call->stack_usage);
2429 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2430 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2431 cfg->flags |= MONO_CFG_HAS_CALLS;
2433 if (cinfo->struct_ret) {
2434 MONO_INST_NEW (cfg, ins, OP_MOVE);
2435 ins->sreg1 = call->vret_var->dreg;
2436 ins->dreg = mono_alloc_preg (cfg);
2437 MONO_ADD_INS (cfg->cbb, ins);
2438 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2441 header = cfg->header;
2442 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2447 for (i = 0; i < n; ++i) {
2450 ainfo = cinfo->args + i;
2451 if (i >= sig->hasthis)
2452 t = sig->params [i - sig->hasthis];
2454 t = &mono_defaults.int_class->byval_arg;
2455 t = mini_get_underlying_type (t);
2457 in = call->args [i];
2459 if ((sig->call_convention == MONO_CALL_VARARG) &&
2461 (i == sig->sentinelpos)) {
2462 emit_sig_cookie (cfg, call, cinfo);
2465 switch (ainfo->regtype) {
2466 case RegTypeGeneral:
2467 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2470 if (MONO_TYPE_ISSTRUCT (t)) {
2471 /* Valuetype passed in one fp register */
2472 ainfo->regtype = RegTypeStructByValInFP;
2475 if (ainfo->size == 4)
2476 ainfo->regtype = RegTypeFPR4;
2477 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2480 case RegTypeStructByVal:
2481 case RegTypeStructByAddr:
2482 case RegTypeStructByAddrOnStack: {
2486 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2487 size = sizeof (MonoTypedRef);
2488 align = sizeof (gpointer);
2492 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2495 * Other backends use mono_type_stack_size (), but that
2496 * aligns the size to 8, which is larger than the size of
2497 * the source, leading to reads of invalid memory if the
2498 * source is at the end of address space.
2500 size = mono_class_value_size (in->klass, &align);
2503 g_assert (in->klass);
2505 ainfo->offparm += cinfo->sz.offStruct;
2507 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2508 ins->sreg1 = in->dreg;
2509 ins->klass = in->klass;
2510 ins->backend.size = ainfo->size;
2511 ins->inst_p0 = call;
2512 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2513 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2515 MONO_ADD_INS (cfg->cbb, ins);
2517 if (ainfo->regtype == RegTypeStructByAddr) {
2519 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2520 * use the normal OUTARG opcodes to pass the address of the location to
2523 int treg = mono_alloc_preg (cfg);
2524 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2525 frmReg, ainfo->offparm);
2526 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2527 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2528 /* The address of the valuetype is passed on the stack */
2529 int treg = mono_alloc_preg (cfg);
2530 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2531 frmReg, ainfo->offparm);
2532 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2533 ainfo->reg, ainfo->offset, treg);
2535 if (cfg->compute_gc_maps) {
2538 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2544 if (!t->byref && t->type == MONO_TYPE_R4) {
2545 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2546 STK_BASE, ainfo->offset + 4,
2548 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2549 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2550 STK_BASE, ainfo->offset,
2553 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2554 ins->inst_destbasereg = STK_BASE;
2555 ins->inst_offset = ainfo->offset;
2556 ins->sreg1 = in->dreg;
2559 /* This is needed by MonoTypedRef->value to point to the correct data */
2560 if ((sig->call_convention == MONO_CALL_VARARG) &&
2561 (i >= sig->sentinelpos)) {
2562 switch (ainfo->size) {
2564 ins->opcode = OP_STOREI1_MEMBASE_REG;
2567 ins->opcode = OP_STOREI2_MEMBASE_REG;
2570 ins->opcode = OP_STOREI4_MEMBASE_REG;
2578 MONO_ADD_INS (cfg->cbb, ins);
2582 g_assert_not_reached ();
2588 * Handle the case where there are no implicit arguments
2590 if ((sig->call_convention == MONO_CALL_VARARG) &&
2592 (i == sig->sentinelpos)) {
2593 emit_sig_cookie (cfg, call, cinfo);
2597 /*========================= End of Function ========================*/
2599 /*------------------------------------------------------------------*/
2601 /* Name - mono_arch_emit_outarg_vt */
2603 /*------------------------------------------------------------------*/
2606 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2608 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2609 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2610 int size = ins->backend.size;
2612 if (ainfo->regtype == RegTypeStructByVal) {
2614 arg->ins.sreg1 = ainfo->reg;
2615 arg->ins.opcode = OP_OUTARG_VT;
2616 arg->size = ainfo->size;
2617 arg->offset = ainfo->offset;
2618 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2620 if (ainfo->reg != STK_BASE) {
2621 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2623 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2626 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2627 int dreg = mono_alloc_freg (cfg);
2629 if (ainfo->size == 4) {
2630 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2631 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2633 g_assert (ainfo->size == 8);
2635 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2638 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2641 MonoMethodHeader *header;
2644 header = mono_method_get_header_checked (cfg->method, &error);
2645 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2646 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2651 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2652 src->dreg, 0, size);
2654 if (cfg->compute_gc_maps) {
2657 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2662 /*========================= End of Function ========================*/
2664 /*------------------------------------------------------------------*/
2666 /* Name - mono_arch_emit_setret */
2668 /*------------------------------------------------------------------*/
2671 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2673 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2676 if (ret->type == MONO_TYPE_R4) {
2677 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2679 } else if (ret->type == MONO_TYPE_R8) {
2680 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2685 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2688 /*========================= End of Function ========================*/
2690 /*------------------------------------------------------------------*/
2692 /* Name - mono_arch_instrument_mem_needs */
2694 /* Function - Allow tracing to work with this interface (with */
2695 /* an optional argument). */
2697 /*------------------------------------------------------------------*/
2700 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2702 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2704 /* split prolog-epilog requirements? */
2705 *code = 50; /* max bytes needed: check this number */
2708 /*========================= End of Function ========================*/
2710 /*------------------------------------------------------------------*/
2712 /* Name - mono_arch_instrument_prolog */
2714 /* Function - Create an "instrumented" prolog. */
2716 /*------------------------------------------------------------------*/
2719 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2720 gboolean enable_arguments)
2727 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2728 if (cfg->method->save_lmf)
2729 parmOffset -= sizeof(MonoLMF);
2730 fpOffset = parmOffset + (5*sizeof(gpointer));
2733 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2734 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2735 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2736 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2737 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2738 S390_SET (code, s390_r1, func);
2739 S390_SET (code, s390_r2, cfg->method);
2740 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2741 s390_lgr (code, s390_r4, STK_BASE);
2742 s390_aghi (code, s390_r4, cfg->stack_usage);
2743 s390_basr (code, s390_r14, s390_r1);
2744 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2745 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2746 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2747 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2748 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2753 /*========================= End of Function ========================*/
2755 /*------------------------------------------------------------------*/
2757 /* Name - mono_arch_instrument_epilog */
2759 /* Function - Create an epilog that will handle the returned */
2760 /* values used in instrumentation. */
2762 /*------------------------------------------------------------------*/
2765 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2768 int save_mode = SAVE_NONE,
2771 MonoMethod *method = cfg->method;
2772 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2774 offset = code - cfg->native_code;
2775 /*-----------------------------------------*/
2776 /* We need about 128 bytes of instructions */
2777 /*-----------------------------------------*/
2778 if (offset > (cfg->code_size - 128)) {
2779 cfg->code_size *= 2;
2780 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2781 code = cfg->native_code + offset;
2784 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2785 if (method->save_lmf)
2786 saveOffset -= sizeof(MonoLMF);
2790 case MONO_TYPE_VOID:
2791 /* special case string .ctor icall */
2792 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2793 save_mode = SAVE_ONE;
2795 save_mode = SAVE_NONE;
2799 save_mode = SAVE_ONE;
2802 save_mode = SAVE_R4;
2805 save_mode = SAVE_R8;
2807 case MONO_TYPE_VALUETYPE:
2808 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2809 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2812 save_mode = SAVE_STRUCT;
2815 save_mode = SAVE_ONE;
2819 switch (save_mode) {
2821 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2822 if (enable_arguments) {
2823 s390_lgr (code, s390_r3, s390_r2);
2827 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2828 if (enable_arguments) {
2829 s390_ldebr (code, s390_f0, s390_f0);
2833 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2836 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2837 if (enable_arguments) {
2838 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2839 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2847 S390_SET (code, s390_r1, func);
2848 S390_SET (code, s390_r2, cfg->method);
2849 s390_basr (code, s390_r14, s390_r1);
2851 switch (save_mode) {
2853 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2857 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2860 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2870 /*========================= End of Function ========================*/
2872 /*------------------------------------------------------------------*/
2874 /* Name - compare_and_branch */
2876 /* Function - Form a peephole pass at the code looking for */
2877 /* simple optimizations. */
2879 /*------------------------------------------------------------------*/
2882 compare_and_branch(MonoBasicBlock *bb, MonoInst *ins, int cc, gboolean logical)
2886 if (mono_hwcap_s390x_has_gie) {
2887 last = mono_inst_prev (ins, FILTER_IL_SEQ_POINT);
2888 ins->sreg1 = last->sreg1;
2889 ins->sreg2 = last->sreg2;
2891 switch(last->opcode) {
2894 ins->opcode = OP_S390_CLRJ;
2896 ins->opcode = OP_S390_CRJ;
2897 MONO_DELETE_INS(bb, last);
2902 ins->opcode = OP_S390_CLGRJ;
2904 ins->opcode = OP_S390_CGRJ;
2905 MONO_DELETE_INS(bb, last);
2907 case OP_ICOMPARE_IMM:
2908 ins->backend.data = (gpointer) last->inst_imm;
2910 ins->opcode = OP_S390_CLIJ;
2912 ins->opcode = OP_S390_CIJ;
2913 MONO_DELETE_INS(bb, last);
2915 case OP_COMPARE_IMM:
2916 case OP_LCOMPARE_IMM:
2917 ins->backend.data = (gpointer) last->inst_imm;
2919 ins->opcode = OP_S390_CLGIJ;
2921 ins->opcode = OP_S390_CGIJ;
2922 MONO_DELETE_INS(bb, last);
2928 /*========================= End of Function ========================*/
2930 /*------------------------------------------------------------------*/
2932 /* Name - mono_arch_peephole_pass_1 */
2934 /* Function - Form a peephole pass at the code looking for */
2935 /* simple optimizations. */
2937 /*------------------------------------------------------------------*/
2940 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2944 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2945 switch (ins->opcode) {
2948 compare_and_branch(bb, ins, S390_CC_EQ, FALSE);
2952 compare_and_branch(bb, ins, S390_CC_NE, TRUE);
2956 compare_and_branch(bb, ins, S390_CC_LT, FALSE);
2960 compare_and_branch(bb, ins, S390_CC_LT, TRUE);
2964 compare_and_branch(bb, ins, S390_CC_GT, FALSE);
2968 compare_and_branch(bb, ins, S390_CC_GT, TRUE);
2972 compare_and_branch(bb, ins, S390_CC_GE, FALSE);
2976 compare_and_branch(bb, ins, S390_CC_GE, TRUE);
2980 compare_and_branch(bb, ins, S390_CC_LE, FALSE);
2984 compare_and_branch(bb, ins, S390_CC_LE, TRUE);
2988 // mono_peephole_ins (bb, ins);
2993 /*========================= End of Function ========================*/
2995 /*------------------------------------------------------------------*/
2997 /* Name - mono_arch_peephole_pass_2 */
2999 /* Function - Form a peephole pass at the code looking for */
3000 /* simple optimizations. */
3002 /*------------------------------------------------------------------*/
3005 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
3007 MonoInst *ins, *n, *last_ins = NULL;
3009 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
3010 switch (ins->opcode) {
3011 case OP_LOADU4_MEMBASE:
3012 case OP_LOADI4_MEMBASE:
3013 if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG) &&
3014 ins->inst_basereg == last_ins->inst_destbasereg &&
3015 ins->inst_offset == last_ins->inst_offset) {
3016 ins->opcode = (ins->opcode == OP_LOADI4_MEMBASE) ? OP_ICONV_TO_I4 : OP_ICONV_TO_U4;
3017 ins->sreg1 = last_ins->sreg1;
3021 mono_peephole_ins (bb, ins);
3025 /*========================= End of Function ========================*/
3027 /*------------------------------------------------------------------*/
3029 /* Name - mono_arch_lowering_pass. */
3031 /*------------------------------------------------------------------*/
3034 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
3036 MonoInst *ins, *next;
3038 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
3039 switch (ins->opcode) {
3044 case OP_IDIV_UN_IMM:
3045 case OP_IREM_UN_IMM:
3050 case OP_LOCALLOC_IMM:
3051 mono_decompose_op_imm (cfg, bb, ins);
3054 if (!s390_is_imm16 (ins->inst_imm))
3055 /* This is created by the memcpy code which ignores is_inst_imm */
3056 mono_decompose_op_imm (cfg, bb, ins);
3063 bb->max_vreg = cfg->next_vreg;
3066 /*========================= End of Function ========================*/
3068 /*------------------------------------------------------------------*/
3070 /* Name - emit_float_to_int */
3072 /* Function - Create instructions which will convert a floating */
3073 /* point value to integer. */
3075 /*------------------------------------------------------------------*/
3078 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
3080 /* sreg is a float, dreg is an integer reg. */
3082 s390_cgdbr (code, dreg, 5, sreg);
3085 s390_ltgr (code, dreg, dreg);
3087 s390_oill (code, dreg, 0x80);
3088 s390_lghi (code, s390_r0, 0xff);
3089 s390_ngr (code, dreg, s390_r0);
3092 s390_ltgr (code, dreg, dreg);
3094 s390_oill (code, dreg, 0x8000);
3095 s390_llill(code, s390_r0, 0xffff);
3096 s390_ngr (code, dreg, s390_r0);
3101 S390_SET (code, s390_r13, 0x41e0000000000000llu);
3102 s390_ldgr (code, s390_f14, s390_r13);
3103 s390_ldr (code, s390_f15, sreg);
3104 s390_cdbr (code, s390_f15, s390_f14);
3105 s390_jl (code, 0); CODEPTR (code, o[0]);
3106 S390_SET (code, s390_r13, 0x41f0000000000000llu);
3107 s390_ldgr (code, s390_f14, s390_r13);
3108 s390_sdbr (code, s390_f15, s390_f14);
3109 s390_cfdbr (code, dreg, 7, s390_f15);
3111 PTRSLOT (code, o[0]);
3112 s390_cfdbr (code, dreg, 5, sreg);
3115 s390_lghi (code, s390_r0, 0xff);
3116 s390_ngr (code, dreg, s390_r0);
3119 s390_llill(code, s390_r0, 0xffff);
3120 s390_ngr (code, dreg, s390_r0);
3127 /*========================= End of Function ========================*/
3129 /*------------------------------------------------------------------*/
3131 /* Name - is_unsigned. */
3133 /* Function - Return TRUE if next opcode is checking for un- */
3136 /*------------------------------------------------------------------*/
3139 is_unsigned (MonoInst *next)
3142 (((next->opcode >= OP_IBNE_UN) &&
3143 (next->opcode <= OP_IBLT_UN)) ||
3144 ((next->opcode >= OP_LBNE_UN) &&
3145 (next->opcode <= OP_LBLT_UN)) ||
3146 ((next->opcode >= OP_COND_EXC_NE_UN) &&
3147 (next->opcode <= OP_COND_EXC_LT_UN)) ||
3148 ((next->opcode >= OP_COND_EXC_INE_UN) &&
3149 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
3150 ((next->opcode == OP_CLT_UN) ||
3151 (next->opcode == OP_CGT_UN) ||
3152 (next->opcode == OP_ICGE_UN) ||
3153 (next->opcode == OP_ICLE_UN)) ||
3154 ((next->opcode == OP_ICLT_UN) ||
3155 (next->opcode == OP_ICGT_UN) ||
3156 (next->opcode == OP_LCLT_UN) ||
3157 (next->opcode == OP_LCGT_UN))))
3163 /*========================= End of Function ========================*/
3165 /*------------------------------------------------------------------*/
3167 /* Name - mono_arch_output_basic_block */
3169 /* Function - Perform the "real" work of emitting instructions */
3170 /* that will do the work of in the basic block. */
3172 /*------------------------------------------------------------------*/
3175 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
3180 guint8 *code = cfg->native_code + cfg->code_len;
3181 guint last_offset = 0;
3184 /* we don't align basic blocks of loops on s390 */
3186 if (cfg->verbose_level > 2)
3187 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3189 MONO_BB_FOR_EACH_INS (bb, ins) {
3190 offset = code - cfg->native_code;
3192 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3194 if (offset > (cfg->code_size - max_len - 16)) {
3195 cfg->code_size *= 2;
3196 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3197 code = cfg->native_code + offset;
3200 mono_debug_record_line_number (cfg, ins, offset);
3202 switch (ins->opcode) {
3203 case OP_STOREI1_MEMBASE_IMM: {
3204 s390_lghi (code, s390_r0, ins->inst_imm);
3205 S390_LONG (code, stcy, stc, s390_r0, 0,
3206 ins->inst_destbasereg, ins->inst_offset);
3209 case OP_STOREI2_MEMBASE_IMM: {
3210 s390_lghi (code, s390_r0, ins->inst_imm);
3211 S390_LONG (code, sthy, sth, s390_r0, 0,
3212 ins->inst_destbasereg, ins->inst_offset);
3215 case OP_STOREI4_MEMBASE_IMM: {
3216 s390_lgfi (code, s390_r0, ins->inst_imm);
3217 S390_LONG (code, sty, st, s390_r0, 0,
3218 ins->inst_destbasereg, ins->inst_offset);
3221 case OP_STORE_MEMBASE_IMM:
3222 case OP_STOREI8_MEMBASE_IMM: {
3223 S390_SET (code, s390_r0, ins->inst_imm);
3224 S390_LONG (code, stg, stg, s390_r0, 0,
3225 ins->inst_destbasereg, ins->inst_offset);
3228 case OP_STOREI1_MEMBASE_REG: {
3229 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3230 ins->inst_destbasereg, ins->inst_offset);
3233 case OP_STOREI2_MEMBASE_REG: {
3234 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3235 ins->inst_destbasereg, ins->inst_offset);
3238 case OP_STOREI4_MEMBASE_REG: {
3239 S390_LONG (code, sty, st, ins->sreg1, 0,
3240 ins->inst_destbasereg, ins->inst_offset);
3243 case OP_STORE_MEMBASE_REG:
3244 case OP_STOREI8_MEMBASE_REG: {
3245 S390_LONG (code, stg, stg, ins->sreg1, 0,
3246 ins->inst_destbasereg, ins->inst_offset);
3250 g_assert_not_reached ();
3252 case OP_LOAD_MEMBASE:
3253 case OP_LOADI8_MEMBASE: {
3254 S390_LONG (code, lg, lg, ins->dreg, 0,
3255 ins->inst_basereg, ins->inst_offset);
3258 case OP_LOADI4_MEMBASE: {
3259 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3260 ins->inst_basereg, ins->inst_offset);
3263 case OP_LOADU4_MEMBASE: {
3264 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3265 ins->inst_basereg, ins->inst_offset);
3268 case OP_LOADU1_MEMBASE: {
3269 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3270 ins->inst_basereg, ins->inst_offset);
3273 case OP_LOADI1_MEMBASE: {
3274 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3275 ins->inst_basereg, ins->inst_offset);
3278 case OP_LOADU2_MEMBASE: {
3279 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3280 ins->inst_basereg, ins->inst_offset);
3283 case OP_LOADI2_MEMBASE: {
3284 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3285 ins->inst_basereg, ins->inst_offset);
3288 case OP_LCONV_TO_I1: {
3289 s390_lgbr (code, ins->dreg, ins->sreg1);
3292 case OP_LCONV_TO_I2: {
3293 s390_lghr (code, ins->dreg, ins->sreg1);
3296 case OP_LCONV_TO_U1: {
3297 s390_llgcr (code, ins->dreg, ins->sreg1);
3300 case OP_LCONV_TO_U2: {
3301 s390_llghr (code, ins->dreg, ins->sreg1);
3304 case OP_ICONV_TO_I1: {
3305 s390_lgbr (code, ins->dreg, ins->sreg1);
3308 case OP_ICONV_TO_I2: {
3309 s390_lghr (code, ins->dreg, ins->sreg1);
3312 case OP_ICONV_TO_U1: {
3313 s390_llgcr (code, ins->dreg, ins->sreg1);
3316 case OP_ICONV_TO_U2: {
3317 s390_llghr (code, ins->dreg, ins->sreg1);
3320 case OP_ICONV_TO_U4: {
3321 s390_llgfr (code, ins->dreg, ins->sreg1);
3324 case OP_ICONV_TO_I4: {
3325 s390_lgfr (code, ins->dreg, ins->sreg1);
3330 if (is_unsigned (ins->next))
3331 s390_clgr (code, ins->sreg1, ins->sreg2);
3333 s390_cgr (code, ins->sreg1, ins->sreg2);
3337 if (is_unsigned (ins->next))
3338 s390_clr (code, ins->sreg1, ins->sreg2);
3340 s390_cr (code, ins->sreg1, ins->sreg2);
3343 case OP_COMPARE_IMM:
3344 case OP_LCOMPARE_IMM: {
3345 gboolean branchUn = is_unsigned (ins->next);
3346 if ((ins->inst_imm == 0) && (!branchUn)) {
3347 s390_ltgr (code, ins->sreg1, ins->sreg1);
3349 S390_SET (code, s390_r0, ins->inst_imm);
3351 s390_clgr (code, ins->sreg1, s390_r0);
3353 s390_cgr (code, ins->sreg1, s390_r0);
3357 case OP_ICOMPARE_IMM: {
3358 gboolean branchUn = is_unsigned (ins->next);
3359 if ((ins->inst_imm == 0) && (!branchUn)) {
3360 s390_ltr (code, ins->sreg1, ins->sreg1);
3362 S390_SET (code, s390_r0, ins->inst_imm);
3364 s390_clr (code, ins->sreg1, s390_r0);
3366 s390_cr (code, ins->sreg1, s390_r0);
3371 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3373 S390_CALL_TEMPLATE (code, s390_r14);
3377 if (mono_hwcap_s390x_has_mlt) {
3378 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3381 s390_agr (code, ins->dreg, src2);
3386 if (mono_hwcap_s390x_has_mlt) {
3387 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3390 s390_agr (code, ins->dreg, src2);
3396 s390_alcgr (code, ins->dreg, src2);
3400 if (mono_hwcap_s390x_has_mlt) {
3401 if (s390_is_imm16 (ins->inst_imm)) {
3402 s390_aghik(code, ins->dreg, ins->sreg1, ins->inst_imm);
3404 S390_SET (code, s390_r0, ins->inst_imm);
3405 s390_agrk (code, ins->dreg, ins->sreg1, s390_r0);
3408 if (ins->dreg != ins->sreg1) {
3409 s390_lgr (code, ins->dreg, ins->sreg1);
3411 if (s390_is_imm16 (ins->inst_imm)) {
3412 s390_aghi (code, ins->dreg, ins->inst_imm);
3413 } else if (s390_is_imm32 (ins->inst_imm)) {
3414 s390_agfi (code, ins->dreg, ins->inst_imm);
3416 S390_SET (code, s390_r0, ins->inst_imm);
3417 s390_agr (code, ins->dreg, s390_r0);
3423 if (ins->dreg != ins->sreg1) {
3424 s390_lgr (code, ins->dreg, ins->sreg1);
3426 if (s390_is_imm32 (ins->inst_imm)) {
3427 s390_agfi (code, ins->dreg, ins->inst_imm);
3429 S390_SET (code, s390_r0, ins->inst_imm);
3430 s390_agr (code, ins->dreg, s390_r0);
3435 if (ins->dreg != ins->sreg1) {
3436 s390_lgr (code, ins->dreg, ins->sreg1);
3438 if (s390_is_imm16 (ins->inst_imm)) {
3439 s390_lghi (code, s390_r0, ins->inst_imm);
3440 s390_alcgr (code, ins->dreg, s390_r0);
3442 S390_SET (code, s390_r0, ins->inst_imm);
3443 s390_alcgr (code, ins->dreg, s390_r0);
3448 case OP_S390_IADD_OVF: {
3450 s390_ar (code, ins->dreg, src2);
3451 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3452 s390_lgfr (code, ins->dreg, ins->dreg);
3455 case OP_IADD_OVF_UN:
3456 case OP_S390_IADD_OVF_UN: {
3458 s390_algr (code, ins->dreg, src2);
3459 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3460 s390_llgfr (code, ins->dreg, ins->dreg);
3463 case OP_ADD_OVF_CARRY: {
3465 s390_lghi (code, s390_r0, 0);
3466 s390_lgr (code, s390_r1, s390_r0);
3467 s390_alcgr (code, s390_r0, s390_r1);
3468 s390_agr (code, ins->dreg, src2);
3469 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3470 s390_agr (code, ins->dreg, s390_r0);
3471 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3474 case OP_ADD_OVF_UN_CARRY: {
3476 s390_alcgr (code, ins->dreg, src2);
3477 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3481 if (mono_hwcap_s390x_has_mlt) {
3482 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3485 s390_sgr (code, ins->dreg, src2);
3490 if (mono_hwcap_s390x_has_mlt) {
3491 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3494 s390_sgr (code, ins->dreg, src2);
3500 s390_slbgr(code, ins->dreg, src2);
3504 if (ins->dreg != ins->sreg1) {
3505 s390_lgr (code, ins->dreg, ins->sreg1);
3507 if (s390_is_imm16 (-ins->inst_imm)) {
3508 s390_aghi (code, ins->dreg, -ins->inst_imm);
3509 } else if (s390_is_imm32 (-ins->inst_imm)) {
3510 s390_slgfi (code, ins->dreg, ins->inst_imm);
3512 S390_SET (code, s390_r0, ins->inst_imm);
3513 s390_slgr (code, ins->dreg, s390_r0);
3518 if (ins->dreg != ins->sreg1) {
3519 s390_lgr (code, ins->dreg, ins->sreg1);
3521 if (s390_is_imm16 (-ins->inst_imm)) {
3522 s390_aghi (code, ins->dreg, -ins->inst_imm);
3523 } else if (s390_is_imm32 (-ins->inst_imm)) {
3524 s390_slgfi (code, ins->dreg, ins->inst_imm);
3526 S390_SET (code, s390_r0, ins->inst_imm);
3527 s390_slgr (code, ins->dreg, s390_r0);
3532 if (ins->dreg != ins->sreg1) {
3533 s390_lgr (code, ins->dreg, ins->sreg1);
3535 if (s390_is_imm16 (-ins->inst_imm)) {
3536 s390_lghi (code, s390_r0, ins->inst_imm);
3537 s390_slbgr (code, ins->dreg, s390_r0);
3539 S390_SET (code, s390_r0, ins->inst_imm);
3540 s390_slbgr(code, ins->dreg, s390_r0);
3544 case OP_SUB_OVF_CARRY: {
3546 s390_lghi (code, s390_r0, 0);
3547 s390_lgr (code, s390_r1, s390_r0);
3548 s390_slbgr (code, s390_r0, s390_r1);
3549 s390_sgr (code, ins->dreg, src2);
3550 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3551 s390_agr (code, ins->dreg, s390_r0);
3552 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3555 case OP_SUB_OVF_UN_CARRY: {
3557 s390_slbgr (code, ins->dreg, src2);
3558 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3562 if (mono_hwcap_s390x_has_mlt) {
3563 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3565 if (ins->sreg1 == ins->dreg) {
3566 s390_ngr (code, ins->dreg, ins->sreg2);
3568 if (ins->sreg2 == ins->dreg) {
3569 s390_ngr (code, ins->dreg, ins->sreg1);
3571 s390_lgr (code, ins->dreg, ins->sreg1);
3572 s390_ngr (code, ins->dreg, ins->sreg2);
3579 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3580 if (mono_hwcap_s390x_has_mlt) {
3581 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3583 if (ins->dreg != ins->sreg1) {
3584 s390_lgr (code, ins->dreg, ins->sreg1);
3586 s390_ngr (code, ins->dreg, s390_r0);
3591 s390_lgr (code, s390_r1, ins->sreg1);
3592 s390_dsgr (code, s390_r0, ins->sreg2);
3593 s390_lgr (code, ins->dreg, s390_r1);
3597 s390_lgr (code, s390_r1, ins->sreg1);
3598 s390_lghi (code, s390_r0, 0);
3599 s390_dlgr (code, s390_r0, ins->sreg2);
3600 s390_lgr (code, ins->dreg, s390_r1);
3604 s390_lgr (code, s390_r1, ins->sreg1);
3605 s390_dsgr (code, s390_r0, ins->sreg2);
3606 s390_lgr (code, ins->dreg, s390_r0);
3610 if (s390_is_imm16 (ins->inst_imm)) {
3611 s390_lghi (code, s390_r13, ins->inst_imm);
3613 s390_lgfi (code, s390_r13, ins->inst_imm);
3615 s390_lgr (code, s390_r0, ins->sreg1);
3616 s390_dsgr (code, s390_r0, s390_r13);
3617 s390_lgfr (code, ins->dreg, s390_r0);
3621 s390_lgr (code, s390_r1, ins->sreg1);
3622 s390_lghi (code, s390_r0, 0);
3623 s390_dlgr (code, s390_r0, ins->sreg2);
3624 s390_lgr (code, ins->dreg, s390_r0);
3628 if (mono_hwcap_s390x_has_mlt) {
3629 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3631 if (ins->sreg1 == ins->dreg) {
3632 s390_ogr (code, ins->dreg, ins->sreg2);
3634 if (ins->sreg2 == ins->dreg) {
3635 s390_ogr (code, ins->dreg, ins->sreg1);
3637 s390_lgr (code, ins->dreg, ins->sreg1);
3638 s390_ogr (code, ins->dreg, ins->sreg2);
3645 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3646 if (mono_hwcap_s390x_has_mlt) {
3647 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3649 if (ins->dreg != ins->sreg1) {
3650 s390_lgr (code, ins->dreg, ins->sreg1);
3652 s390_ogr (code, ins->dreg, s390_r0);
3657 if (mono_hwcap_s390x_has_mlt) {
3658 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3660 if (ins->sreg1 == ins->dreg) {
3661 s390_xgr (code, ins->dreg, ins->sreg2);
3664 if (ins->sreg2 == ins->dreg) {
3665 s390_xgr (code, ins->dreg, ins->sreg1);
3668 s390_lgr (code, ins->dreg, ins->sreg1);
3669 s390_xgr (code, ins->dreg, ins->sreg2);
3676 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3677 if (mono_hwcap_s390x_has_mlt) {
3678 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3680 if (ins->dreg != ins->sreg1) {
3681 s390_lgr (code, ins->dreg, ins->sreg1);
3683 s390_xgr (code, ins->dreg, s390_r0);
3689 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3694 if (ins->sreg1 != ins->dreg) {
3695 s390_lgr (code, ins->dreg, ins->sreg1);
3697 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3702 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3707 if (ins->sreg1 != ins->dreg) {
3708 s390_lgr (code, ins->dreg, ins->sreg1);
3710 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3714 case OP_LSHR_UN_IMM: {
3715 if (ins->sreg1 != ins->dreg) {
3716 s390_lgr (code, ins->dreg, ins->sreg1);
3718 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3723 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3727 if (ins->sreg1 != ins->dreg) {
3728 s390_lgr (code, ins->dreg, ins->sreg1);
3730 s390_lghi (code, s390_r0, -1);
3731 s390_xgr (code, ins->dreg, s390_r0);
3735 s390_lcgr (code, ins->dreg, ins->sreg1);
3740 s390_msgr (code, ins->dreg, src2);
3745 if (ins->dreg != ins->sreg1) {
3746 s390_lgr (code, ins->dreg, ins->sreg1);
3748 if (s390_is_imm16 (ins->inst_imm)) {
3749 s390_lghi (code, s390_r13, ins->inst_imm);
3750 } else if (s390_is_imm32 (ins->inst_imm)) {
3751 s390_lgfi (code, s390_r13, ins->inst_imm);
3753 S390_SET (code, s390_r13, ins->inst_imm);
3755 s390_msgr (code, ins->dreg, s390_r13);
3760 s390_ltgr (code, s390_r1, ins->sreg1);
3761 s390_jz (code, 0); CODEPTR(code, o[0]);
3762 s390_ltgr (code, s390_r0, ins->sreg2);
3764 s390_lghi (code, s390_r1, 0);
3765 s390_j (code, 0); CODEPTR(code, o[1]);
3766 s390_xgr (code, s390_r0, s390_r1);
3767 s390_msgr (code, s390_r1, ins->sreg2);
3768 s390_xgr (code, s390_r0, s390_r1);
3769 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3770 s390_ltgr (code, s390_r0, s390_r0);
3771 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3772 PTRSLOT (code, o[0]);
3773 PTRSLOT (code, o[1]);
3774 s390_lgr (code, ins->dreg, s390_r1);
3777 case OP_LMUL_OVF_UN: {
3778 s390_lghi (code, s390_r0, 0);
3779 s390_lgr (code, s390_r1, ins->sreg1);
3780 s390_mlgr (code, s390_r0, ins->sreg2);
3781 s390_ltgr (code, s390_r0, s390_r0);
3782 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3783 s390_lgr (code, ins->dreg, s390_r1);
3787 g_assert_not_reached ();
3789 s390_algr (code, ins->dreg, src2);
3794 s390_agr (code, ins->dreg, src2);
3798 g_assert_not_reached ();
3800 s390_alcgr (code, ins->dreg, src2);
3804 if (ins->dreg != ins->sreg1) {
3805 s390_lgfr (code, ins->dreg, ins->sreg1);
3807 if (s390_is_imm16 (ins->inst_imm)) {
3808 s390_aghi (code, ins->dreg, ins->inst_imm);
3810 s390_afi (code, ins->dreg, ins->inst_imm);
3815 if (ins->dreg != ins->sreg1) {
3816 s390_lgfr (code, ins->dreg, ins->sreg1);
3818 if (s390_is_imm16 (ins->inst_imm)) {
3819 s390_lghi (code, s390_r0, ins->inst_imm);
3820 s390_alcgr (code, ins->dreg, s390_r0);
3822 S390_SET (code, s390_r0, ins->inst_imm);
3823 s390_alcgr (code, ins->dreg, s390_r0);
3828 case OP_S390_LADD_OVF: {
3830 s390_agr (code, ins->dreg, src2);
3831 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3834 case OP_LADD_OVF_UN:
3835 case OP_S390_LADD_OVF_UN: {
3837 s390_algr (code, ins->dreg, src2);
3838 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3842 CHECK_SRCDST_NCOM_I;
3843 s390_slgr (code, ins->dreg, src2);
3847 CHECK_SRCDST_NCOM_I;
3848 s390_sgr (code, ins->dreg, src2);
3852 CHECK_SRCDST_NCOM_I;
3853 s390_slbgr (code, ins->dreg, src2);
3857 if (ins->dreg != ins->sreg1) {
3858 s390_lgfr (code, ins->dreg, ins->sreg1);
3860 if (s390_is_imm16 (-ins->inst_imm)) {
3861 s390_aghi (code, ins->dreg, -ins->inst_imm);
3863 s390_agfi (code, ins->dreg, -ins->inst_imm);
3868 S390_SET (code, s390_r0, ins->inst_imm);
3869 s390_slgfr (code, ins->dreg, s390_r0);
3873 case OP_S390_ISUB_OVF: {
3875 s390_sr (code, ins->dreg, src2);
3876 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3877 s390_lgfr (code, ins->dreg, ins->dreg);
3880 case OP_ISUB_OVF_UN:
3881 case OP_S390_ISUB_OVF_UN: {
3883 s390_slr (code, ins->dreg, src2);
3884 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3885 s390_llgfr(code, ins->dreg, ins->dreg);
3889 case OP_S390_LSUB_OVF: {
3891 s390_sgr (code, ins->dreg, src2);
3892 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3895 case OP_LSUB_OVF_UN:
3896 case OP_S390_LSUB_OVF_UN: {
3898 s390_slgr (code, ins->dreg, src2);
3899 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3903 if (mono_hwcap_s390x_has_mlt) {
3904 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3906 CHECK_SRCDST_NCOM_I;
3907 s390_ngr (code, ins->dreg, src2);
3912 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3913 if (mono_hwcap_s390x_has_mlt) {
3914 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3916 if (ins->dreg != ins->sreg1) {
3917 s390_lgfr (code, ins->dreg, ins->sreg1);
3919 s390_ngr (code, ins->dreg, s390_r0);
3924 s390_lgfr (code, s390_r0, ins->sreg1);
3925 s390_srda (code, s390_r0, 0, 32);
3926 s390_dr (code, s390_r0, ins->sreg2);
3927 s390_lgfr (code, ins->dreg, s390_r1);
3931 s390_lgfr (code, s390_r0, ins->sreg1);
3932 s390_srdl (code, s390_r0, 0, 32);
3933 s390_dlr (code, s390_r0, ins->sreg2);
3934 s390_lgfr (code, ins->dreg, s390_r1);
3938 if (s390_is_imm16 (ins->inst_imm)) {
3939 s390_lghi (code, s390_r13, ins->inst_imm);
3941 s390_lgfi (code, s390_r13, ins->inst_imm);
3943 s390_lgfr (code, s390_r0, ins->sreg1);
3944 s390_srda (code, s390_r0, 0, 32);
3945 s390_dr (code, s390_r0, ins->sreg2);
3946 s390_lgfr (code, ins->dreg, s390_r1);
3950 s390_lgfr (code, s390_r0, ins->sreg1);
3951 s390_srda (code, s390_r0, 0, 32);
3952 s390_dr (code, s390_r0, ins->sreg2);
3953 s390_lgfr (code, ins->dreg, s390_r0);
3956 s390_lgfr (code, s390_r0, ins->sreg1);
3957 s390_srdl (code, s390_r0, 0, 32);
3958 s390_dlr (code, s390_r0, ins->sreg2);
3959 s390_lgfr (code, ins->dreg, s390_r0);
3963 if (s390_is_imm16 (ins->inst_imm)) {
3964 s390_lghi (code, s390_r13, ins->inst_imm);
3966 s390_lgfi (code, s390_r13, ins->inst_imm);
3968 s390_lgfr (code, s390_r0, ins->sreg1);
3969 s390_srda (code, s390_r0, 0, 32);
3970 s390_dr (code, s390_r0, ins->sreg2);
3971 s390_lgfr (code, ins->dreg, s390_r0);
3975 if (mono_hwcap_s390x_has_mlt) {
3976 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3979 s390_ogr (code, ins->dreg, src2);
3984 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3985 if (mono_hwcap_s390x_has_mlt) {
3986 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3988 if (ins->dreg != ins->sreg1) {
3989 s390_lgfr (code, ins->dreg, ins->sreg1);
3991 s390_ogr (code, ins->dreg, s390_r0);
3996 if (mono_hwcap_s390x_has_mlt) {
3997 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
4000 s390_xgr (code, ins->dreg, src2);
4005 S390_SET_MASK (code, s390_r0, ins->inst_imm);
4006 if (mono_hwcap_s390x_has_mlt) {
4007 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
4009 if (ins->dreg != ins->sreg1) {
4010 s390_lgfr (code, ins->dreg, ins->sreg1);
4012 s390_xgr (code, ins->dreg, s390_r0);
4018 s390_sll (code, ins->dreg, src2, 0);
4022 if (ins->sreg1 != ins->dreg) {
4023 s390_lgfr (code, ins->dreg, ins->sreg1);
4025 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4030 s390_sra (code, ins->dreg, src2, 0);
4034 if (ins->sreg1 != ins->dreg) {
4035 s390_lgfr (code, ins->dreg, ins->sreg1);
4037 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4040 case OP_ISHR_UN_IMM: {
4041 if (ins->sreg1 != ins->dreg) {
4042 s390_lgfr (code, ins->dreg, ins->sreg1);
4044 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4049 s390_srl (code, ins->dreg, src2, 0);
4053 if (ins->sreg1 != ins->dreg) {
4054 s390_lgfr (code, ins->dreg, ins->sreg1);
4056 s390_lghi (code, s390_r0, -1);
4057 s390_xgr (code, ins->dreg, s390_r0);
4061 s390_lcgr (code, ins->dreg, ins->sreg1);
4066 s390_msr (code, ins->dreg, src2);
4070 if (ins->dreg != ins->sreg1) {
4071 s390_lgfr (code, ins->dreg, ins->sreg1);
4073 if (s390_is_imm16 (ins->inst_imm)) {
4074 s390_lghi (code, s390_r0, ins->inst_imm);
4076 s390_lgfi (code, s390_r0, ins->inst_imm);
4078 s390_msr (code, ins->dreg, s390_r0);
4083 s390_ltr (code, s390_r1, ins->sreg1);
4084 s390_jz (code, 0); CODEPTR(code, o[0]);
4085 s390_ltr (code, s390_r0, ins->sreg2);
4087 s390_lhi (code, s390_r1, 0);
4088 s390_j (code, 0); CODEPTR(code, o[1]);
4089 s390_xr (code, s390_r0, s390_r1);
4090 s390_msr (code, s390_r1, ins->sreg2);
4091 s390_xr (code, s390_r0, s390_r1);
4092 s390_srl (code, s390_r0, 0, 31);
4093 s390_ltr (code, s390_r0, s390_r0);
4094 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4095 PTRSLOT (code, o[0]);
4096 PTRSLOT (code, o[1]);
4097 s390_lgfr (code, ins->dreg, s390_r1);
4100 case OP_IMUL_OVF_UN: {
4101 s390_lhi (code, s390_r0, 0);
4102 s390_lr (code, s390_r1, ins->sreg1);
4103 s390_mlr (code, s390_r0, ins->sreg2);
4104 s390_ltr (code, s390_r0, s390_r0);
4105 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4106 s390_lgfr (code, ins->dreg, s390_r1);
4111 S390_SET (code, ins->dreg, ins->inst_c0);
4115 mono_add_patch_info (cfg, code - cfg->native_code,
4116 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4117 S390_LOAD_TEMPLATE (code, ins->dreg);
4120 case OP_JUMP_TABLE: {
4121 mono_add_patch_info (cfg, code - cfg->native_code,
4122 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4123 S390_LOAD_TEMPLATE (code, ins->dreg);
4127 if (ins->dreg != ins->sreg1) {
4128 s390_lgr (code, ins->dreg, ins->sreg1);
4132 case OP_LCONV_TO_I8:
4134 s390_lgfr (code, ins->dreg, ins->sreg1);
4136 case OP_LCONV_TO_I4:
4137 s390_lgfr (code, ins->dreg, ins->sreg1);
4140 case OP_LCONV_TO_U8:
4141 case OP_LCONV_TO_U4:
4143 s390_llgfr (code, ins->dreg, ins->sreg1);
4145 case OP_LCONV_TO_OVF_U4:
4146 S390_SET (code, s390_r0, 4294967295);
4147 s390_clgr (code, ins->sreg1, s390_r0);
4148 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4149 s390_ltgr (code, ins->sreg1, ins->sreg1);
4150 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4151 s390_llgfr(code, ins->dreg, ins->sreg1);
4153 case OP_LCONV_TO_OVF_I4_UN:
4154 S390_SET (code, s390_r0, 2147483647);
4155 s390_cgr (code, ins->sreg1, s390_r0);
4156 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4157 s390_ltgr (code, ins->sreg1, ins->sreg1);
4158 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4159 s390_lgfr (code, ins->dreg, ins->sreg1);
4162 if (ins->dreg != ins->sreg1) {
4163 s390_ldr (code, ins->dreg, ins->sreg1);
4166 case OP_MOVE_F_TO_I8:
4167 s390_lgdr (code, ins->dreg, ins->sreg1);
4169 case OP_MOVE_I8_TO_F:
4170 s390_ldgr (code, ins->dreg, ins->sreg1);
4172 case OP_MOVE_F_TO_I4:
4173 s390_ledbr (code, s390_f0, ins->sreg1);
4174 s390_lgdr (code, ins->dreg, s390_f0);
4175 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
4177 case OP_MOVE_I4_TO_F:
4178 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
4179 s390_ldgr (code, ins->dreg, s390_r0);
4180 s390_ldebr (code, ins->dreg, ins->dreg);
4182 case OP_FCONV_TO_R4:
4183 s390_ledbr (code, ins->dreg, ins->sreg1);
4184 s390_ldebr (code, ins->dreg, ins->dreg);
4186 case OP_S390_SETF4RET:
4187 s390_ledbr (code, ins->dreg, ins->sreg1);
4190 if (s390_is_imm16 (ins->inst_offset)) {
4191 s390_lghi (code, s390_r13, ins->inst_offset);
4192 } else if (s390_is_imm32 (ins->inst_offset)) {
4193 s390_lgfi (code, s390_r13, ins->inst_offset);
4195 S390_SET (code, s390_r13, ins->inst_offset);
4197 s390_ear (code, s390_r1, 0);
4198 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4199 s390_ear (code, s390_r1, 1);
4200 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
4204 if (s390_is_imm16 (ins->inst_offset)) {
4205 s390_lghi (code, s390_r13, ins->inst_offset);
4206 } else if (s390_is_imm32 (ins->inst_offset)) {
4207 s390_lgfi (code, s390_r13, ins->inst_offset);
4209 S390_SET (code, s390_r13, ins->inst_offset);
4211 s390_ear (code, s390_r1, 0);
4212 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4213 s390_ear (code, s390_r1, 1);
4214 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
4218 if (cfg->method->save_lmf)
4219 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4221 if (cfg->flags & MONO_CFG_HAS_TAIL) {
4222 code = emit_load_volatile_arguments (code, cfg);
4225 code = backUpStackPtr(cfg, code);
4226 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
4227 mono_add_patch_info (cfg, code - cfg->native_code,
4228 MONO_PATCH_INFO_METHOD_JUMP,
4230 s390_jcl (code, S390_CC_UN, 0);
4233 case OP_CHECK_THIS: {
4234 /* ensure ins->sreg1 is not NULL */
4235 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
4236 s390_ltgr (code, s390_r0, s390_r0);
4237 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4241 int offset = cfg->sig_cookie + cfg->stack_usage;
4243 if (s390_is_imm16 (offset)) {
4244 s390_lghi (code, s390_r0, offset);
4245 } else if (s390_is_imm32 (offset)) {
4246 s390_lgfi (code, s390_r0, offset);
4248 S390_SET (code, s390_r0, offset);
4250 s390_agr (code, s390_r0, cfg->frame_reg);
4251 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
4255 call = (MonoCallInst*)ins;
4256 if (ins->flags & MONO_INST_HAS_METHOD)
4257 mono_add_patch_info (cfg, code-cfg->native_code,
4258 MONO_PATCH_INFO_METHOD,
4261 mono_add_patch_info (cfg, code-cfg->native_code,
4262 MONO_PATCH_INFO_ABS,
4264 S390_CALL_TEMPLATE (code, s390_r14);
4265 if (call->signature->ret->type == MONO_TYPE_R4)
4266 s390_ldebr (code, s390_f0, s390_f0);
4274 call = (MonoCallInst*)ins;
4275 if (ins->flags & MONO_INST_HAS_METHOD)
4276 mono_add_patch_info (cfg, code-cfg->native_code,
4277 MONO_PATCH_INFO_METHOD,
4280 mono_add_patch_info (cfg, code-cfg->native_code,
4281 MONO_PATCH_INFO_ABS,
4283 S390_CALL_TEMPLATE (code, s390_r14);
4286 case OP_FCALL_REG: {
4287 call = (MonoCallInst*)ins;
4288 s390_lgr (code, s390_r1, ins->sreg1);
4289 s390_basr (code, s390_r14, s390_r1);
4290 if (call->signature->ret->type == MONO_TYPE_R4)
4291 s390_ldebr (code, s390_f0, s390_f0);
4297 case OP_VOIDCALL_REG:
4299 s390_lgr (code, s390_r1, ins->sreg1);
4300 s390_basr (code, s390_r14, s390_r1);
4303 case OP_FCALL_MEMBASE: {
4304 call = (MonoCallInst*)ins;
4305 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4306 s390_basr (code, s390_r14, s390_r1);
4307 if (call->signature->ret->type == MONO_TYPE_R4)
4308 s390_ldebr (code, s390_f0, s390_f0);
4311 case OP_LCALL_MEMBASE:
4312 case OP_VCALL_MEMBASE:
4313 case OP_VCALL2_MEMBASE:
4314 case OP_VOIDCALL_MEMBASE:
4315 case OP_CALL_MEMBASE: {
4316 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4317 s390_basr (code, s390_r14, s390_r1);
4324 if (cfg->param_area == 0)
4325 alloca_skip = S390_MINIMAL_STACK_SIZE;
4327 alloca_skip = cfg->param_area;
4329 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4330 s390_lgr (code, s390_r1, ins->sreg1);
4331 if (ins->flags & MONO_INST_INIT)
4332 s390_lgr (code, s390_r0, ins->sreg1);
4333 s390_aghi (code, s390_r1, 14);
4334 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4335 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4336 if (cfg->method->save_lmf) {
4337 /*----------------------------------*/
4338 /* we have to adjust lmf ebp value */
4339 /*----------------------------------*/
4340 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4342 s390_lgr (code, s390_r13, cfg->frame_reg);
4343 if (s390_is_imm16(lmfOffset)) {
4344 s390_aghi (code, s390_r13, lmfOffset);
4345 } else if (s390_is_imm32(lmfOffset)) {
4346 s390_agfi (code, s390_r13, lmfOffset);
4348 S390_SET (code, s390_r13, lmfOffset);
4350 s390_lgr (code, s390_r14, STK_BASE);
4351 s390_sgr (code, s390_r14, s390_r1);
4352 s390_stg (code, s390_r14, 0, s390_r13,
4353 G_STRUCT_OFFSET(MonoLMF, ebp));
4355 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4356 s390_sgr (code, STK_BASE, s390_r1);
4357 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4358 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4359 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4360 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4361 if (ins->flags & MONO_INST_INIT) {
4362 s390_lgr (code, s390_r1, s390_r0);
4363 s390_lgr (code, s390_r0, ins->dreg);
4364 s390_lgr (code, s390_r14, s390_r12);
4365 s390_lghi (code, s390_r13, 0);
4366 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4368 s390_lgr (code, s390_r12, s390_r14);
4373 s390_lgr (code, s390_r2, ins->sreg1);
4374 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4375 (gpointer) "mono_arch_throw_exception");
4376 S390_CALL_TEMPLATE(code, s390_r14);
4380 s390_lgr (code, s390_r2, ins->sreg1);
4381 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4382 (gpointer) "mono_arch_rethrow_exception");
4383 S390_CALL_TEMPLATE(code, s390_r14);
4386 case OP_START_HANDLER: {
4387 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4389 S390_LONG (code, stg, stg, s390_r14, 0,
4390 spvar->inst_basereg,
4391 spvar->inst_offset);
4394 case OP_ENDFILTER: {
4395 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4397 if (ins->sreg1 != s390_r2)
4398 s390_lgr(code, s390_r2, ins->sreg1);
4399 S390_LONG (code, lg, lg, s390_r14, 0,
4400 spvar->inst_basereg,
4401 spvar->inst_offset);
4402 s390_br (code, s390_r14);
4405 case OP_ENDFINALLY: {
4406 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4408 S390_LONG (code, lg, lg, s390_r14, 0,
4409 spvar->inst_basereg,
4410 spvar->inst_offset);
4411 s390_br (code, s390_r14);
4414 case OP_CALL_HANDLER: {
4415 mono_add_patch_info (cfg, code-cfg->native_code,
4416 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4417 s390_brasl (code, s390_r14, 0);
4418 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4422 ins->inst_c0 = code - cfg->native_code;
4425 case OP_RELAXED_NOP:
4428 case OP_DUMMY_STORE:
4429 case OP_NOT_REACHED:
4433 case OP_IL_SEQ_POINT:
4434 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4436 case OP_SEQ_POINT: {
4439 if (cfg->compile_aot)
4443 * Read from the single stepping trigger page. This will cause a
4444 * SIGSEGV when single stepping is enabled.
4445 * We do this _before_ the breakpoint, so single stepping after
4446 * a breakpoint is hit will step to the next IL offset.
4448 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4449 breakpointCode.pTrigger = ss_trigger_page;
4450 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4451 code += BREAKPOINT_SIZE;
4454 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4457 * A placeholder for a possible breakpoint inserted by
4458 * mono_arch_set_breakpoint ().
4460 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4464 * Add an additional nop so skipping the bp doesn't cause the ip to point
4465 * to another IL offset.
4471 case OP_GENERIC_CLASS_INIT: {
4472 static int byte_offset = -1;
4473 static guint8 bitmask;
4476 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4478 if (byte_offset < 0)
4479 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4481 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4482 s390_jo (code, 0); CODEPTR(code, jump);
4484 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4485 "mono_generic_class_init");
4486 S390_CALL_TEMPLATE(code, s390_r14);
4488 PTRSLOT (code, jump);
4490 ins->flags |= MONO_INST_GC_CALLSITE;
4491 ins->backend.pc_offset = code - cfg->native_code;
4495 EMIT_UNCOND_BRANCH(ins);
4498 s390_br (code, ins->sreg1);
4504 s390_lghi(code, ins->dreg, 1);
4506 s390_lghi(code, ins->dreg, 0);
4512 s390_lghi(code, ins->dreg, 1);
4514 s390_lghi(code, ins->dreg, 0);
4520 s390_lghi(code, ins->dreg, 1);
4522 s390_lghi(code, ins->dreg, 0);
4528 s390_lghi(code, ins->dreg, 1);
4530 s390_lghi(code, ins->dreg, 0);
4536 s390_lghi(code, ins->dreg, 1);
4538 s390_lghi(code, ins->dreg, 0);
4542 s390_lghi(code, ins->dreg, 1);
4544 s390_lghi(code, ins->dreg, 0);
4548 s390_lghi(code, ins->dreg, 1);
4550 s390_lghi(code, ins->dreg, 0);
4554 s390_lghi(code, ins->dreg, 1);
4556 s390_lghi(code, ins->dreg, 0);
4560 s390_lghi(code, ins->dreg, 1);
4562 s390_lghi(code, ins->dreg, 0);
4566 s390_lghi(code, ins->dreg, 1);
4568 s390_lghi(code, ins->dreg, 0);
4571 case OP_COND_EXC_EQ:
4572 case OP_COND_EXC_IEQ:
4573 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4575 case OP_COND_EXC_NE_UN:
4576 case OP_COND_EXC_INE_UN:
4577 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4579 case OP_COND_EXC_LT:
4580 case OP_COND_EXC_ILT:
4581 case OP_COND_EXC_LT_UN:
4582 case OP_COND_EXC_ILT_UN:
4583 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4585 case OP_COND_EXC_GT:
4586 case OP_COND_EXC_IGT:
4587 case OP_COND_EXC_GT_UN:
4588 case OP_COND_EXC_IGT_UN:
4589 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4591 case OP_COND_EXC_GE:
4592 case OP_COND_EXC_IGE:
4593 case OP_COND_EXC_GE_UN:
4594 case OP_COND_EXC_IGE_UN:
4595 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4597 case OP_COND_EXC_LE:
4598 case OP_COND_EXC_ILE:
4599 case OP_COND_EXC_LE_UN:
4600 case OP_COND_EXC_ILE_UN:
4601 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4603 case OP_COND_EXC_OV:
4604 case OP_COND_EXC_IOV:
4605 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4607 case OP_COND_EXC_NO:
4608 case OP_COND_EXC_INO:
4609 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4612 case OP_COND_EXC_IC:
4613 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4615 case OP_COND_EXC_NC:
4616 case OP_COND_EXC_INC:
4617 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4621 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4625 EMIT_COND_BRANCH (ins, S390_CC_NE);
4631 EMIT_COND_BRANCH (ins, S390_CC_LT);
4637 EMIT_COND_BRANCH (ins, S390_CC_GT);
4643 EMIT_COND_BRANCH (ins, S390_CC_GE);
4649 EMIT_COND_BRANCH (ins, S390_CC_LE);
4653 EMIT_COMP_AND_BRANCH(ins, crj, cr);
4657 EMIT_COMP_AND_BRANCH(ins, clrj, clr);
4661 EMIT_COMP_AND_BRANCH(ins, cgrj, cgr);
4665 EMIT_COMP_AND_BRANCH(ins, clgrj, clgr);
4669 EMIT_COMP_AND_BRANCH_IMM(ins, crj, cr, ltr, FALSE);
4673 EMIT_COMP_AND_BRANCH_IMM(ins, clrj, clr, ltr, TRUE);
4677 EMIT_COMP_AND_BRANCH_IMM(ins, cgrj, cgr, ltgr, FALSE);
4681 EMIT_COMP_AND_BRANCH_IMM(ins, clgrj, clgr, ltgr, TRUE);
4684 /* floating point opcodes */
4686 if (*((double *) ins->inst_p0) == 0) {
4687 s390_lzdr (code, ins->dreg);
4689 S390_SET (code, s390_r13, ins->inst_p0);
4690 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4695 if (*((float *) ins->inst_p0) == 0) {
4696 s390_lzdr (code, ins->dreg);
4698 S390_SET (code, s390_r13, ins->inst_p0);
4699 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4703 case OP_STORER8_MEMBASE_REG: {
4704 S390_LONG (code, stdy, std, ins->sreg1, 0,
4705 ins->inst_destbasereg, ins->inst_offset);
4708 case OP_LOADR8_MEMBASE: {
4709 S390_LONG (code, ldy, ld, ins->dreg, 0,
4710 ins->inst_basereg, ins->inst_offset);
4713 case OP_STORER4_MEMBASE_REG: {
4714 s390_ledbr (code, s390_f15, ins->sreg1);
4715 S390_LONG (code, stey, ste, s390_f15, 0,
4716 ins->inst_destbasereg, ins->inst_offset);
4719 case OP_LOADR4_MEMBASE: {
4720 S390_LONG (code, ley, le, s390_f15, 0,
4721 ins->inst_basereg, ins->inst_offset);
4722 s390_ldebr (code, ins->dreg, s390_f15);
4725 case OP_ICONV_TO_R_UN: {
4726 if (mono_hwcap_s390x_has_fpe) {
4727 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4729 s390_llgfr (code, s390_r0, ins->sreg1);
4730 s390_cdgbr (code, ins->dreg, s390_r0);
4734 case OP_LCONV_TO_R_UN: {
4735 if (mono_hwcap_s390x_has_fpe) {
4736 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4739 s390_cxgbr (code, s390_f12, ins->sreg1);
4740 s390_ltgr (code, ins->sreg1, ins->sreg1);
4741 s390_jnl (code, 0); CODEPTR(code, jump);
4742 S390_SET (code, s390_r13, 0x403f000000000000llu);
4743 s390_lgdr (code, s390_f13, s390_r13);
4744 s390_lzdr (code, s390_f15);
4745 s390_axbr (code, s390_f12, s390_f13);
4746 PTRSLOT(code, jump);
4747 s390_ldxbr (code, s390_f13, s390_f12);
4748 s390_ldr (code, ins->dreg, s390_f13);
4752 case OP_LCONV_TO_R4:
4753 case OP_ICONV_TO_R4: {
4754 s390_cegbr (code, ins->dreg, ins->sreg1);
4755 s390_ldebr (code, ins->dreg, ins->dreg);
4758 case OP_LCONV_TO_R8:
4759 case OP_ICONV_TO_R8: {
4760 s390_cdgbr (code, ins->dreg, ins->sreg1);
4763 case OP_FCONV_TO_I1:
4764 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4765 s390_ltgr (code, ins->dreg, ins->dreg);
4767 s390_oill (code, ins->dreg, 0x80);
4768 s390_lghi (code, s390_r0, 0xff);
4769 s390_ngr (code, ins->dreg, s390_r0);
4771 case OP_FCONV_TO_U1:
4772 if (mono_hwcap_s390x_has_fpe) {
4773 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4774 s390_lghi (code, s390_r0, 0xff);
4775 s390_ngr (code, ins->dreg, s390_r0);
4777 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4780 case OP_FCONV_TO_I2:
4781 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4782 s390_ltgr (code, ins->dreg, ins->dreg);
4784 s390_oill (code, ins->dreg, 0x8000);
4785 s390_llill (code, s390_r0, 0xffff);
4786 s390_ngr (code, ins->dreg, s390_r0);
4788 case OP_FCONV_TO_U2:
4789 if (mono_hwcap_s390x_has_fpe) {
4790 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4791 s390_llill (code, s390_r0, 0xffff);
4792 s390_ngr (code, ins->dreg, s390_r0);
4794 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4797 case OP_FCONV_TO_I4:
4799 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4801 case OP_FCONV_TO_U4:
4803 if (mono_hwcap_s390x_has_fpe) {
4804 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4806 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4809 case OP_FCONV_TO_I8:
4810 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4812 case OP_FCONV_TO_U8:
4813 if (mono_hwcap_s390x_has_fpe) {
4814 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4816 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4819 case OP_LCONV_TO_OVF_I: {
4820 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4822 s390_ltgr (code, ins->sreg2, ins->sreg2);
4823 s390_jnl (code, 0); CODEPTR(code, o[0]);
4824 s390_ltgr (code, ins->sreg1, ins->sreg1);
4825 s390_jnl (code, 0); CODEPTR(code, o[1]);
4826 s390_lhi (code, s390_r13, -1);
4827 s390_cgr (code, ins->sreg1, s390_r13);
4828 s390_jnz (code, 0); CODEPTR(code, o[2]);
4829 if (ins->dreg != ins->sreg2)
4830 s390_lgr (code, ins->dreg, ins->sreg2);
4831 s390_j (code, 0); CODEPTR(code, o[3]);
4832 PTRSLOT(code, o[0]);
4833 s390_jz (code, 0); CODEPTR(code, o[4]);
4834 PTRSLOT(code, o[1]);
4835 PTRSLOT(code, o[2]);
4836 mono_add_patch_info (cfg, code - cfg->native_code,
4837 MONO_PATCH_INFO_EXC, "OverflowException");
4838 s390_brasl (code, s390_r14, 0);
4839 PTRSLOT(code, o[3]);
4840 PTRSLOT(code, o[4]);
4844 s390_lpdbr (code, ins->dreg, ins->sreg1);
4848 s390_sqdbr (code, ins->dreg, ins->sreg1);
4853 s390_adbr (code, ins->dreg, src2);
4857 CHECK_SRCDST_NCOM_F;
4858 s390_sdbr (code, ins->dreg, src2);
4863 s390_mdbr (code, ins->dreg, src2);
4867 CHECK_SRCDST_NCOM_F;
4868 s390_ddbr (code, ins->dreg, src2);
4872 s390_lcdbr (code, ins->dreg, ins->sreg1);
4876 CHECK_SRCDST_NCOM_F;
4877 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4881 s390_cdbr (code, ins->sreg1, ins->sreg2);
4885 s390_cdbr (code, ins->sreg1, ins->sreg2);
4886 s390_lghi (code, ins->dreg, 1);
4888 s390_lghi (code, ins->dreg, 0);
4892 s390_cdbr (code, ins->sreg1, ins->sreg2);
4893 s390_lghi (code, ins->dreg, 1);
4895 s390_lghi (code, ins->dreg, 0);
4899 s390_cdbr (code, ins->sreg1, ins->sreg2);
4900 s390_lghi (code, ins->dreg, 1);
4902 s390_lghi (code, ins->dreg, 0);
4906 s390_cdbr (code, ins->sreg1, ins->sreg2);
4907 s390_lghi (code, ins->dreg, 1);
4909 s390_lghi (code, ins->dreg, 0);
4913 s390_cdbr (code, ins->sreg1, ins->sreg2);
4914 s390_lghi (code, ins->dreg, 1);
4916 s390_lghi (code, ins->dreg, 0);
4920 s390_cdbr (code, ins->sreg1, ins->sreg2);
4921 s390_lghi (code, ins->dreg, 1);
4923 s390_lghi (code, ins->dreg, 0);
4927 s390_cdbr (code, ins->sreg1, ins->sreg2);
4928 s390_lghi (code, ins->dreg, 1);
4930 s390_lghi (code, ins->dreg, 0);
4934 s390_cdbr (code, ins->sreg1, ins->sreg2);
4935 s390_lghi (code, ins->dreg, 1);
4937 s390_lghi (code, ins->dreg, 0);
4942 s390_jo (code, 0); CODEPTR(code, o);
4943 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4948 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4952 s390_jo (code, 0); CODEPTR(code, o);
4953 EMIT_COND_BRANCH (ins, S390_CC_LT);
4958 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4962 s390_jo (code, 0); CODEPTR(code, o);
4963 EMIT_COND_BRANCH (ins, S390_CC_GT);
4968 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4972 s390_jo (code, 0); CODEPTR(code, o);
4973 EMIT_COND_BRANCH (ins, S390_CC_GE);
4978 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4982 s390_jo (code, 0); CODEPTR(code, o);
4983 EMIT_COND_BRANCH (ins, S390_CC_LE);
4988 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4992 s390_lhi (code, s390_r13, 0x7f);
4993 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4994 s390_jz (code, 0); CODEPTR(code, o);
4995 mono_add_patch_info (cfg, code - cfg->native_code,
4996 MONO_PATCH_INFO_EXC, "OverflowException");
4997 s390_brasl (code, s390_r14,0);
5001 case OP_S390_MOVE: {
5002 if (ins->backend.size > 0) {
5003 if (ins->backend.size <= 256) {
5004 s390_mvc (code, ins->backend.size, ins->dreg,
5005 ins->inst_offset, ins->sreg1, ins->inst_imm);
5007 s390_lgr (code, s390_r0, ins->dreg);
5008 if (ins->inst_offset > 0) {
5009 if (s390_is_imm16 (ins->inst_offset)) {
5010 s390_aghi (code, s390_r0, ins->inst_offset);
5011 } else if (s390_is_imm32 (ins->inst_offset)) {
5012 s390_agfi (code, s390_r0, ins->inst_offset);
5014 S390_SET (code, s390_r13, ins->inst_offset);
5015 s390_agr (code, s390_r0, s390_r13);
5018 s390_lgr (code, s390_r12, ins->sreg1);
5019 if (ins->inst_imm > 0) {
5020 if (s390_is_imm16 (ins->inst_imm)) {
5021 s390_aghi (code, s390_r12, ins->inst_imm);
5022 } else if (s390_is_imm32 (ins->inst_imm)) {
5023 s390_agfi (code, s390_r12, ins->inst_imm);
5025 S390_SET (code, s390_r13, ins->inst_imm);
5026 s390_agr (code, s390_r12, s390_r13);
5029 if (s390_is_imm16 (ins->backend.size)) {
5030 s390_lghi (code, s390_r1, ins->backend.size);
5031 } else if (s390_is_imm32 (ins->inst_offset)) {
5032 s390_agfi (code, s390_r1, ins->backend.size);
5034 S390_SET (code, s390_r13, ins->backend.size);
5035 s390_agr (code, s390_r1, s390_r13);
5037 s390_lgr (code, s390_r13, s390_r1);
5038 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
5044 case OP_ATOMIC_ADD_I8: {
5045 if (mono_hwcap_s390x_has_ia) {
5046 s390_laag (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5047 s390_agr (code, ins->dreg, ins->sreg2);
5049 s390_lgr (code, s390_r1, ins->sreg2);
5050 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5051 s390_agr (code, s390_r1, s390_r0);
5052 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5053 s390_jnz (code, -10);
5054 s390_lgr (code, ins->dreg, s390_r1);
5058 case OP_ATOMIC_EXCHANGE_I8: {
5059 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5060 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5061 s390_jnz (code, -6);
5062 s390_lgr (code, ins->dreg, s390_r0);
5065 case OP_ATOMIC_ADD_I4: {
5066 if (mono_hwcap_s390x_has_ia) {
5067 s390_laa (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5068 s390_ar (code, ins->dreg, ins->sreg2);
5070 s390_lgfr(code, s390_r1, ins->sreg2);
5071 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5072 s390_agr (code, s390_r1, s390_r0);
5073 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5074 s390_jnz (code, -9);
5075 s390_lgfr(code, ins->dreg, s390_r1);
5079 case OP_ATOMIC_EXCHANGE_I4: {
5080 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5081 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5082 s390_jnz (code, -4);
5083 s390_lgfr(code, ins->dreg, s390_r0);
5086 case OP_S390_BKCHAIN: {
5087 s390_lgr (code, ins->dreg, ins->sreg1);
5088 if (s390_is_imm16 (cfg->stack_offset)) {
5089 s390_aghi (code, ins->dreg, cfg->stack_offset);
5090 } else if (s390_is_imm32 (cfg->stack_offset)) {
5091 s390_agfi (code, ins->dreg, cfg->stack_offset);
5093 S390_SET (code, s390_r13, cfg->stack_offset);
5094 s390_agr (code, ins->dreg, s390_r13);
5098 case OP_MEMORY_BARRIER:
5101 case OP_GC_SAFE_POINT: {
5104 g_assert (mono_threads_is_coop_enabled ());
5106 s390_ltg (code, s390_r0, 0, ins->sreg1, 0);
5107 s390_jz (code, 0); CODEPTR(code, br);
5108 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
5109 mono_threads_state_poll);
5110 S390_CALL_TEMPLATE (code, s390_r14);
5114 case OP_GC_LIVENESS_DEF:
5115 case OP_GC_LIVENESS_USE:
5116 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
5117 ins->backend.pc_offset = code - cfg->native_code;
5119 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
5120 ins->backend.pc_offset = code - cfg->native_code;
5121 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
5123 #ifdef MONO_ARCH_SIMD_INTRINSICS
5125 s390x_addps (code, ins->sreg1, ins->sreg2);
5128 s390x_divps (code, ins->sreg1, ins->sreg2);
5131 s390x_mulps (code, ins->sreg1, ins->sreg2);
5134 s390x_subps (code, ins->sreg1, ins->sreg2);
5137 s390x_maxps (code, ins->sreg1, ins->sreg2);
5140 s390x_minps (code, ins->sreg1, ins->sreg2);
5143 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5144 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5147 s390x_andps (code, ins->sreg1, ins->sreg2);
5150 s390x_andnps (code, ins->sreg1, ins->sreg2);
5153 s390x_orps (code, ins->sreg1, ins->sreg2);
5156 s390x_xorps (code, ins->sreg1, ins->sreg2);
5159 s390x_sqrtps (code, ins->dreg, ins->sreg1);
5162 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
5165 s390x_rcpps (code, ins->dreg, ins->sreg1);
5168 s390x_addsubps (code, ins->sreg1, ins->sreg2);
5171 s390x_haddps (code, ins->sreg1, ins->sreg2);
5174 s390x_hsubps (code, ins->sreg1, ins->sreg2);
5177 s390x_movshdup (code, ins->dreg, ins->sreg1);
5180 s390x_movsldup (code, ins->dreg, ins->sreg1);
5183 case OP_PSHUFLEW_HIGH:
5184 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5185 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5187 case OP_PSHUFLEW_LOW:
5188 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5189 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5192 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5193 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5196 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5197 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5200 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
5201 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5205 s390x_addpd (code, ins->sreg1, ins->sreg2);
5208 s390x_divpd (code, ins->sreg1, ins->sreg2);
5211 s390x_mulpd (code, ins->sreg1, ins->sreg2);
5214 s390x_subpd (code, ins->sreg1, ins->sreg2);
5217 s390x_maxpd (code, ins->sreg1, ins->sreg2);
5220 s390x_minpd (code, ins->sreg1, ins->sreg2);
5223 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5224 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5227 s390x_andpd (code, ins->sreg1, ins->sreg2);
5230 s390x_andnpd (code, ins->sreg1, ins->sreg2);
5233 s390x_orpd (code, ins->sreg1, ins->sreg2);
5236 s390x_xorpd (code, ins->sreg1, ins->sreg2);
5239 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
5242 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
5245 s390x_haddpd (code, ins->sreg1, ins->sreg2);
5248 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
5251 s390x_movddup (code, ins->dreg, ins->sreg1);
5254 case OP_EXTRACT_MASK:
5255 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
5259 s390x_pand (code, ins->sreg1, ins->sreg2);
5262 s390x_por (code, ins->sreg1, ins->sreg2);
5265 s390x_pxor (code, ins->sreg1, ins->sreg2);
5269 s390x_paddb (code, ins->sreg1, ins->sreg2);
5272 s390x_paddw (code, ins->sreg1, ins->sreg2);
5275 s390x_paddd (code, ins->sreg1, ins->sreg2);
5278 s390x_paddq (code, ins->sreg1, ins->sreg2);
5282 s390x_psubb (code, ins->sreg1, ins->sreg2);
5285 s390x_psubw (code, ins->sreg1, ins->sreg2);
5288 s390x_psubd (code, ins->sreg1, ins->sreg2);
5291 s390x_psubq (code, ins->sreg1, ins->sreg2);
5295 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
5298 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
5301 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
5305 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
5308 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
5311 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
5315 s390x_pavgb (code, ins->sreg1, ins->sreg2);
5318 s390x_pavgw (code, ins->sreg1, ins->sreg2);
5322 s390x_pminub (code, ins->sreg1, ins->sreg2);
5325 s390x_pminuw (code, ins->sreg1, ins->sreg2);
5328 s390x_pminud (code, ins->sreg1, ins->sreg2);
5332 s390x_pminsb (code, ins->sreg1, ins->sreg2);
5335 s390x_pminsw (code, ins->sreg1, ins->sreg2);
5338 s390x_pminsd (code, ins->sreg1, ins->sreg2);
5342 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
5345 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
5348 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
5351 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
5355 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
5358 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5361 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5364 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5367 case OP_PSUM_ABS_DIFF:
5368 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5371 case OP_UNPACK_LOWB:
5372 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5374 case OP_UNPACK_LOWW:
5375 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5377 case OP_UNPACK_LOWD:
5378 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5380 case OP_UNPACK_LOWQ:
5381 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5383 case OP_UNPACK_LOWPS:
5384 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5386 case OP_UNPACK_LOWPD:
5387 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5390 case OP_UNPACK_HIGHB:
5391 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5393 case OP_UNPACK_HIGHW:
5394 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5396 case OP_UNPACK_HIGHD:
5397 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5399 case OP_UNPACK_HIGHQ:
5400 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5402 case OP_UNPACK_HIGHPS:
5403 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5405 case OP_UNPACK_HIGHPD:
5406 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5410 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5413 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5416 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5419 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5422 case OP_PADDB_SAT_UN:
5423 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5425 case OP_PSUBB_SAT_UN:
5426 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5428 case OP_PADDW_SAT_UN:
5429 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5431 case OP_PSUBW_SAT_UN:
5432 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5436 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5439 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5442 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5445 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5449 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5452 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5455 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5457 case OP_PMULW_HIGH_UN:
5458 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5461 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5465 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5468 s390x_psrlw (code, ins->dreg, ins->sreg2);
5472 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5475 s390x_psraw (code, ins->dreg, ins->sreg2);
5479 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5482 s390x_psllw (code, ins->dreg, ins->sreg2);
5486 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5489 s390x_psrld (code, ins->dreg, ins->sreg2);
5493 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5496 s390x_psrad (code, ins->dreg, ins->sreg2);
5500 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5503 s390x_pslld (code, ins->dreg, ins->sreg2);
5507 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5510 s390x_psrlq (code, ins->dreg, ins->sreg2);
5513 /*TODO: This is appart of the sse spec but not added
5515 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5518 s390x_psraq (code, ins->dreg, ins->sreg2);
5523 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5526 s390x_psllq (code, ins->dreg, ins->sreg2);
5529 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5532 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5535 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5538 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5541 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5544 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5547 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5550 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5554 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5557 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5561 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5562 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5564 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5569 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5571 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5572 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5576 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5578 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5579 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5580 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5584 amd64_movhlps (code, ins->dreg, ins->sreg1);
5586 s390x_movsd (code, ins->dreg, ins->sreg1);
5589 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5591 case OP_EXTRACTX_U2:
5592 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5594 case OP_INSERTX_U1_SLOW:
5595 /*sreg1 is the extracted ireg (scratch)
5596 /sreg2 is the to be inserted ireg (scratch)
5597 /dreg is the xreg to receive the value*/
5599 /*clear the bits from the extracted word*/
5600 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5601 /*shift the value to insert if needed*/
5602 if (ins->inst_c0 & 1)
5603 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5604 /*join them together*/
5605 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5606 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5608 case OP_INSERTX_I4_SLOW:
5609 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5610 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5611 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5613 case OP_INSERTX_I8_SLOW:
5614 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5616 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5618 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5621 case OP_INSERTX_R4_SLOW:
5622 switch (ins->inst_c0) {
5625 s390x_movss (code, ins->dreg, ins->sreg2);
5627 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5630 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5632 s390x_movss (code, ins->dreg, ins->sreg2);
5634 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5635 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5638 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5640 s390x_movss (code, ins->dreg, ins->sreg2);
5642 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5643 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5646 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5648 s390x_movss (code, ins->dreg, ins->sreg2);
5650 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5651 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5655 case OP_INSERTX_R8_SLOW:
5657 amd64_movlhps (code, ins->dreg, ins->sreg2);
5659 s390x_movsd (code, ins->dreg, ins->sreg2);
5661 case OP_STOREX_MEMBASE_REG:
5662 case OP_STOREX_MEMBASE:
5663 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5665 case OP_LOADX_MEMBASE:
5666 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5668 case OP_LOADX_ALIGNED_MEMBASE:
5669 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5671 case OP_STOREX_ALIGNED_MEMBASE_REG:
5672 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5674 case OP_STOREX_NTA_MEMBASE_REG:
5675 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5677 case OP_PREFETCH_MEMBASE:
5678 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5682 /*FIXME the peephole pass should have killed this*/
5683 if (ins->dreg != ins->sreg1)
5684 s390x_movaps (code, ins->dreg, ins->sreg1);
5687 s390x_pxor (code, ins->dreg, ins->dreg);
5689 case OP_ICONV_TO_R4_RAW:
5690 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5693 case OP_FCONV_TO_R8_X:
5694 s390x_movsd (code, ins->dreg, ins->sreg1);
5697 case OP_XCONV_R8_TO_I4:
5698 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5699 switch (ins->backend.source_opcode) {
5700 case OP_FCONV_TO_I1:
5701 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5703 case OP_FCONV_TO_U1:
5704 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5706 case OP_FCONV_TO_I2:
5707 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5709 case OP_FCONV_TO_U2:
5710 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5716 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5717 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5718 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5721 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5722 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5725 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5726 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5730 s390x_movsd (code, ins->dreg, ins->sreg1);
5732 s390x_movsd (code, ins->dreg, ins->sreg1);
5733 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5735 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5738 s390x_movsd (code, ins->dreg, ins->sreg1);
5739 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5743 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5744 g_assert_not_reached ();
5747 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5748 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5749 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5750 g_assert_not_reached ();
5753 last_offset = offset;
5756 cfg->code_len = code - cfg->native_code;
5759 /*========================= End of Function ========================*/
5761 /*------------------------------------------------------------------*/
5763 /* Name - mono_arch_register_lowlevel_calls */
5765 /* Function - Register routines to help with --trace operation. */
5767 /*------------------------------------------------------------------*/
5770 mono_arch_register_lowlevel_calls (void)
5774 /*========================= End of Function ========================*/
5776 /*------------------------------------------------------------------*/
5778 /* Name - mono_arch_patch_code */
5780 /* Function - Process the patch data created during the */
5781 /* instruction build process. This resolves jumps, */
5782 /* calls, variables etc. */
5784 /*------------------------------------------------------------------*/
5787 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5788 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5791 MonoJumpInfo *patch_info;
5795 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5796 unsigned char *ip = patch_info->ip.i + code;
5797 gconstpointer target = NULL;
5799 target = mono_resolve_patch_target (method, domain, code,
5800 patch_info, run_cctors, error);
5801 return_if_nok (error);
5803 switch (patch_info->type) {
5804 case MONO_PATCH_INFO_IP:
5805 case MONO_PATCH_INFO_LDSTR:
5806 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5807 case MONO_PATCH_INFO_LDTOKEN:
5808 case MONO_PATCH_INFO_EXC:
5809 s390_patch_addr (ip, (guint64) target);
5811 case MONO_PATCH_INFO_METHOD:
5812 case MONO_PATCH_INFO_INTERNAL_METHOD:
5813 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5814 case MONO_PATCH_INFO_RGCTX_FETCH:
5815 case MONO_PATCH_INFO_ABS: {
5816 S390_EMIT_CALL (ip, target);
5819 case MONO_PATCH_INFO_SWITCH:
5820 /*----------------------------------*/
5821 /* ip points at the basr r13,0/j +4 */
5822 /* instruction the vtable value */
5823 /* follows this (i.e. ip+6) */
5824 /*----------------------------------*/
5825 S390_EMIT_LOAD (ip, target);
5827 case MONO_PATCH_INFO_METHODCONST:
5828 case MONO_PATCH_INFO_CLASS:
5829 case MONO_PATCH_INFO_IMAGE:
5830 case MONO_PATCH_INFO_FIELD:
5831 case MONO_PATCH_INFO_IID:
5832 case MONO_PATCH_INFO_EXC_NAME:
5833 target = S390_RELATIVE(target, ip);
5834 s390_patch_rel (ip, (guint64) target);
5836 case MONO_PATCH_INFO_R4:
5837 case MONO_PATCH_INFO_R8:
5838 case MONO_PATCH_INFO_METHOD_REL:
5839 g_assert_not_reached ();
5842 target = S390_RELATIVE(target, ip);
5844 s390_patch_rel (ip, (guint64) target);
5849 /*========================= End of Function ========================*/
5851 /*------------------------------------------------------------------*/
5853 /* Name - emit_load_volatile_arguments */
5855 /* Function - Emit the instructions to reload parameter regist- */
5856 /* registers for use with "tail" operations. */
5858 /* The register loading operations performed here */
5859 /* are the mirror of the store operations performed */
5860 /* in mono_arch_emit_prolog and need to be kept in */
5861 /* synchronization with it. */
5863 /*------------------------------------------------------------------*/
5866 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5869 MonoMethod *method = cfg->method;
5870 MonoMethodSignature *sig = mono_method_signature(method);
5874 cinfo = get_call_info (NULL, NULL, sig);
5876 if (cinfo->struct_ret) {
5877 ArgInfo *ainfo = &cinfo->ret;
5878 inst = cfg->vret_addr;
5879 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5882 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5883 ArgInfo *ainfo = cinfo->args + i;
5884 inst = cfg->args [pos];
5886 if (inst->opcode == OP_REGVAR) {
5887 if (ainfo->regtype == RegTypeGeneral)
5888 s390_lgr (code, ainfo->reg, inst->dreg);
5889 else if (ainfo->regtype == RegTypeFP) {
5890 if (inst->dreg != ainfo->reg) {
5891 if (ainfo->size == 4) {
5892 s390_ldebr (code, ainfo->reg, inst->dreg);
5894 s390_ldr (code, ainfo->reg, inst->dreg);
5898 else if (ainfo->regtype == RegTypeBase) {
5900 g_assert_not_reached ();
5902 if (ainfo->regtype == RegTypeGeneral) {
5903 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5904 g_assert_not_reached();
5905 switch (ainfo->size) {
5907 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5910 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5913 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5916 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5919 } else if (ainfo->regtype == RegTypeBase) {
5920 } else if (ainfo->regtype == RegTypeFP) {
5921 if (ainfo->size == 8)
5922 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5923 else if (ainfo->size == 4)
5924 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5926 g_assert_not_reached ();
5927 } else if (ainfo->regtype == RegTypeStructByVal) {
5928 if (ainfo->reg != STK_BASE) {
5929 switch (ainfo->size) {
5931 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5934 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5937 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5940 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5944 } else if (ainfo->regtype == RegTypeStructByAddr) {
5945 if (ainfo->reg != STK_BASE) {
5946 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5949 g_assert_not_reached ();
5957 /*========================= End of Function ========================*/
5959 /*------------------------------------------------------------------*/
5961 /* Name - mono_arch_emit_prolog */
5963 /* Function - Create the instruction sequence for a function */
5966 /*------------------------------------------------------------------*/
5969 mono_arch_emit_prolog (MonoCompile *cfg)
5971 MonoMethod *method = cfg->method;
5973 MonoMethodSignature *sig;
5975 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5984 cfg->code_size = 512;
5986 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5988 cfg->code_size += 256;
5991 if (method->save_lmf)
5992 cfg->code_size += 200;
5994 cfg->native_code = code = g_malloc (cfg->code_size);
5996 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5997 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5998 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5999 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
6000 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
6003 if ((strcmp(method->klass->name, "Tests") == 0) &&
6004 (strcmp(method->name,"test_5_jmp") == 0)) {
6005 printf("Found!\n"); fflush(stdout);
6010 if (cfg->arch.bkchain_reg != -1)
6011 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
6013 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6014 cfg->used_int_regs |= 1 << 11;
6017 alloc_size = cfg->stack_offset;
6019 cfg->stack_usage = cfa_offset = alloc_size;
6020 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
6021 s390_lgr (code, s390_r11, STK_BASE);
6022 if (s390_is_imm16 (alloc_size)) {
6023 s390_aghi (code, STK_BASE, -alloc_size);
6024 } else if (s390_is_imm32 (alloc_size)) {
6025 s390_agfi (code, STK_BASE, -alloc_size);
6027 int stackSize = alloc_size;
6028 while (stackSize > INT_MAX) {
6029 s390_agfi (code, STK_BASE, -INT_MAX);
6030 stackSize -= INT_MAX;
6032 s390_agfi (code, STK_BASE, -stackSize);
6034 s390_stg (code, s390_r11, 0, STK_BASE, 0);
6036 if (cfg->frame_reg != STK_BASE)
6037 s390_lgr (code, s390_r11, STK_BASE);
6039 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
6041 /* store runtime generic context */
6042 if (cfg->rgctx_var) {
6043 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
6045 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
6046 cfg->rgctx_var->inst_basereg,
6047 cfg->rgctx_var->inst_offset);
6050 /* compute max_offset in order to use short forward jumps
6051 * we always do it on s390 because the immediate displacement
6052 * for jumps is too small
6055 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6057 bb->max_offset = max_offset;
6059 MONO_BB_FOR_EACH_INS (bb, ins)
6060 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
6063 /* load arguments allocated to register from the stack */
6064 sig = mono_method_signature (method);
6067 cinfo = get_call_info (cfg, cfg->mempool, sig);
6069 if (cinfo->struct_ret) {
6070 ArgInfo *ainfo = &cinfo->ret;
6071 inst = cfg->vret_addr;
6072 inst->backend.size = ainfo->vtsize;
6073 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6076 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6077 ArgInfo *ainfo = cinfo->args + i;
6078 inst = cfg->args [pos];
6080 if (inst->opcode == OP_VTARG_ADDR)
6081 inst = inst->inst_left;
6083 if (inst->opcode == OP_REGVAR) {
6084 if (ainfo->regtype == RegTypeGeneral)
6085 s390_lgr (code, inst->dreg, ainfo->reg);
6086 else if (ainfo->regtype == RegTypeFP) {
6087 if (inst->dreg != ainfo->reg) {
6088 if (ainfo->size == 4) {
6089 s390_ledbr (code, inst->dreg, ainfo->reg);
6091 s390_ldr (code, inst->dreg, ainfo->reg);
6095 else if (ainfo->regtype == RegTypeBase) {
6096 s390_lgr (code, s390_r13, STK_BASE);
6097 s390_aghi (code, s390_r13, alloc_size);
6098 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
6100 g_assert_not_reached ();
6102 if (cfg->verbose_level > 2)
6103 g_print ("Argument %d assigned to register %s\n",
6104 pos, mono_arch_regname (inst->dreg));
6106 if (ainfo->regtype == RegTypeGeneral) {
6107 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
6108 g_assert_not_reached();
6109 switch (ainfo->size) {
6111 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6114 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6117 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6120 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6123 } else if (ainfo->regtype == RegTypeBase) {
6124 } else if (ainfo->regtype == RegTypeFP) {
6125 if (ainfo->size == 8)
6126 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6127 else if (ainfo->size == 4)
6128 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6130 g_assert_not_reached ();
6131 } else if (ainfo->regtype == RegTypeStructByVal) {
6132 int doffset = inst->inst_offset;
6134 if (ainfo->reg != STK_BASE)
6138 s390_lgr (code, s390_r13, STK_BASE);
6139 s390_aghi (code, s390_r13, alloc_size);
6142 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
6143 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
6148 if (ainfo->reg == STK_BASE)
6149 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
6150 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
6153 if (ainfo->reg == STK_BASE)
6154 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
6155 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
6158 if (ainfo->reg == STK_BASE)
6159 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
6160 s390_st (code, reg, 0, inst->inst_basereg, doffset);
6163 if (ainfo->reg == STK_BASE)
6164 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
6165 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
6168 } else if (ainfo->regtype == RegTypeStructByAddr) {
6169 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6170 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
6172 g_assert_not_reached ();
6177 if (method->save_lmf) {
6178 /*---------------------------------------------------------------*/
6179 /* build the MonoLMF structure on the stack - see mini-s390x.h */
6180 /*---------------------------------------------------------------*/
6181 lmfOffset = alloc_size - sizeof(MonoLMF);
6183 s390_lgr (code, s390_r13, cfg->frame_reg);
6184 s390_aghi (code, s390_r13, lmfOffset);
6186 /*---------------------------------------------------------------*/
6187 /* Preserve the parameter registers while we fix up the lmf */
6188 /*---------------------------------------------------------------*/
6189 s390_stmg (code, s390_r2, s390_r6, s390_r13,
6190 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6192 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
6193 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
6194 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
6195 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
6196 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
6198 /*---------------------------------------------------------------*/
6199 /* On return from this call r2 have the address of the &lmf */
6200 /*---------------------------------------------------------------*/
6201 mono_add_patch_info (cfg, code - cfg->native_code,
6202 MONO_PATCH_INFO_INTERNAL_METHOD,
6203 (gpointer)"mono_tls_get_lmf_addr");
6204 S390_CALL_TEMPLATE(code, s390_r1);
6206 /*---------------------------------------------------------------*/
6207 /* Set lmf.lmf_addr = jit_tls->lmf */
6208 /*---------------------------------------------------------------*/
6209 s390_stg (code, s390_r2, 0, s390_r13,
6210 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
6211 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
6213 /*---------------------------------------------------------------*/
6214 /* Get current lmf */
6215 /*---------------------------------------------------------------*/
6216 s390_lg (code, s390_r0, 0, s390_r2, 0);
6218 /*---------------------------------------------------------------*/
6219 /* Set our lmf as the current lmf */
6220 /*---------------------------------------------------------------*/
6221 s390_stg (code, s390_r13, 0, s390_r2, 0);
6223 /*---------------------------------------------------------------*/
6224 /* Have our lmf.previous_lmf point to the last lmf */
6225 /*---------------------------------------------------------------*/
6226 s390_stg (code, s390_r0, 0, s390_r13,
6227 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
6228 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
6230 /*---------------------------------------------------------------*/
6231 /* save method info */
6232 /*---------------------------------------------------------------*/
6233 S390_SET (code, s390_r1, method);
6234 s390_stg (code, s390_r1, 0, s390_r13,
6235 G_STRUCT_OFFSET(MonoLMF, method));
6236 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
6238 /*---------------------------------------------------------------*/
6239 /* save the current IP */
6240 /*---------------------------------------------------------------*/
6241 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
6242 s390_basr (code, s390_r1, 0);
6243 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
6244 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
6245 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
6247 /*---------------------------------------------------------------*/
6248 /* Save general and floating point registers */
6249 /*---------------------------------------------------------------*/
6250 s390_stmg (code, s390_r2, s390_r12, s390_r13,
6251 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
6252 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
6253 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
6254 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
6255 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
6256 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
6257 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
6258 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
6259 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
6260 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
6261 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
6262 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
6264 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
6265 for (i = 0; i < 16; i++) {
6266 s390_std (code, i, 0, s390_r13,
6267 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
6268 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
6269 fpOffset += sizeof(double);
6272 /*---------------------------------------------------------------*/
6273 /* Restore the parameter registers now that we've set up the lmf */
6274 /*---------------------------------------------------------------*/
6275 s390_lmg (code, s390_r2, s390_r6, s390_r13,
6276 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6279 if (cfg->method->save_lmf)
6280 argsClobbered = TRUE;
6283 argsClobbered = TRUE;
6284 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
6288 * Optimize the common case of the first bblock making a call with the same
6289 * arguments as the method. This works because the arguments are still in their
6290 * original argument registers.
6292 if (!argsClobbered) {
6293 MonoBasicBlock *first_bb = cfg->bb_entry;
6295 int filter = FILTER_IL_SEQ_POINT;
6297 next = mono_bb_first_inst (first_bb, filter);
6298 if (!next && first_bb->next_bb) {
6299 first_bb = first_bb->next_bb;
6300 next = mono_bb_first_inst (first_bb, filter);
6303 if (first_bb->in_count > 1)
6306 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
6307 ArgInfo *ainfo = cinfo->args + i;
6308 gboolean match = FALSE;
6310 inst = cfg->args [i];
6311 if (inst->opcode != OP_REGVAR) {
6312 switch (ainfo->regtype) {
6313 case RegTypeGeneral: {
6314 if (((next->opcode == OP_LOAD_MEMBASE) ||
6315 (next->opcode == OP_LOADI4_MEMBASE)) &&
6316 next->inst_basereg == inst->inst_basereg &&
6317 next->inst_offset == inst->inst_offset) {
6318 if (next->dreg == ainfo->reg) {
6322 next->opcode = OP_MOVE;
6323 next->sreg1 = ainfo->reg;
6324 /* Only continue if the instruction doesn't change argument regs */
6325 if (next->dreg == ainfo->reg)
6335 /* Argument allocated to (non-volatile) register */
6336 switch (ainfo->regtype) {
6337 case RegTypeGeneral:
6338 if (next->opcode == OP_MOVE &&
6339 next->sreg1 == inst->dreg &&
6340 next->dreg == ainfo->reg) {
6351 next = mono_inst_next (next, filter);
6358 cfg->code_len = code - cfg->native_code;
6359 g_assert (cfg->code_len < cfg->code_size);
6364 /*========================= End of Function ========================*/
6366 /*------------------------------------------------------------------*/
6368 /* Name - mono_arch_emit_epilog */
6370 /* Function - Emit the instructions for a function epilog. */
6372 /*------------------------------------------------------------------*/
6375 mono_arch_emit_epilog (MonoCompile *cfg)
6377 MonoMethod *method = cfg->method;
6380 int max_epilog_size = 96;
6382 if (cfg->method->save_lmf)
6383 max_epilog_size += 128;
6385 if (mono_jit_trace_calls != NULL)
6386 max_epilog_size += 128;
6388 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6389 cfg->code_size *= 2;
6390 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6391 cfg->stat_code_reallocs++;
6394 code = cfg->native_code + cfg->code_len;
6396 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6397 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6401 if (method->save_lmf)
6402 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6404 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6405 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6407 code = backUpStackPtr(cfg, code);
6409 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6410 s390_br (code, s390_r14);
6412 cfg->code_len = code - cfg->native_code;
6414 g_assert (cfg->code_len < cfg->code_size);
6418 /*========================= End of Function ========================*/
6420 /*------------------------------------------------------------------*/
6422 /* Name - mono_arch_emit_exceptions */
6424 /* Function - Emit the blocks to handle exception conditions. */
6426 /*------------------------------------------------------------------*/
6429 mono_arch_emit_exceptions (MonoCompile *cfg)
6431 MonoJumpInfo *patch_info;
6437 MonoClass *exc_classes [MAX_EXC];
6438 guint8 *exc_throw_start [MAX_EXC];
6440 for (patch_info = cfg->patch_info;
6442 patch_info = patch_info->next) {
6443 if (patch_info->type == MONO_PATCH_INFO_EXC)
6447 code_size = exc_count * 48;
6449 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6450 cfg->code_size *= 2;
6451 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6452 cfg->stat_code_reallocs++;
6455 code = cfg->native_code + cfg->code_len;
6457 /*---------------------------------------------------------------------*/
6458 /* Add code to raise exceptions */
6459 /*---------------------------------------------------------------------*/
6460 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6461 switch (patch_info->type) {
6462 case MONO_PATCH_INFO_EXC: {
6463 guint8 *ip = patch_info->ip.i + cfg->native_code;
6464 MonoClass *exc_class;
6467 /*-----------------------------------------------------*/
6468 /* Patch the branch in epilog to come here */
6469 /*-----------------------------------------------------*/
6470 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6472 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6474 patch_info->data.name);
6475 throw_ip = patch_info->ip.i;
6477 for (iExc = 0; iExc < nThrows; ++iExc)
6478 if (exc_classes [iExc] == exc_class)
6481 if (iExc < nThrows) {
6482 s390_jcl (code, S390_CC_UN,
6483 (guint64) exc_throw_start [iExc]);
6484 patch_info->type = MONO_PATCH_INFO_NONE;
6487 if (nThrows < MAX_EXC) {
6488 exc_classes [nThrows] = exc_class;
6489 exc_throw_start [nThrows] = code;
6492 /*---------------------------------------------*/
6493 /* Patch the parameter passed to the handler */
6494 /*---------------------------------------------*/
6495 S390_SET (code, s390_r2, exc_class->type_token);
6496 /*---------------------------------------------*/
6497 /* Load return address & parameter register */
6498 /*---------------------------------------------*/
6499 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6500 cfg->native_code + 8), code));
6501 /*---------------------------------------------*/
6502 /* Reuse the current patch to set the jump */
6503 /*---------------------------------------------*/
6504 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6505 patch_info->data.name = "mono_arch_throw_corlib_exception";
6506 patch_info->ip.i = code - cfg->native_code;
6507 S390_BR_TEMPLATE (code, s390_r1);
6517 cfg->code_len = code - cfg->native_code;
6519 g_assert (cfg->code_len < cfg->code_size);
6523 /*========================= End of Function ========================*/
6525 /*------------------------------------------------------------------*/
6527 /* Name - mono_arch_finish_init */
6529 /* Function - Setup the JIT's Thread Level Specific Data. */
6531 /*------------------------------------------------------------------*/
6534 mono_arch_finish_init (void)
6538 /*========================= End of Function ========================*/
6540 /*------------------------------------------------------------------*/
6542 /* Name - mono_arch_free_jit_tls_data */
6544 /* Function - Free tls data. */
6546 /*------------------------------------------------------------------*/
6549 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6553 /*========================= End of Function ========================*/
6555 /*------------------------------------------------------------------*/
6557 /* Name - mono_arch_emit_inst_for_method */
6559 /*------------------------------------------------------------------*/
6562 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6567 /*========================= End of Function ========================*/
6569 /*------------------------------------------------------------------*/
6571 /* Name - mono_arch_decompose_opts */
6573 /* Function - Decompose opcode into a System z opcode. */
6575 /*------------------------------------------------------------------*/
6578 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6581 * Have to rename these to avoid being decomposed normally, since the normal
6582 * decomposition does not work on S390.
6584 switch (ins->opcode) {
6586 ins->opcode = OP_S390_ISUB_OVF;
6588 case OP_ISUB_OVF_UN:
6589 ins->opcode = OP_S390_ISUB_OVF_UN;
6592 ins->opcode = OP_S390_IADD_OVF;
6594 case OP_IADD_OVF_UN:
6595 ins->opcode = OP_S390_IADD_OVF_UN;
6598 ins->opcode = OP_S390_LADD_OVF;
6600 case OP_LADD_OVF_UN:
6601 ins->opcode = OP_S390_LADD_OVF_UN;
6604 ins->opcode = OP_S390_LSUB_OVF;
6606 case OP_LSUB_OVF_UN:
6607 ins->opcode = OP_S390_LSUB_OVF_UN;
6614 /*========================= End of Function ========================*/
6616 /*------------------------------------------------------------------*/
6618 /* Name - mono_arch_regalloc_cost */
6620 /* Function - Determine the cost, in the number of memory */
6621 /* references, of the action of allocating the var- */
6622 /* iable VMV into a register during global register */
6625 /* Returns - Cost */
6627 /*------------------------------------------------------------------*/
6630 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6636 /*========================= End of Function ========================*/
6638 /*------------------------------------------------------------------*/
6640 /* Name - mono_arch_flush_register_windows */
6646 /*------------------------------------------------------------------*/
6649 mono_arch_flush_register_windows (void)
6653 /*========================= End of Function ========================*/
6655 /*------------------------------------------------------------------*/
6657 /* Name - mono_arch_is_inst_imm */
6659 /* Function - Determine if operand qualifies as an immediate */
6660 /* value. For s390 this is a value -32768-32768 */
6662 /* Returns - True|False - is [not] immediate value. */
6664 /*------------------------------------------------------------------*/
6667 mono_arch_is_inst_imm (gint64 imm)
6669 return s390_is_imm32 (imm);
6672 /*========================= End of Function ========================*/
6674 /*------------------------------------------------------------------*/
6676 /* Name - mono_arch_get_patch_offset */
6678 /* Function - Dummy entry point until s390x supports aot. */
6680 /* Returns - Offset for patch. */
6682 /*------------------------------------------------------------------*/
6685 mono_arch_get_patch_offset (guint8 *code)
6690 /*========================= End of Function ========================*/
6692 /*------------------------------------------------------------------*/
6694 /* Name - mono_arch_context_get_int_reg. */
6698 /* Returns - Return a register from the context. */
6700 /*------------------------------------------------------------------*/
6703 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6705 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6708 /*========================= End of Function ========================*/
6710 /*------------------------------------------------------------------*/
6712 /* Name - mono_arch_context_set_int_reg. */
6714 /* Function - Set a value in a specified register. */
6716 /*------------------------------------------------------------------*/
6719 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6721 ctx->uc_mcontext.gregs[reg] = val;
6724 /*========================= End of Function ========================*/
6726 /*------------------------------------------------------------------*/
6728 /* Name - mono_arch_get_this_arg_from_call. */
6732 /*------------------------------------------------------------------*/
6735 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6737 return (gpointer) regs [s390_r2];
6740 /*========================= End of Function ========================*/
6742 /*------------------------------------------------------------------*/
6744 /* Name - get_delegate_invoke_impl. */
6748 /*------------------------------------------------------------------*/
6751 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6753 guint8 *code, *start;
6758 start = code = mono_global_codeman_reserve (size);
6760 /* Replace the this argument with the target */
6761 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6762 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6763 s390_br (code, s390_r1);
6764 g_assert ((code - start) <= size);
6766 mono_arch_flush_icache (start, size);
6770 size = 32 + param_count * 8;
6771 start = code = mono_global_codeman_reserve (size);
6773 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6774 /* slide down the arguments */
6775 for (i = 0; i < param_count; ++i) {
6776 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6778 s390_br (code, s390_r1);
6780 g_assert ((code - start) <= size);
6782 mono_arch_flush_icache (start, size);
6786 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6788 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6789 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6796 /*========================= End of Function ========================*/
6798 /*------------------------------------------------------------------*/
6800 /* Name - mono_arch_get_delegate_invoke_impls. */
6804 /*------------------------------------------------------------------*/
6807 mono_arch_get_delegate_invoke_impls (void)
6810 MonoTrampInfo *info;
6813 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6814 res = g_slist_prepend (res, info);
6816 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6817 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6818 res = g_slist_prepend (res, info);
6824 /*========================= End of Function ========================*/
6826 /*------------------------------------------------------------------*/
6828 /* Name - mono_arch_get_delegate_invoke_impl. */
6832 /*------------------------------------------------------------------*/
6835 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6837 guint8 *code, *start;
6839 /* FIXME: Support more cases */
6840 if (MONO_TYPE_ISSTRUCT (sig->ret))
6844 static guint8* cached = NULL;
6849 if (mono_aot_only) {
6850 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6852 MonoTrampInfo *info;
6853 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6854 mono_tramp_info_register (info, NULL);
6857 mono_memory_barrier ();
6861 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6864 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6866 for (i = 0; i < sig->param_count; ++i)
6867 if (!mono_is_regsize_var (sig->params [i]))
6871 code = cache [sig->param_count];
6875 if (mono_aot_only) {
6876 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6877 start = mono_aot_get_trampoline (name);
6880 MonoTrampInfo *info;
6881 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6882 mono_tramp_info_register (info, NULL);
6885 mono_memory_barrier ();
6887 cache [sig->param_count] = start;
6892 /*========================= End of Function ========================*/
6894 /*------------------------------------------------------------------*/
6896 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6900 /*------------------------------------------------------------------*/
6903 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6904 int offset, gboolean load_imt_reg)
6906 guint8 *code, *start;
6909 start = code = mono_global_codeman_reserve (size);
6912 * Replace the "this" argument with the target
6914 s390_lgr (code, s390_r1, s390_r2);
6915 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6918 * Load the IMT register, if needed
6921 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6927 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6929 s390_agfi(code, s390_r1, offset);
6931 s390_lg (code, s390_r1, 0, s390_r1, 0);
6932 s390_br (code, s390_r1);
6937 /*========================= End of Function ========================*/
6939 /*------------------------------------------------------------------*/
6941 /* Name - mono_arch_build_imt_trampoline. */
6945 /*------------------------------------------------------------------*/
6948 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6949 MonoIMTCheckItem **imt_entries, int count,
6950 gpointer fail_tramp)
6954 guchar *code, *start;
6957 for (i = 0; i < count; ++i) {
6958 MonoIMTCheckItem *item = imt_entries [i];
6959 if (item->is_equals) {
6960 if (item->check_target_idx) {
6961 if (!item->compare_done)
6962 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6963 if (item->has_target_code)
6964 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6966 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6970 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6972 if (!item->has_target_code)
6973 item->chunk_size += LOAD_SIZE;
6975 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6976 #if ENABLE_WRONG_METHOD_CHECK
6977 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6982 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6983 imt_entries [item->check_target_idx]->compare_done = TRUE;
6985 size += item->chunk_size;
6989 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6991 code = mono_domain_code_reserve (domain, size);
6995 for (i = 0; i < count; ++i) {
6996 MonoIMTCheckItem *item = imt_entries [i];
6997 item->code_target = (guint8 *) code;
6998 if (item->is_equals) {
6999 if (item->check_target_idx) {
7000 if (!item->compare_done) {
7001 S390_SET (code, s390_r0, item->key);
7002 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
7004 item->jmp_code = (guint8*) code;
7005 s390_jcl (code, S390_CC_NE, 0);
7007 if (item->has_target_code) {
7008 S390_SET (code, s390_r1, item->value.target_code);
7010 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7011 s390_lg (code, s390_r1, 0, s390_r1, 0);
7013 s390_br (code, s390_r1);
7018 S390_SET (code, s390_r0, item->key);
7019 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
7020 item->jmp_code = (guint8*) code;
7021 s390_jcl (code, S390_CC_NE, 0);
7022 if (item->has_target_code) {
7023 S390_SET (code, s390_r1, item->value.target_code);
7026 S390_SET (code, s390_r1,
7027 (&(vtable->vtable [item->value.vtable_slot])));
7028 s390_lg (code, s390_r1, 0, s390_r1, 0);
7030 s390_br (code, s390_r1);
7031 target = (gint64) S390_RELATIVE(code, item->jmp_code);
7032 s390_patch_rel(item->jmp_code+2, target);
7033 S390_SET (code, s390_r1, fail_tramp);
7034 s390_br (code, s390_r1);
7035 item->jmp_code = NULL;
7037 /* enable the commented code to assert on wrong method */
7038 #if ENABLE_WRONG_METHOD_CHECK
7039 g_assert_not_reached ();
7041 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7042 s390_lg (code, s390_r1, 0, s390_r1, 0);
7043 s390_br (code, s390_r1);
7047 S390_SET (code, s390_r0, item->key);
7048 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
7049 item->jmp_code = (guint8 *) code;
7050 s390_jcl (code, S390_CC_GE, 0);
7054 * patch the branches to get to the target items
7056 for (i = 0; i < count; ++i) {
7057 MonoIMTCheckItem *item = imt_entries [i];
7058 if (item->jmp_code) {
7059 if (item->check_target_idx) {
7061 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
7063 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
7068 mono_arch_flush_icache ((guint8*)start, (code - start));
7071 mono_stats.imt_trampolines_size += (code - start);
7073 g_assert (code - start <= size);
7075 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
7076 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
7081 /*========================= End of Function ========================*/
7083 /*------------------------------------------------------------------*/
7085 /* Name - mono_arch_find_imt_method. */
7087 /* Function - Get the method address from MONO_ARCH_IMT_REG */
7088 /* found in the save area. */
7090 /*------------------------------------------------------------------*/
7093 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
7095 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
7098 /*========================= End of Function ========================*/
7100 /*------------------------------------------------------------------*/
7102 /* Name - mono_arch_find_static_call_vtable */
7104 /* Function - Find the static call vtable. */
7106 /*------------------------------------------------------------------*/
7109 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
7111 mgreg_t *r = (mgreg_t*)regs;
7113 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
7116 /*========================= End of Function ========================*/
7118 /*------------------------------------------------------------------*/
7120 /* Name - mono_arch_get_cie_program */
7122 /* Function - Find the static call vtable. */
7124 /*------------------------------------------------------------------*/
7127 mono_arch_get_cie_program (void)
7131 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
7136 /*========================= End of Function ========================*/
7138 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7140 /*------------------------------------------------------------------*/
7142 /* Name - mono_arch_set_breakpoint. */
7144 /* Function - Set a breakpoint at the native code corresponding */
7145 /* to JI at NATIVE_OFFSET. The location should */
7146 /* contain code emitted by OP_SEQ_POINT. */
7148 /*------------------------------------------------------------------*/
7151 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
7155 breakpointCode.pTrigger = bp_trigger_page;
7156 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
7157 code += BREAKPOINT_SIZE;
7160 /*========================= End of Function ========================*/
7162 /*------------------------------------------------------------------*/
7164 /* Name - mono_arch_clear_breakpoint. */
7166 /* Function - Clear the breakpoint at IP. */
7168 /*------------------------------------------------------------------*/
7171 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
7176 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
7180 /*========================= End of Function ========================*/
7182 /*------------------------------------------------------------------*/
7184 /* Name - mono_arch_is_breakpoint_event. */
7188 /*------------------------------------------------------------------*/
7191 mono_arch_is_breakpoint_event (void *info, void *sigctx)
7193 siginfo_t* sinfo = (siginfo_t*) info;
7196 * Sometimes the address is off by 4
7198 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
7204 /*========================= End of Function ========================*/
7206 /*------------------------------------------------------------------*/
7208 /* Name - mono_arch_skip_breakpoint. */
7210 /* Function - Modify the CTX so the IP is placed after the */
7211 /* breakpoint instruction, so when we resume, the */
7212 /* instruction is not executed again. */
7214 /*------------------------------------------------------------------*/
7217 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
7219 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
7222 /*========================= End of Function ========================*/
7224 /*------------------------------------------------------------------*/
7226 /* Name - mono_arch_start_single_stepping. */
7228 /* Function - Start single stepping. */
7230 /*------------------------------------------------------------------*/
7233 mono_arch_start_single_stepping (void)
7235 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
7238 /*========================= End of Function ========================*/
7240 /*------------------------------------------------------------------*/
7242 /* Name - mono_arch_stop_single_stepping. */
7244 /* Function - Stop single stepping. */
7246 /*------------------------------------------------------------------*/
7249 mono_arch_stop_single_stepping (void)
7251 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
7254 /*========================= End of Function ========================*/
7256 /*------------------------------------------------------------------*/
7258 /* Name - mono_arch_is_single_step_event. */
7260 /* Function - Return whether the machine state in sigctx cor- */
7261 /* responds to a single step event. */
7263 /*------------------------------------------------------------------*/
7266 mono_arch_is_single_step_event (void *info, void *sigctx)
7268 siginfo_t* sinfo = (siginfo_t*) info;
7271 * Sometimes the address is off by 4
7273 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7279 /*========================= End of Function ========================*/
7281 /*------------------------------------------------------------------*/
7283 /* Name - mono_arch_skip_single_step. */
7285 /* Function - Modify the ctx so the IP is placed after the */
7286 /* single step trigger instruction, so that the */
7287 /* instruction is not executed again. */
7289 /*------------------------------------------------------------------*/
7292 mono_arch_skip_single_step (MonoContext *ctx)
7294 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7297 /*========================= End of Function ========================*/
7299 /*------------------------------------------------------------------*/
7301 /* Name - mono_arch_create_seq_point_info. */
7303 /* Function - Return a pointer to a data struction which is */
7304 /* used by the sequence point implementation in */
7307 /*------------------------------------------------------------------*/
7310 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7316 /*========================= End of Function ========================*/
7318 /*------------------------------------------------------------------*/
7320 /* Name - mono_arch_init_lmf_ext. */
7324 /*------------------------------------------------------------------*/
7327 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7329 ext->lmf.previous_lmf = prev_lmf;
7330 /* Mark that this is a MonoLMFExt */
7331 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7332 ext->lmf.ebp = (gssize)ext;
7335 /*========================= End of Function ========================*/
7339 /*------------------------------------------------------------------*/
7341 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7343 /* Function - If this CPU supports vector operations then it */
7344 /* supports the equivalent of SSE1-4. */
7346 /*------------------------------------------------------------------*/
7349 mono_arch_cpu_enumerate_simd_versions (void)
7351 guint32 sseOpts = 0;
7353 if (mono_hwcap_s390x_has_vec)
7354 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7355 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7356 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7357 SIMD_VERSION_SSE4a);
7362 /*========================= End of Function ========================*/
7364 /*------------------------------------------------------------------*/
7366 /* Name - mono_arch_opcode_supported. */
7368 /* Function - Check if a given return code is supported. */
7370 /*------------------------------------------------------------------*/
7373 mono_arch_opcode_supported (int opcode)
7376 case OP_ATOMIC_ADD_I4:
7377 case OP_ATOMIC_ADD_I8:
7378 case OP_ATOMIC_EXCHANGE_I4:
7379 case OP_ATOMIC_EXCHANGE_I8:
7386 /*========================= End of Function ========================*/