3 * Function - S/390 backend for the Mono code generator.
5 * Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
9 * Derivation - From mini-x86 & mini-ppc by -
10 * Paolo Molaro (lupus@ximian.com)
11 * Dietmar Maurer (dietmar@ximian.com)
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 #define MAX_ARCH_DELEGATE_PARAMS 7
21 #define EMIT_COND_BRANCH(ins,cond) \
23 if (ins->inst_true_bb->native_offset) { \
25 displace = ((cfg->native_code + \
26 ins->inst_true_bb->native_offset) - code) / 2; \
27 if (s390_is_imm16(displace)) { \
28 s390_brc (code, cond, displace); \
30 s390_jcl (code, cond, displace); \
33 mono_add_patch_info (cfg, code - cfg->native_code, \
34 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
35 s390_jcl (code, cond, 0); \
39 #define EMIT_UNCOND_BRANCH(ins) \
41 if (ins->inst_target_bb->native_offset) { \
43 displace = ((cfg->native_code + \
44 ins->inst_target_bb->native_offset) - code) / 2; \
45 if (s390_is_imm16(displace)) { \
46 s390_brc (code, S390_CC_UN, displace); \
48 s390_jcl (code, S390_CC_UN, displace); \
51 mono_add_patch_info (cfg, code - cfg->native_code, \
52 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
53 s390_jcl (code, S390_CC_UN, 0); \
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
59 mono_add_patch_info (cfg, code - cfg->native_code, \
60 MONO_PATCH_INFO_EXC, exc_name); \
61 s390_jcl (code, cond, 0); \
64 #define EMIT_COMP_AND_BRANCH(ins, cab, cmp) \
66 if (ins->inst_true_bb->native_offset) { \
68 displace = ((cfg->native_code + \
69 ins->inst_true_bb->native_offset) - code) / 2; \
70 if (s390_is_imm16(displace)) { \
71 s390_##cab (code, ins->sreg1, ins->sreg2, \
72 ins->sreg3, displace); \
74 s390_##cmp (code, ins->sreg1, ins->sreg2); \
75 displace = ((cfg->native_code + \
76 ins->inst_true_bb->native_offset) - code) / 2; \
77 s390_jcl (code, ins->sreg3, displace); \
80 s390_##cmp (code, ins->sreg1, ins->sreg2); \
81 mono_add_patch_info (cfg, code - cfg->native_code, \
82 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
83 s390_jcl (code, ins->sreg3, 0); \
87 #define EMIT_COMP_AND_BRANCH_IMM(ins, cab, cmp, lat, logical) \
89 if (ins->inst_true_bb->native_offset) { \
91 if ((ins->backend.data == 0) && (!logical)) { \
92 s390_##lat (code, ins->sreg1, ins->sreg1); \
93 displace = ((cfg->native_code + \
94 ins->inst_true_bb->native_offset) - code) / 2; \
95 if (s390_is_imm16(displace)) { \
96 s390_brc (code, ins->sreg3, displace); \
98 s390_jcl (code, ins->sreg3, displace); \
101 S390_SET (code, s390_r0, ins->backend.data); \
102 displace = ((cfg->native_code + \
103 ins->inst_true_bb->native_offset) - code) / 2; \
104 if (s390_is_imm16(displace)) { \
105 s390_##cab (code, ins->sreg1, s390_r0, \
106 ins->sreg3, displace); \
108 s390_##cmp (code, ins->sreg1, s390_r0); \
109 displace = ((cfg->native_code + \
110 ins->inst_true_bb->native_offset) - code) / 2; \
111 s390_jcl (code, ins->sreg3, displace); \
115 if ((ins->backend.data == 0) && (!logical)) { \
116 s390_##lat (code, ins->sreg1, ins->sreg1); \
118 S390_SET (code, s390_r0, ins->backend.data); \
119 s390_##cmp (code, ins->sreg1, s390_r0); \
121 mono_add_patch_info (cfg, code - cfg->native_code, \
122 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
123 s390_jcl (code, ins->sreg3, 0); \
127 #define CHECK_SRCDST_COM \
128 if (ins->dreg == ins->sreg2) { \
132 if (ins->dreg != ins->sreg1) { \
133 s390_lgr (code, ins->dreg, ins->sreg1); \
137 #define CHECK_SRCDST_NCOM \
138 if (ins->dreg == ins->sreg2) { \
140 s390_lgr (code, s390_r13, ins->sreg2); \
144 if (ins->dreg != ins->sreg1) { \
145 s390_lgr (code, ins->dreg, ins->sreg1); \
148 #define CHECK_SRCDST_COM_I \
149 if (ins->dreg == ins->sreg2) { \
153 if (ins->dreg != ins->sreg1) { \
154 s390_lgfr (code, ins->dreg, ins->sreg1); \
158 #define CHECK_SRCDST_NCOM_I \
159 if (ins->dreg == ins->sreg2) { \
161 s390_lgfr (code, s390_r13, ins->sreg2); \
165 if (ins->dreg != ins->sreg1) { \
166 s390_lgfr (code, ins->dreg, ins->sreg1); \
169 #define CHECK_SRCDST_COM_F \
170 if (ins->dreg == ins->sreg2) { \
174 if (ins->dreg != ins->sreg1) { \
175 s390_ldr (code, ins->dreg, ins->sreg1); \
179 #define CHECK_SRCDST_NCOM_F \
180 if (ins->dreg == ins->sreg2) { \
182 s390_ldr (code, s390_r13, ins->sreg2); \
186 if (ins->dreg != ins->sreg1) { \
187 s390_ldr (code, ins->dreg, ins->sreg1); \
190 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
193 MONO_INST_NEW (cfg, inst, OP_NOP); \
196 inst->inst_offset = offset; \
198 inst->inst_imm = imm; \
200 if (s390_is_uimm12(offset)) { \
202 inst->inst_offset = offset; \
204 dReg = mono_alloc_preg (cfg); \
205 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
206 dReg, dest, offset); \
208 inst->inst_offset = 0; \
210 if (s390_is_uimm12(imm)) { \
212 inst->inst_imm = imm; \
214 sReg = mono_alloc_preg (cfg); \
215 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
217 inst->sreg1 = sReg; \
218 inst->inst_imm = 0; \
221 inst->opcode = OP_S390_MOVE; \
222 inst->backend.size = size; \
223 MONO_ADD_INS (cfg->cbb, inst); \
226 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
227 int reg = mono_alloc_preg (cfg); \
230 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
233 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
237 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
241 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
245 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
249 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
252 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
256 tmpr = mono_alloc_preg (cfg); \
257 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
258 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
262 tmpr = mono_alloc_preg (cfg); \
263 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
265 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
269 tmpr = mono_alloc_preg (cfg); \
270 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
272 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
276 tmpr = mono_alloc_preg (cfg); \
277 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
279 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
283 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
289 #define DEBUG(a) if (cfg->verbose_level > 1) a
293 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
295 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
296 #define S390X_NOP_SIZE sizeof(RR_Format)
298 #define MAX(a, b) ((a) > (b) ? (a) : (b))
301 * imt trampoline size values
304 #define LOADCON_SIZE 20
308 #define ENABLE_WRONG_METHOD_CHECK 0
310 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
311 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
313 /*========================= End of Defines =========================*/
315 /*------------------------------------------------------------------*/
316 /* I n c l u d e s */
317 /*------------------------------------------------------------------*/
321 #include <sys/types.h>
324 #include <mono/metadata/abi-details.h>
325 #include <mono/metadata/appdomain.h>
326 #include <mono/metadata/debug-helpers.h>
327 #include <mono/metadata/profiler-private.h>
328 #include <mono/utils/mono-error.h>
329 #include <mono/utils/mono-error-internals.h>
330 #include <mono/utils/mono-math.h>
331 #include <mono/utils/mono-mmap.h>
332 #include <mono/utils/mono-hwcap.h>
333 #include <mono/utils/mono-threads.h>
334 #include <mono/utils/unlocked.h>
336 #include "mini-s390x.h"
337 #include "cpu-s390x.h"
338 #include "support-s390x.h"
339 #include "jit-icalls.h"
344 /*========================= End of Includes ========================*/
346 /*------------------------------------------------------------------*/
347 /* T y p e d e f s */
348 /*------------------------------------------------------------------*/
360 /*------------------------------------------------------------------*/
361 /* Used by the instrument_emit_epilog */
362 /*------------------------------------------------------------------*/
373 typedef struct InstList InstList;
387 RegTypeStructByValInFP,
389 RegTypeStructByAddrOnStack
393 gint32 offset; /* offset from caller's stack */
394 gint32 offparm; /* offset from callee's stack */
395 guint16 vtsize; /* in param area */
398 guint32 size; /* Size of structure used by RegTypeStructByVal */
399 gint32 type; /* Data type of argument */
415 gint64 gr[5]; /* R2-R6 */
416 gdouble fp[3]; /* F0-F2 */
417 } __attribute__ ((__packed__)) RegParm;
425 } __attribute__ ((__packed__)) breakpoint_t;
427 /*========================= End of Typedefs ========================*/
429 /*------------------------------------------------------------------*/
430 /* P r o t o t y p e s */
431 /*------------------------------------------------------------------*/
433 static void indent (int);
434 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
435 static void decodeParm (MonoType *, void *, int);
436 static void enter_method (MonoMethod *, RegParm *, char *);
437 static void leave_method (MonoMethod *, ...);
438 static inline void add_general (guint *, size_data *, ArgInfo *);
439 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
440 static inline void add_float (guint *, size_data *, ArgInfo *);
441 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
442 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
443 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
444 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
445 static void compare_and_branch(MonoBasicBlock *, MonoInst *, int, gboolean);
447 /*========================= End of Prototypes ======================*/
449 /*------------------------------------------------------------------*/
450 /* G l o b a l V a r i a b l e s */
451 /*------------------------------------------------------------------*/
453 int mono_exc_esp_offset = 0;
455 __thread int indent_level = 0;
456 __thread FILE *trFd = NULL;
460 * The code generated for sequence points reads from this location,
461 * which is made read-only when single stepping is enabled.
463 static gpointer ss_trigger_page;
466 * Enabled breakpoints read from this trigger page
468 static gpointer bp_trigger_page;
470 breakpoint_t breakpointCode;
472 static mono_mutex_t mini_arch_mutex;
474 static const char * grNames[] = {
475 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
476 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
477 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
481 static const char * fpNames[] = {
482 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
483 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
484 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
488 static const char * vrNames[] = {
489 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
490 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
491 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
492 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
495 /*====================== End of Global Variables ===================*/
497 /*------------------------------------------------------------------*/
499 /* Name - mono_arch_regname */
501 /* Function - Returns the name of the register specified by */
502 /* the input parameter. */
504 /*------------------------------------------------------------------*/
507 mono_arch_regname (int reg)
509 if (reg >= 0 && reg < 16)
510 return grNames [reg];
515 /*========================= End of Function ========================*/
517 /*------------------------------------------------------------------*/
519 /* Name - mono_arch_fregname */
521 /* Function - Returns the name of the register specified by */
522 /* the input parameter. */
524 /*------------------------------------------------------------------*/
527 mono_arch_fregname (int reg)
529 if (reg >= 0 && reg < 16)
530 return fpNames [reg];
535 /*========================= End of Function ========================*/
537 /*------------------------------------------------------------------*/
539 /* Name - mono_arch_xregname */
541 /* Function - Returns the name of the register specified by */
542 /* the input parameter. */
544 /*------------------------------------------------------------------*/
547 mono_arch_xregname (int reg)
549 if (reg < s390_VR_NREG)
550 return vrNames [reg];
555 /*========================= End of Function ========================*/
557 /*------------------------------------------------------------------*/
559 /* Name - arch_get_argument_info */
561 /* Function - Gathers information on parameters such as size, */
562 /* alignment, and padding. arg_info should be large */
563 /* enough to hold param_count + 1 entries. */
565 /* Parameters - @csig - Method signature */
566 /* @param_count - No. of parameters to consider */
567 /* @arg_info - An array to store the result info */
569 /* Returns - Size of the activation frame */
571 /*------------------------------------------------------------------*/
574 mono_arch_get_argument_info (MonoMethodSignature *csig,
576 MonoJitArgumentInfo *arg_info)
578 int k, frame_size = 0;
579 int size, align, pad;
582 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
583 frame_size += sizeof (gpointer);
587 arg_info [0].offset = offset;
590 frame_size += sizeof (gpointer);
594 arg_info [0].size = frame_size;
596 for (k = 0; k < param_count; k++) {
599 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
601 size = mini_type_stack_size (csig->params [k], &align);
603 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
604 arg_info [k].pad = pad;
606 arg_info [k + 1].pad = 0;
607 arg_info [k + 1].size = size;
609 arg_info [k + 1].offset = offset;
613 align = MONO_ARCH_FRAME_ALIGNMENT;
614 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
615 arg_info [k].pad = pad;
620 /*========================= End of Function ========================*/
622 /*------------------------------------------------------------------*/
624 /* Name - emit_unwind_regs. */
626 /* Function - Determines if a value can be returned in one or */
629 /*------------------------------------------------------------------*/
631 static void __inline__
632 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
636 for (i = start; i < end; i++) {
637 mono_emit_unwind_op_offset (cfg, code, i, offset);
638 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
639 offset += sizeof(gulong);
643 /*========================= End of Function ========================*/
645 /*------------------------------------------------------------------*/
647 /* Name - retFitsInReg. */
649 /* Function - Determines if a value can be returned in one or */
652 /*------------------------------------------------------------------*/
654 static inline gboolean
655 retFitsInReg(guint32 size)
670 /*========================= End of Function ========================*/
672 /*------------------------------------------------------------------*/
674 /* Name - backStackPtr. */
676 /* Function - Restore Stack Pointer to previous frame. */
678 /*------------------------------------------------------------------*/
680 static inline guint8 *
681 backUpStackPtr(MonoCompile *cfg, guint8 *code)
683 int stackSize = cfg->stack_usage;
685 if (cfg->frame_reg != STK_BASE)
686 s390_lgr (code, STK_BASE, cfg->frame_reg);
688 if (s390_is_imm16 (stackSize)) {
689 s390_aghi (code, STK_BASE, stackSize);
691 while (stackSize > 32767) {
692 s390_aghi (code, STK_BASE, 32767);
695 s390_aghi (code, STK_BASE, stackSize);
700 /*========================= End of Function ========================*/
702 /*------------------------------------------------------------------*/
706 /* Function - Perform nice indenting to current level */
708 /*------------------------------------------------------------------*/
714 indent_level += diff;
716 fprintf (trFd, "%p [%3d] ",(void *)pthread_self(),v);
718 fprintf (trFd, ". ");
721 indent_level += diff;
724 /*========================= End of Function ========================*/
726 /*------------------------------------------------------------------*/
728 /* Name - cvtMonoType */
730 /* Function - Convert a mono-type to a string. */
732 /*------------------------------------------------------------------*/
735 cvtMonoType(MonoTypeEnum t)
740 return "MONO_TYPE_END";
742 return "MONO_TYPE_VOID";
743 case MONO_TYPE_BOOLEAN:
744 return "MONO_TYPE_BOOLEAN";
746 return "MONO_TYPE_CHAR";
748 return "MONO_TYPE_I1";
750 return "MONO_TYPE_U1";
752 return "MONO_TYPE_I2";
754 return "MONO_TYPE_U2";
756 return "MONO_TYPE_I4";
758 return "MONO_TYPE_U4";
760 return "MONO_TYPE_I8";
762 return "MONO_TYPE_U8";
764 return "MONO_TYPE_R4";
766 return "MONO_TYPE_R8";
767 case MONO_TYPE_STRING:
768 return "MONO_TYPE_STRING";
770 return "MONO_TYPE_PTR";
771 case MONO_TYPE_BYREF:
772 return "MONO_TYPE_BYREF";
773 case MONO_TYPE_VALUETYPE:
774 return "MONO_TYPE_VALUETYPE";
775 case MONO_TYPE_CLASS:
776 return "MONO_TYPE_CLASS";
778 return "MONO_TYPE_VAR";
779 case MONO_TYPE_ARRAY:
780 return "MONO_TYPE_ARRAY";
781 case MONO_TYPE_GENERICINST:
782 return "MONO_TYPE_GENERICINST";
783 case MONO_TYPE_TYPEDBYREF:
784 return "MONO_TYPE_TYPEDBYREF";
786 return "MONO_TYPE_I";
788 return "MONO_TYPE_U";
789 case MONO_TYPE_FNPTR:
790 return "MONO_TYPE_FNPTR";
791 case MONO_TYPE_OBJECT:
792 return "MONO_TYPE_OBJECT";
793 case MONO_TYPE_SZARRAY:
794 return "MONO_TYPE_SZARRAY";
796 return "MONO_TYPE_MVAR";
797 case MONO_TYPE_CMOD_REQD:
798 return "MONO_TYPE_CMOD_REQD";
799 case MONO_TYPE_CMOD_OPT:
800 return "MONO_TYPE_CMOD_OPT";
801 case MONO_TYPE_INTERNAL:
802 return "MONO_TYPE_INTERNAL";
803 case MONO_TYPE_MODIFIER:
804 return "MONO_TYPE_MODIFIER";
805 case MONO_TYPE_SENTINEL:
806 return "MONO_TYPE_SENTINEL";
807 case MONO_TYPE_PINNED:
808 return "MONO_TYPE_PINNED";
815 /*========================= End of Function ========================*/
817 /*------------------------------------------------------------------*/
819 /* Name - decodeParmString */
821 /* Function - Decode a parameter string for the trace. */
823 /*------------------------------------------------------------------*/
826 decodeParmString (MonoString *s)
829 char *str = mono_string_to_utf8_checked(s, &error);
830 if (is_ok (&error)) {
831 fprintf (trFd, "[STRING:%p:%s], ", s, str);
834 mono_error_cleanup (&error);
835 fprintf (trFd, "[STRING:%p:], ", s);
839 /*========================= End of Function ========================*/
841 /*------------------------------------------------------------------*/
843 /* Name - decodeParm */
845 /* Function - Decode a parameter for the trace. */
847 /*------------------------------------------------------------------*/
851 decodeParm(MonoType *type, void *curParm, int size)
856 fprintf (trFd, "[BYREF:%p], ", *((char **) curParm));
858 simpleType = mini_get_underlying_type(type)->type;
860 switch (simpleType) {
862 fprintf (trFd, "[INTPTR:%p], ", *((int **) curParm));
865 fprintf (trFd, "[UINTPTR:%p], ", *((int **) curParm));
867 case MONO_TYPE_BOOLEAN :
868 fprintf (trFd, "[BOOL:%ld], ", *((gint64 *) curParm));
870 case MONO_TYPE_CHAR :
871 fprintf (trFd, "[CHAR:%c], ", *((int *) curParm));
874 fprintf (trFd, "[INT1:%ld], ", *((gint64 *) curParm));
877 fprintf (trFd, "[INT2:%ld], ", *((gint64 *) curParm));
880 fprintf (trFd, "[INT4:%ld], ", *((gint64 *) curParm));
883 fprintf (trFd, "[UINT1:%lu], ", *((guint64 *) curParm));
886 fprintf (trFd, "[UINT2:%lu], ", *((guint64 *) curParm));
889 fprintf (trFd, "[UINT4:%lu], ", *((guint64 *) curParm));
892 fprintf (trFd, "[UINT8:%lu], ", *((guint64 *) curParm));
894 case MONO_TYPE_STRING : {
895 MonoString *s = *((MonoString **) curParm);
897 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
898 decodeParmString (s);
900 fprintf (trFd, "[STRING:null], ");
904 case MONO_TYPE_CLASS :
905 case MONO_TYPE_OBJECT : {
906 MonoObject *obj = *((MonoObject **) curParm);
908 if ((obj) && (obj->vtable)) {
909 fprintf (trFd, "[CLASS/OBJ:");
910 klass = obj->vtable->klass;
911 fprintf (trFd, "%p [%p] ",obj,curParm);
912 if (klass == mono_defaults.string_class) {
913 decodeParmString ((MonoString *)obj);
914 } else if (klass == mono_defaults.int32_class) {
915 fprintf (trFd, "[INT32:%p:%d]",
916 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
918 fprintf (trFd, "[%s.%s:%p]",
919 klass->name_space, klass->name, obj);
920 fprintf (trFd, "], ");
922 fprintf (trFd, "[OBJECT:null], ");
927 fprintf (trFd, "[PTR:%p], ", *((gpointer **) (curParm)));
929 case MONO_TYPE_FNPTR :
930 fprintf (trFd, "[FNPTR:%p], ", *((gpointer **) (curParm)));
932 case MONO_TYPE_ARRAY :
933 fprintf (trFd, "[ARRAY:%p], ", *((gpointer **) (curParm)));
935 case MONO_TYPE_SZARRAY :
936 fprintf (trFd, "[SZARRAY:%p], ", *((gpointer **) (curParm)));
939 fprintf (trFd, "[INT8:%ld], ", *((gint64 *) (curParm)));
942 fprintf (trFd, "[FLOAT4:%g], ", *((float *) (curParm)));
945 fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
947 case MONO_TYPE_VALUETYPE : {
949 MonoMarshalType *info;
951 if (type->data.klass->enumtype) {
952 simpleType = mono_class_enum_basetype (type->data.klass)->type;
953 fprintf (trFd, "{VALUETYPE} - ");
957 info = mono_marshal_load_type_info (type->data.klass);
959 if ((info->native_size == sizeof(float)) &&
960 (info->num_fields == 1) &&
961 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
962 fprintf (trFd, "[FLOAT4:%f], ", *((float *) (curParm)));
966 if ((info->native_size == sizeof(double)) &&
967 (info->num_fields == 1) &&
968 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
969 fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
973 fprintf (trFd, "[VALUETYPE:");
974 for (i = 0; i < size; i++)
975 fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
976 fprintf (trFd, "], ");
979 case MONO_TYPE_TYPEDBYREF: {
981 fprintf (trFd, "[TYPEDBYREF:");
982 for (i = 0; i < size; i++)
983 fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
988 fprintf (trFd, "[%s], ",cvtMonoType(simpleType));
993 /*========================= End of Function ========================*/
995 /*------------------------------------------------------------------*/
997 /* Name - enter_method */
999 /* Function - Perform tracing of the entry to the current */
1002 /*------------------------------------------------------------------*/
1005 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
1007 int i, oParm = 0, iParm = 0;
1010 MonoMethodSignature *sig;
1019 sprintf(buf, "/tmp/mono.%d.trc.%d", getpid(), curThreadNo++);
1020 trFd = fopen(buf, "w");
1022 fname = mono_method_full_name (method, TRUE);
1024 fprintf (trFd, "ENTER: %s ", fname);
1027 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
1028 fprintf (trFd, "ip: %p sp: %p - ", (gpointer) ip, sp);
1033 sig = mono_method_signature (method);
1035 cinfo = get_call_info (NULL, NULL, sig);
1037 if (cinfo->struct_ret) {
1038 fprintf (trFd, "[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
1043 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
1044 obj = (MonoObject *) this_arg;
1045 switch(method->klass->this_arg.type) {
1046 case MONO_TYPE_VALUETYPE:
1048 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
1049 fprintf (trFd, "this:[value:%p:%016lx], ", this_arg, *value);
1051 fprintf (trFd, "this:[NULL], ");
1053 case MONO_TYPE_STRING:
1056 klass = obj->vtable->klass;
1057 if (klass == mono_defaults.string_class) {
1058 fprintf (trFd, "this:");
1059 decodeParmString((MonoString *)obj);
1061 fprintf (trFd, "this:%p[%s.%s], ",
1062 obj, klass->name_space, klass->name);
1065 fprintf (trFd, "vtable:[NULL], ");
1067 fprintf (trFd, "this:[NULL], ");
1070 fprintf (trFd, "this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1075 for (i = 0; i < sig->param_count; ++i) {
1076 ainfo = &cinfo->args[i + oParm];
1077 switch (ainfo->regtype) {
1078 case RegTypeGeneral :
1079 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1082 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1085 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1087 case RegTypeStructByVal :
1088 if (ainfo->reg != STK_BASE) {
1089 int offset = sizeof(glong) - ainfo->size;
1090 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1093 curParm = sp+ainfo->offset;
1095 if (retFitsInReg (ainfo->vtsize))
1096 decodeParm(sig->params[i],
1100 decodeParm(sig->params[i],
1101 *((char **) curParm),
1104 case RegTypeStructByAddr :
1105 if (ainfo->reg != STK_BASE)
1106 curParm = &(rParm->gr[ainfo->reg-2]);
1108 curParm = sp+ainfo->offset;
1110 decodeParm(sig->params[i],
1111 *((char **) curParm),
1116 fprintf (trFd, "???, ");
1119 fprintf (trFd, "\n");
1123 /*========================= End of Function ========================*/
1125 /*------------------------------------------------------------------*/
1127 /* Name - leave_method */
1131 /*------------------------------------------------------------------*/
1134 leave_method (MonoMethod *method, ...)
1141 va_start(ap, method);
1143 fname = mono_method_full_name (method, TRUE);
1145 fprintf (trFd, "LEAVE: %s", fname);
1148 type = mono_method_signature (method)->ret;
1151 switch (type->type) {
1152 case MONO_TYPE_VOID:
1154 case MONO_TYPE_BOOLEAN: {
1155 int val = va_arg (ap, int);
1157 fprintf (trFd, "[TRUE:%d]", val);
1159 fprintf (trFd, "[FALSE]");
1163 case MONO_TYPE_CHAR: {
1164 int val = va_arg (ap, int);
1165 fprintf (trFd, "[CHAR:%d]", val);
1168 case MONO_TYPE_I1: {
1169 int val = va_arg (ap, int);
1170 fprintf (trFd, "[INT1:%d]", val);
1173 case MONO_TYPE_U1: {
1174 int val = va_arg (ap, int);
1175 fprintf (trFd, "[UINT1:%d]", val);
1178 case MONO_TYPE_I2: {
1179 int val = va_arg (ap, int);
1180 fprintf (trFd, "[INT2:%d]", val);
1183 case MONO_TYPE_U2: {
1184 int val = va_arg (ap, int);
1185 fprintf (trFd, "[UINT2:%d]", val);
1188 case MONO_TYPE_I4: {
1189 int val = va_arg (ap, int);
1190 fprintf (trFd, "[INT4:%d]", val);
1193 case MONO_TYPE_U4: {
1194 int val = va_arg (ap, int);
1195 fprintf (trFd, "[UINT4:%d]", val);
1199 gint64 val = va_arg (ap, gint64);
1200 fprintf (trFd, "[INT:%ld]", val);
1201 fprintf (trFd, "]");
1205 gint64 val = va_arg (ap, gint64);
1206 fprintf (trFd, "[UINT:%lu]", val);
1207 fprintf (trFd, "]");
1210 case MONO_TYPE_STRING: {
1211 MonoString *s = va_arg (ap, MonoString *);
1214 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1215 decodeParmString (s);
1217 fprintf (trFd, "[STRING:null], ");
1220 case MONO_TYPE_CLASS:
1221 case MONO_TYPE_OBJECT: {
1222 MonoObject *o = va_arg (ap, MonoObject *);
1224 if ((o) && (o->vtable)) {
1225 if (o->vtable->klass == mono_defaults.boolean_class) {
1226 fprintf (trFd, "[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1227 } else if (o->vtable->klass == mono_defaults.int32_class) {
1228 fprintf (trFd, "[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1229 } else if (o->vtable->klass == mono_defaults.int64_class) {
1230 fprintf (trFd, "[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1232 fprintf (trFd, "[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1234 fprintf (trFd, "[OBJECT:%p]", o);
1239 case MONO_TYPE_FNPTR:
1240 case MONO_TYPE_ARRAY:
1241 case MONO_TYPE_SZARRAY: {
1242 gpointer p = va_arg (ap, gpointer);
1243 fprintf (trFd, "[result=%p]", p);
1246 case MONO_TYPE_I8: {
1247 gint64 l = va_arg (ap, gint64);
1248 fprintf (trFd, "[LONG:%ld]", l);
1251 case MONO_TYPE_U8: {
1252 guint64 l = va_arg (ap, guint64);
1253 fprintf (trFd, "[ULONG:%lu]", l);
1256 case MONO_TYPE_R4: {
1257 double f = va_arg (ap, double);
1258 fprintf (trFd, "[FLOAT4:%g]\n", f);
1261 case MONO_TYPE_R8: {
1262 double f = va_arg (ap, double);
1263 fprintf (trFd, "[FLOAT8:%g]\n", f);
1266 case MONO_TYPE_VALUETYPE: {
1267 MonoMarshalType *info;
1268 if (type->data.klass->enumtype) {
1269 type = mono_class_enum_basetype (type->data.klass);
1274 info = mono_marshal_load_type_info (type->data.klass);
1276 if ((info->native_size == sizeof(float)) &&
1277 (info->num_fields == 1) &&
1278 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1279 double f = va_arg (ap, double);
1280 fprintf (trFd, "[FLOAT4:%g]\n", (double) f);
1284 if ((info->native_size == sizeof(double)) &&
1285 (info->num_fields == 1) &&
1286 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1287 double f = va_arg (ap, double);
1288 fprintf (trFd, "[FLOAT8:%g]\n", f);
1292 size = mono_type_size (type, &align);
1295 guint32 p = va_arg (ap, guint32);
1296 fprintf (trFd, "[%02x]\n",p);
1300 guint32 p = va_arg (ap, guint32);
1301 fprintf (trFd, "[%04x]\n",p);
1305 guint32 p = va_arg (ap, guint32);
1306 fprintf (trFd, "[%08x]\n",p);
1310 guint64 p = va_arg (ap, guint64);
1311 fprintf (trFd, "[%016lx]\n",p);
1315 gpointer p = va_arg (ap, gpointer);
1316 fprintf (trFd, "[VALUETYPE] %p\n",p);
1322 case MONO_TYPE_TYPEDBYREF: {
1323 guint8 *p = va_arg (ap, gpointer);
1325 size = mono_type_size (type, &align);
1331 fprintf (trFd, "[");
1332 for (j = 0; p && j < size; j++)
1333 fprintf (trFd, "%02x,", p [j]);
1334 fprintf (trFd, "]\n");
1337 fprintf (trFd, "[TYPEDBYREF]\n");
1341 case MONO_TYPE_GENERICINST: {
1342 fprintf (trFd, "[GENERICINST]\n");
1345 case MONO_TYPE_MVAR: {
1346 fprintf (trFd, "[MVAR]\n");
1349 case MONO_TYPE_CMOD_REQD: {
1350 fprintf (trFd, "[CMOD_REQD]\n");
1353 case MONO_TYPE_CMOD_OPT: {
1354 fprintf (trFd, "[CMOD_OPT]\n");
1357 case MONO_TYPE_INTERNAL: {
1358 fprintf (trFd, "[INTERNAL]\n");
1362 fprintf (trFd, "(unknown return type %x)",
1363 mono_method_signature (method)->ret->type);
1366 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1367 fprintf (trFd, " ip: %p\n", (gpointer) ip);
1371 /*========================= End of Function ========================*/
1373 /*------------------------------------------------------------------*/
1375 /* Name - mono_arch_cpu_init */
1377 /* Function - Perform CPU specific initialization to execute */
1380 /*------------------------------------------------------------------*/
1383 mono_arch_cpu_init (void)
1387 /*========================= End of Function ========================*/
1389 /*------------------------------------------------------------------*/
1391 /* Name - mono_arch_init. */
1393 /* Function - Initialize architecture specific code. */
1395 /*------------------------------------------------------------------*/
1398 mono_arch_init (void)
1402 mono_set_partial_sharing_supported (FALSE);
1403 mono_os_mutex_init_recursive (&mini_arch_mutex);
1405 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1406 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1407 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1409 code = (guint8 *) &breakpointCode;
1410 s390_basr(code, s390_r13, 0);
1412 s390_llong(code, 0);
1413 s390_lg(code, s390_r13, 0, s390_r13, 4);
1414 s390_lg(code, s390_r0, 0, s390_r13, 0);
1417 /*========================= End of Function ========================*/
1419 /*------------------------------------------------------------------*/
1421 /* Name - mono_arch_cleanup. */
1423 /* Function - Cleanup architecture specific code . */
1425 /*------------------------------------------------------------------*/
1428 mono_arch_cleanup (void)
1430 if (ss_trigger_page)
1431 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1432 if (bp_trigger_page)
1433 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1434 mono_os_mutex_destroy (&mini_arch_mutex);
1437 /*========================= End of Function ========================*/
1439 /*------------------------------------------------------------------*/
1441 /* Name - mono_arch_have_fast_tls */
1443 /* Function - Returns whether we use fast inlined thread local */
1444 /* storage managed access, instead of falling back */
1445 /* to native code. */
1447 /*------------------------------------------------------------------*/
1450 mono_arch_have_fast_tls (void)
1455 /*========================= End of Function ========================*/
1457 /*------------------------------------------------------------------*/
1459 /* Name - mono_arch_cpu_optimizations */
1461 /* Function - Returns the optimizations supported on this CPU */
1463 /*------------------------------------------------------------------*/
1466 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1470 /*----------------------------------------------------------*/
1471 /* No s390-specific optimizations yet */
1472 /*----------------------------------------------------------*/
1473 *exclude_mask = MONO_OPT_LINEARS;
1477 /*========================= End of Function ========================*/
1479 /*------------------------------------------------------------------*/
1481 /* Name - mono_arch_get_allocatable_int_vars */
1485 /*------------------------------------------------------------------*/
1488 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1493 for (i = 0; i < cfg->num_varinfo; i++) {
1494 MonoInst *ins = cfg->varinfo [i];
1495 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1498 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1501 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1502 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1505 /* we can only allocate 32 bit values */
1506 if (mono_is_regsize_var(ins->inst_vtype)) {
1507 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1508 g_assert (i == vmv->idx);
1509 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1516 /*========================= End of Function ========================*/
1518 /*------------------------------------------------------------------*/
1520 /* Name - mono_arch_global_int_regs */
1522 /* Function - Return a list of usable integer registers. */
1524 /*------------------------------------------------------------------*/
1527 mono_arch_get_global_int_regs (MonoCompile *cfg)
1530 MonoMethodHeader *header;
1533 header = cfg->header;
1534 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1535 cfg->frame_reg = s390_r11;
1538 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1540 for (i = 8; i < top; ++i) {
1541 if ((cfg->frame_reg != i) &&
1542 //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
1543 (i != MONO_ARCH_IMT_REG))
1544 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1550 /*========================= End of Function ========================*/
1552 /*------------------------------------------------------------------*/
1554 /* Name - mono_arch_flush_icache */
1556 /* Function - Flush the CPU icache. */
1558 /*------------------------------------------------------------------*/
1561 mono_arch_flush_icache (guint8 *code, gint size)
1565 /*========================= End of Function ========================*/
1567 /*------------------------------------------------------------------*/
1569 /* Name - add_general */
1571 /* Function - Determine code and stack size incremements for a */
1574 /*------------------------------------------------------------------*/
1577 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1579 if (*gr > S390_LAST_ARG_REG) {
1580 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1581 ainfo->offset = sz->stack_size;
1582 ainfo->reg = STK_BASE;
1583 ainfo->regtype = RegTypeBase;
1584 sz->stack_size += sizeof(long);
1585 sz->local_size += sizeof(long);
1586 sz->offStruct += sizeof(long);
1587 sz->code_size += 12;
1595 /*========================= End of Function ========================*/
1597 /*------------------------------------------------------------------*/
1599 /* Name - add_stackParm */
1601 /* Function - Determine code and stack size incremements for a */
1604 /*------------------------------------------------------------------*/
1607 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1609 if (*gr > S390_LAST_ARG_REG) {
1610 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1611 ainfo->reg = STK_BASE;
1612 ainfo->offset = sz->stack_size;
1613 ainfo->regtype = RegTypeStructByAddrOnStack;
1614 sz->stack_size += sizeof (gpointer);
1615 sz->parm_size += sizeof(gpointer);
1616 sz->offStruct += sizeof(gpointer);
1619 ainfo->offset = sz->stack_size;
1620 ainfo->regtype = RegTypeStructByAddr;
1623 ainfo->offparm = sz->offset;
1624 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1626 ainfo->vtsize = size;
1627 sz->parm_size += size;
1630 /*========================= End of Function ========================*/
1632 /*------------------------------------------------------------------*/
1634 /* Name - add_float */
1636 /* Function - Determine code and stack size incremements for a */
1637 /* float parameter. */
1639 /*------------------------------------------------------------------*/
1642 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1644 if ((*fr) <= S390_LAST_FPARG_REG) {
1645 ainfo->regtype = RegTypeFP;
1651 ainfo->offset = sz->stack_size;
1652 ainfo->reg = STK_BASE;
1653 ainfo->regtype = RegTypeBase;
1655 sz->stack_size += sizeof(double);
1656 sz->local_size += sizeof(double);
1657 sz->offStruct += sizeof(double);
1661 /*========================= End of Function ========================*/
1663 /*------------------------------------------------------------------*/
1665 /* Name - get_call_info */
1667 /* Function - Determine the amount of space required for code */
1668 /* and stack. In addition determine starting points */
1669 /* for stack-based parameters, and area for struct- */
1670 /* ures being returned on the stack. */
1672 /*------------------------------------------------------------------*/
1675 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1677 guint i, fr, gr, size, pstart;
1678 int nParm = sig->hasthis + sig->param_count;
1680 guint32 simpleType, align;
1681 gboolean is_pinvoke = sig->pinvoke;
1686 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1688 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1693 cinfo->struct_ret = 0;
1697 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1698 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1705 /*----------------------------------------------------------*/
1706 /* We determine the size of the return code/stack in case we*/
1707 /* need to reserve a register to be used to address a stack */
1708 /* area that the callee will use. */
1709 /*----------------------------------------------------------*/
1711 ret_type = mini_get_underlying_type (sig->ret);
1712 simpleType = ret_type->type;
1714 switch (simpleType) {
1723 case MONO_TYPE_OBJECT:
1725 case MONO_TYPE_FNPTR:
1726 cinfo->ret.reg = s390_r2;
1731 cinfo->ret.reg = s390_f0;
1736 cinfo->ret.reg = s390_r2;
1739 case MONO_TYPE_GENERICINST:
1740 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1741 cinfo->ret.reg = s390_r2;
1746 case MONO_TYPE_VALUETYPE: {
1747 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1748 if (klass->enumtype) {
1749 simpleType = mono_class_enum_basetype (klass)->type;
1752 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1754 cinfo->struct_ret = 1;
1755 cinfo->ret.size = size;
1756 cinfo->ret.vtsize = size;
1759 case MONO_TYPE_TYPEDBYREF:
1760 size = sizeof (MonoTypedRef);
1761 cinfo->struct_ret = 1;
1762 cinfo->ret.size = size;
1763 cinfo->ret.vtsize = size;
1765 case MONO_TYPE_VOID:
1768 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1774 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1775 * the first argument, allowing 'this' to be always passed in the first arg reg.
1776 * Also do this if the first argument is a reference type, since virtual calls
1777 * are sometimes made using calli without sig->hasthis set, like in the delegate
1780 if (cinfo->struct_ret && !is_pinvoke &&
1782 (sig->param_count > 0 &&
1783 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1785 cinfo->args[nParm].size = sizeof (gpointer);
1786 add_general (&gr, sz, cinfo->args + nParm);
1788 cinfo->args[nParm].size = sizeof (gpointer);
1789 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1793 cinfo->vret_arg_index = 1;
1794 cinfo->ret.reg = gr;
1799 cinfo->args[nParm].size = sizeof (gpointer);
1800 add_general (&gr, sz, cinfo->args + nParm);
1804 if (cinfo->struct_ret) {
1805 cinfo->ret.reg = gr;
1810 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1811 gr = S390_LAST_ARG_REG + 1;
1812 fr = S390_LAST_FPARG_REG + 1;
1814 /* Emit the signature cookie just before the implicit arguments */
1815 add_general (&gr, sz, &cinfo->sigCookie);
1818 /*----------------------------------------------------------*/
1819 /* We determine the size of the parameter code and stack */
1820 /* requirements by checking the types and sizes of the */
1822 /*----------------------------------------------------------*/
1824 for (i = pstart; i < sig->param_count; ++i) {
1827 /*--------------------------------------------------*/
1828 /* Handle vararg type calls. All args are put on */
1830 /*--------------------------------------------------*/
1831 if ((sig->call_convention == MONO_CALL_VARARG) &&
1832 (i == sig->sentinelpos)) {
1833 gr = S390_LAST_ARG_REG + 1;
1834 fr = S390_LAST_FPARG_REG + 1;
1835 add_general (&gr, sz, &cinfo->sigCookie);
1838 if (sig->params [i]->byref) {
1839 add_general (&gr, sz, cinfo->args+nParm);
1840 cinfo->args[nParm].size = sizeof(gpointer);
1845 ptype = mini_get_underlying_type (sig->params [i]);
1846 simpleType = ptype->type;
1847 cinfo->args[nParm].type = simpleType;
1848 switch (simpleType) {
1851 cinfo->args[nParm].size = sizeof(char);
1852 add_general (&gr, sz, cinfo->args+nParm);
1857 cinfo->args[nParm].size = sizeof(short);
1858 add_general (&gr, sz, cinfo->args+nParm);
1863 cinfo->args[nParm].size = sizeof(int);
1864 add_general (&gr, sz, cinfo->args+nParm);
1870 case MONO_TYPE_FNPTR:
1871 case MONO_TYPE_OBJECT:
1872 cinfo->args[nParm].size = sizeof(gpointer);
1873 add_general (&gr, sz, cinfo->args+nParm);
1878 cinfo->args[nParm].size = sizeof(long long);
1879 add_general (&gr, sz, cinfo->args+nParm);
1883 cinfo->args[nParm].size = sizeof(float);
1884 add_float (&fr, sz, cinfo->args+nParm);
1888 cinfo->args[nParm].size = sizeof(double);
1889 add_float (&fr, sz, cinfo->args+nParm);
1892 case MONO_TYPE_GENERICINST:
1893 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1894 cinfo->args[nParm].size = sizeof(gpointer);
1895 add_general (&gr, sz, cinfo->args+nParm);
1900 case MONO_TYPE_VALUETYPE: {
1901 MonoMarshalType *info;
1902 MonoClass *klass = mono_class_from_mono_type (ptype);
1905 size = mono_class_native_size(klass, NULL);
1907 size = mono_class_value_size(klass, NULL);
1909 if (simpleType != MONO_TYPE_GENERICINST) {
1910 info = mono_marshal_load_type_info(klass);
1912 if ((info->native_size == sizeof(float)) &&
1913 (info->num_fields == 1) &&
1914 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1915 cinfo->args[nParm].size = sizeof(float);
1916 add_float(&fr, sz, cinfo->args+nParm);
1921 if ((info->native_size == sizeof(double)) &&
1922 (info->num_fields == 1) &&
1923 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1924 cinfo->args[nParm].size = sizeof(double);
1925 add_float(&fr, sz, cinfo->args+nParm);
1931 cinfo->args[nParm].vtsize = 0;
1932 cinfo->args[nParm].size = 0;
1935 /*----------------------------------*/
1936 /* On S/390, structures of size 1, */
1937 /* 2, 4, and 8 bytes are passed in */
1938 /* (a) register(s). */
1939 /*----------------------------------*/
1945 add_general(&gr, sz, cinfo->args+nParm);
1946 cinfo->args[nParm].size = size;
1947 cinfo->args[nParm].regtype = RegTypeStructByVal;
1949 sz->local_size += sizeof(long);
1952 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1957 case MONO_TYPE_TYPEDBYREF: {
1958 int size = sizeof (MonoTypedRef);
1960 cinfo->args[nParm].vtsize = 0;
1961 cinfo->args[nParm].size = 0;
1964 /*----------------------------------*/
1965 /* On S/390, structures of size 1, */
1966 /* 2, 4, and 8 bytes are passed in */
1967 /* (a) register(s). */
1968 /*----------------------------------*/
1974 add_general(&gr, sz, cinfo->args+nParm);
1975 cinfo->args[nParm].size = size;
1976 cinfo->args[nParm].regtype = RegTypeStructByVal;
1978 sz->local_size += sizeof(long);
1981 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1987 g_error ("Can't trampoline 0x%x", ptype);
1991 /*----------------------------------------------------------*/
1992 /* Handle the case where there are no implicit arguments */
1993 /*----------------------------------------------------------*/
1994 if ((sig->call_convention == MONO_CALL_VARARG) &&
1997 (sig->param_count == sig->sentinelpos)) {
1998 gr = S390_LAST_ARG_REG + 1;
1999 fr = S390_LAST_FPARG_REG + 1;
2000 add_general (&gr, sz, &cinfo->sigCookie);
2003 /*----------------------------------------------------------*/
2004 /* If we are passing a structure back then if it won't be */
2005 /* in a register(s) then we make room at the end of the */
2006 /* parameters that may have been placed on the stack */
2007 /*----------------------------------------------------------*/
2008 if (cinfo->struct_ret) {
2009 cinfo->ret.offset = sz->stack_size;
2010 switch (cinfo->ret.size) {
2018 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
2023 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
2025 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
2030 /*========================= End of Function ========================*/
2032 /*------------------------------------------------------------------*/
2034 /* Name - mono_arch_allocate_vars */
2036 /* Function - Set var information according to the calling */
2037 /* convention for S/390. The local var stuff should */
2038 /* most likely be split in another method. */
2040 /* Parameter - @m - Compile unit. */
2042 /*------------------------------------------------------------------*/
2045 mono_arch_allocate_vars (MonoCompile *cfg)
2047 MonoMethodSignature *sig;
2048 MonoMethodHeader *header;
2051 int iParm, iVar, offset, align, size, curinst;
2052 int frame_reg = STK_BASE;
2055 header = cfg->header;
2057 cfg->flags |= MONO_CFG_HAS_SPILLUP;
2059 /*---------------------------------------------------------*/
2060 /* We use the frame register also for any method that has */
2061 /* filter clauses. This way, when the handlers are called, */
2062 /* the code will reference local variables using the frame */
2063 /* reg instead of the stack pointer: if we had to restore */
2064 /* the stack pointer, we'd corrupt the method frames that */
2065 /* are already on the stack (since filters get called */
2066 /* before stack unwinding happens) when the filter code */
2067 /* would call any method. */
2068 /*---------------------------------------------------------*/
2069 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2070 frame_reg = s390_r11;
2072 cfg->frame_reg = frame_reg;
2074 cfg->arch.bkchain_reg = -1;
2076 if (frame_reg != STK_BASE)
2077 cfg->used_int_regs |= (1LL << frame_reg);
2079 sig = mono_method_signature (cfg->method);
2081 cinfo = get_call_info (cfg, cfg->mempool, sig);
2083 if (!cinfo->struct_ret) {
2084 switch (mini_get_underlying_type (sig->ret)->type) {
2085 case MONO_TYPE_VOID:
2088 cfg->ret->opcode = OP_REGVAR;
2089 cfg->ret->dreg = s390_r2;
2094 /*--------------------------------------------------------------*/
2095 /* local vars are at a positive offset from the stack pointer */
2096 /* also note that if the function uses alloca, we use s390_r11 */
2097 /* to point at the local variables. */
2098 /* add parameter area size for called functions */
2099 /*--------------------------------------------------------------*/
2100 if (cfg->param_area == 0)
2101 offset = S390_MINIMAL_STACK_SIZE;
2103 offset = cfg->param_area;
2105 cfg->sig_cookie = 0;
2107 if (cinfo->struct_ret) {
2108 inst = cfg->vret_addr;
2109 offset = S390_ALIGN(offset, sizeof(gpointer));
2110 inst->inst_offset = offset;
2111 inst->opcode = OP_REGOFFSET;
2112 inst->inst_basereg = frame_reg;
2113 offset += sizeof(gpointer);
2114 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2115 printf ("vret_addr =");
2116 mono_print_ins (cfg->vret_addr);
2121 inst = cfg->args [0];
2122 if (inst->opcode != OP_REGVAR) {
2123 inst->opcode = OP_REGOFFSET;
2124 inst->inst_basereg = frame_reg;
2125 offset = S390_ALIGN(offset, sizeof(gpointer));
2126 inst->inst_offset = offset;
2127 offset += sizeof (gpointer);
2134 eArg = sig->param_count + sArg;
2136 if (sig->call_convention == MONO_CALL_VARARG)
2137 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2139 for (iParm = sArg; iParm < eArg; ++iParm) {
2140 inst = cfg->args [curinst];
2141 if (inst->opcode != OP_REGVAR) {
2142 switch (cinfo->args[iParm].regtype) {
2143 case RegTypeStructByAddr : {
2146 size = sizeof (gpointer);
2148 inst->opcode = OP_REGOFFSET;
2149 inst->inst_basereg = frame_reg;
2150 offset = S390_ALIGN (offset, sizeof (gpointer));
2151 inst->inst_offset = offset;
2153 /* Add a level of indirection */
2154 MONO_INST_NEW (cfg, indir, 0);
2156 inst->opcode = OP_VTARG_ADDR;
2157 inst->inst_left = indir;
2160 case RegTypeStructByAddrOnStack : {
2163 size = sizeof (gpointer);
2165 /* Similar to the == STK_BASE case below */
2166 cfg->arch.bkchain_reg = s390_r12;
2167 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2169 inst->opcode = OP_REGOFFSET;
2170 inst->dreg = mono_alloc_preg (cfg);
2171 inst->inst_basereg = cfg->arch.bkchain_reg;
2172 inst->inst_offset = cinfo->args [iParm].offset;
2174 /* Add a level of indirection */
2175 MONO_INST_NEW (cfg, indir, 0);
2177 inst->opcode = OP_VTARG_ADDR;
2178 inst->inst_left = indir;
2181 case RegTypeStructByVal :
2182 size = cinfo->args[iParm].size;
2183 offset = S390_ALIGN(offset, size);
2184 inst->opcode = OP_REGOFFSET;
2185 inst->inst_basereg = frame_reg;
2186 inst->inst_offset = offset;
2189 if (cinfo->args [iParm].reg == STK_BASE) {
2191 * These arguments are in the previous frame, so we can't
2192 * compute their offset from the current frame pointer right
2193 * now, since cfg->stack_offset is not yet known, so dedicate a
2194 * register holding the previous frame pointer.
2196 cfg->arch.bkchain_reg = s390_r12;
2197 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2199 inst->opcode = OP_REGOFFSET;
2200 inst->inst_basereg = cfg->arch.bkchain_reg;
2201 size = (cinfo->args[iParm].size < 8
2202 ? 8 - cinfo->args[iParm].size
2204 inst->inst_offset = cinfo->args [iParm].offset + size;
2205 size = sizeof (long);
2207 inst->opcode = OP_REGOFFSET;
2208 inst->inst_basereg = frame_reg;
2209 size = (cinfo->args[iParm].size < 8
2212 offset = S390_ALIGN(offset, size);
2213 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2214 inst->inst_offset = offset;
2216 inst->inst_offset = offset + (8 - size);
2220 offset += MAX(size, 8);
2225 cfg->locals_min_stack_offset = offset;
2227 curinst = cfg->locals_start;
2228 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2229 inst = cfg->varinfo [iVar];
2230 if ((inst->flags & MONO_INST_IS_DEAD) ||
2231 (inst->opcode == OP_REGVAR))
2234 /*--------------------------------------------------*/
2235 /* inst->backend.is_pinvoke indicates native sized */
2236 /* value typs this is used by the pinvoke wrappers */
2237 /* when they call functions returning structure */
2238 /*--------------------------------------------------*/
2239 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2240 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2241 (guint32 *) &align);
2243 size = mono_type_size (inst->inst_vtype, &align);
2245 offset = S390_ALIGN(offset, align);
2246 inst->inst_offset = offset;
2247 inst->opcode = OP_REGOFFSET;
2248 inst->inst_basereg = frame_reg;
2250 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2251 iVar, inst->inst_offset, size));
2254 cfg->locals_max_stack_offset = offset;
2256 /*------------------------------------------------------*/
2257 /* Allow space for the trace method stack area if needed*/
2258 /*------------------------------------------------------*/
2259 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2260 offset += S390_TRACE_STACK_SIZE;
2262 /*------------------------------------------------------*/
2263 /* Reserve space to save LMF and caller saved registers */
2264 /*------------------------------------------------------*/
2265 if (cfg->method->save_lmf)
2266 offset += sizeof (MonoLMF);
2268 /*------------------------------------------------------*/
2269 /* align the offset */
2270 /*------------------------------------------------------*/
2271 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2273 /*------------------------------------------------------*/
2274 /* Fix offsets for args whose value is in parent frame */
2275 /*------------------------------------------------------*/
2276 for (iParm = sArg; iParm < eArg; ++iParm) {
2277 inst = cfg->args [iParm];
2279 if (inst->opcode == OP_S390_STKARG) {
2280 inst->opcode = OP_REGOFFSET;
2281 inst->inst_offset += cfg->stack_offset;
2286 /*========================= End of Function ========================*/
2288 /*------------------------------------------------------------------*/
2290 /* Name - mono_arch_create_vars */
2292 /*------------------------------------------------------------------*/
2295 mono_arch_create_vars (MonoCompile *cfg)
2297 MonoMethodSignature *sig;
2300 sig = mono_method_signature (cfg->method);
2302 cinfo = get_call_info (cfg, cfg->mempool, sig);
2304 if (cinfo->struct_ret) {
2305 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2306 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2307 printf ("vret_addr = ");
2308 mono_print_ins (cfg->vret_addr);
2313 /*========================= End of Function ========================*/
2315 /*------------------------------------------------------------------*/
2317 /* Name - add_outarg_reg2. */
2319 /*------------------------------------------------------------------*/
2322 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2327 case RegTypeGeneral:
2328 MONO_INST_NEW (cfg, ins, OP_MOVE);
2329 ins->dreg = mono_alloc_ireg (cfg);
2330 ins->sreg1 = tree->dreg;
2331 MONO_ADD_INS (cfg->cbb, ins);
2332 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2335 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2336 ins->dreg = mono_alloc_freg (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, TRUE);
2342 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
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 g_assert_not_reached ();
2353 /*========================= End of Function ========================*/
2355 /*------------------------------------------------------------------*/
2357 /* Name - emit_sig_cookie. */
2359 /*------------------------------------------------------------------*/
2362 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2364 MonoMethodSignature *tmpSig;
2367 cfg->disable_aot = TRUE;
2369 /*----------------------------------------------------------*/
2370 /* mono_ArgIterator_Setup assumes the signature cookie is */
2371 /* passed first and all the arguments which were before it */
2372 /* passed on the stack after the signature. So compensate */
2373 /* by passing a different signature. */
2374 /*----------------------------------------------------------*/
2375 tmpSig = mono_metadata_signature_dup (call->signature);
2376 tmpSig->param_count -= call->signature->sentinelpos;
2377 tmpSig->sentinelpos = 0;
2378 if (tmpSig->param_count > 0)
2379 memcpy (tmpSig->params,
2380 call->signature->params + call->signature->sentinelpos,
2381 tmpSig->param_count * sizeof(MonoType *));
2383 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2384 sig_arg->dreg = mono_alloc_ireg (cfg);
2385 sig_arg->inst_p0 = tmpSig;
2386 MONO_ADD_INS (cfg->cbb, sig_arg);
2388 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2389 cinfo->sigCookie.offset, sig_arg->dreg);
2392 /*========================= End of Function ========================*/
2394 /*------------------------------------------------------------------*/
2396 /* Name - mono_arch_emit_call */
2398 /*------------------------------------------------------------------*/
2401 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2404 MonoMethodSignature *sig;
2406 int i, n, lParamArea;
2408 ArgInfo *ainfo = NULL;
2410 MonoMethodHeader *header;
2413 sig = call->signature;
2414 n = sig->param_count + sig->hasthis;
2415 DEBUG (g_print ("Call requires: %d parameters\n",n));
2417 cinfo = get_call_info (cfg, cfg->mempool, sig);
2419 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2420 cinfo->sz.parm_size + cinfo->sz.offset;
2421 call->stack_usage = MAX(stackSize, call->stack_usage);
2422 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2423 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2424 cfg->flags |= MONO_CFG_HAS_CALLS;
2426 if (cinfo->struct_ret) {
2427 MONO_INST_NEW (cfg, ins, OP_MOVE);
2428 ins->sreg1 = call->vret_var->dreg;
2429 ins->dreg = mono_alloc_preg (cfg);
2430 MONO_ADD_INS (cfg->cbb, ins);
2431 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2434 header = cfg->header;
2435 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2440 for (i = 0; i < n; ++i) {
2443 ainfo = cinfo->args + i;
2444 if (i >= sig->hasthis)
2445 t = sig->params [i - sig->hasthis];
2447 t = &mono_defaults.int_class->byval_arg;
2448 t = mini_get_underlying_type (t);
2450 in = call->args [i];
2452 if ((sig->call_convention == MONO_CALL_VARARG) &&
2454 (i == sig->sentinelpos)) {
2455 emit_sig_cookie (cfg, call, cinfo);
2458 switch (ainfo->regtype) {
2459 case RegTypeGeneral:
2460 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2463 if (MONO_TYPE_ISSTRUCT (t)) {
2464 /* Valuetype passed in one fp register */
2465 ainfo->regtype = RegTypeStructByValInFP;
2468 if (ainfo->size == 4)
2469 ainfo->regtype = RegTypeFPR4;
2470 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2473 case RegTypeStructByVal:
2474 case RegTypeStructByAddr:
2475 case RegTypeStructByAddrOnStack: {
2479 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2480 size = sizeof (MonoTypedRef);
2481 align = sizeof (gpointer);
2485 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2488 * Other backends use mono_type_stack_size (), but that
2489 * aligns the size to 8, which is larger than the size of
2490 * the source, leading to reads of invalid memory if the
2491 * source is at the end of address space.
2493 size = mono_class_value_size (in->klass, &align);
2496 g_assert (in->klass);
2498 ainfo->offparm += cinfo->sz.offStruct;
2500 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2501 ins->sreg1 = in->dreg;
2502 ins->klass = in->klass;
2503 ins->backend.size = ainfo->size;
2504 ins->inst_p0 = call;
2505 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2506 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2508 MONO_ADD_INS (cfg->cbb, ins);
2510 if (ainfo->regtype == RegTypeStructByAddr) {
2512 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2513 * use the normal OUTARG opcodes to pass the address of the location to
2516 int treg = mono_alloc_preg (cfg);
2517 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2518 frmReg, ainfo->offparm);
2519 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2520 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2521 /* The address of the valuetype is passed on the stack */
2522 int treg = mono_alloc_preg (cfg);
2523 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2524 frmReg, ainfo->offparm);
2525 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2526 ainfo->reg, ainfo->offset, treg);
2528 if (cfg->compute_gc_maps) {
2531 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2537 if (!t->byref && t->type == MONO_TYPE_R4) {
2538 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2539 STK_BASE, ainfo->offset + 4,
2541 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2542 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2543 STK_BASE, ainfo->offset,
2546 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2547 ins->inst_destbasereg = STK_BASE;
2548 ins->inst_offset = ainfo->offset;
2549 ins->sreg1 = in->dreg;
2550 MONO_ADD_INS (cfg->cbb, ins);
2554 g_assert_not_reached ();
2560 * Handle the case where there are no implicit arguments
2562 if ((sig->call_convention == MONO_CALL_VARARG) &&
2564 (i == sig->sentinelpos)) {
2565 emit_sig_cookie (cfg, call, cinfo);
2569 /*========================= End of Function ========================*/
2571 /*------------------------------------------------------------------*/
2573 /* Name - mono_arch_emit_outarg_vt */
2575 /*------------------------------------------------------------------*/
2578 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2580 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2581 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2582 int size = ins->backend.size;
2584 if (ainfo->regtype == RegTypeStructByVal) {
2586 arg->ins.sreg1 = ainfo->reg;
2587 arg->ins.opcode = OP_OUTARG_VT;
2588 arg->size = ainfo->size;
2589 arg->offset = ainfo->offset;
2590 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2592 if (ainfo->reg != STK_BASE) {
2593 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2595 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2598 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2599 int dreg = mono_alloc_freg (cfg);
2601 if (ainfo->size == 4) {
2602 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2603 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2605 g_assert (ainfo->size == 8);
2607 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2610 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2613 MonoMethodHeader *header;
2616 header = mono_method_get_header_checked (cfg->method, &error);
2617 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2618 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2623 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2624 src->dreg, 0, size);
2626 if (cfg->compute_gc_maps) {
2629 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2634 /*========================= End of Function ========================*/
2636 /*------------------------------------------------------------------*/
2638 /* Name - mono_arch_emit_setret */
2640 /*------------------------------------------------------------------*/
2643 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2645 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2648 if (ret->type == MONO_TYPE_R4) {
2649 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2651 } else if (ret->type == MONO_TYPE_R8) {
2652 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2657 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2660 /*========================= End of Function ========================*/
2662 /*------------------------------------------------------------------*/
2664 /* Name - mono_arch_instrument_mem_needs */
2666 /* Function - Allow tracing to work with this interface (with */
2667 /* an optional argument). */
2669 /*------------------------------------------------------------------*/
2672 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2674 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2676 /* split prolog-epilog requirements? */
2677 *code = 50; /* max bytes needed: check this number */
2680 /*========================= End of Function ========================*/
2682 /*------------------------------------------------------------------*/
2684 /* Name - mono_arch_instrument_prolog */
2686 /* Function - Create an "instrumented" prolog. */
2688 /*------------------------------------------------------------------*/
2691 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2692 gboolean enable_arguments)
2699 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2700 if (cfg->method->save_lmf)
2701 parmOffset -= sizeof(MonoLMF);
2702 fpOffset = parmOffset + (5*sizeof(gpointer));
2705 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2706 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2707 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2708 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2709 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2710 S390_SET (code, s390_r1, func);
2711 S390_SET (code, s390_r2, cfg->method);
2712 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2713 s390_lgr (code, s390_r4, STK_BASE);
2714 s390_aghi (code, s390_r4, cfg->stack_usage);
2715 s390_basr (code, s390_r14, s390_r1);
2716 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2717 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2718 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2719 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2720 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2725 /*========================= End of Function ========================*/
2727 /*------------------------------------------------------------------*/
2729 /* Name - mono_arch_instrument_epilog */
2731 /* Function - Create an epilog that will handle the returned */
2732 /* values used in instrumentation. */
2734 /*------------------------------------------------------------------*/
2737 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2740 int save_mode = SAVE_NONE,
2743 MonoMethod *method = cfg->method;
2744 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2746 offset = code - cfg->native_code;
2747 /*-----------------------------------------*/
2748 /* We need about 128 bytes of instructions */
2749 /*-----------------------------------------*/
2750 if (offset > (cfg->code_size - 128)) {
2751 cfg->code_size *= 2;
2752 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2753 code = cfg->native_code + offset;
2756 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2757 if (method->save_lmf)
2758 saveOffset -= sizeof(MonoLMF);
2762 case MONO_TYPE_VOID:
2763 /* special case string .ctor icall */
2764 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2765 save_mode = SAVE_ONE;
2767 save_mode = SAVE_NONE;
2771 save_mode = SAVE_ONE;
2774 save_mode = SAVE_R4;
2777 save_mode = SAVE_R8;
2779 case MONO_TYPE_VALUETYPE:
2780 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2781 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2784 save_mode = SAVE_STRUCT;
2787 save_mode = SAVE_ONE;
2791 switch (save_mode) {
2793 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2794 if (enable_arguments) {
2795 s390_lgr (code, s390_r3, s390_r2);
2799 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2800 if (enable_arguments) {
2801 s390_ldebr (code, s390_f0, s390_f0);
2805 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2808 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2809 if (enable_arguments) {
2810 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2811 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2819 S390_SET (code, s390_r1, func);
2820 S390_SET (code, s390_r2, cfg->method);
2821 s390_basr (code, s390_r14, s390_r1);
2823 switch (save_mode) {
2825 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2829 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2832 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2842 /*========================= End of Function ========================*/
2844 /*------------------------------------------------------------------*/
2846 /* Name - compare_and_branch */
2848 /* Function - Form a peephole pass at the code looking for */
2849 /* simple optimizations. */
2851 /*------------------------------------------------------------------*/
2854 compare_and_branch(MonoBasicBlock *bb, MonoInst *ins, int cc, gboolean logical)
2858 if (mono_hwcap_s390x_has_gie) {
2859 last = mono_inst_prev (ins, FILTER_IL_SEQ_POINT);
2860 ins->sreg1 = last->sreg1;
2861 ins->sreg2 = last->sreg2;
2863 switch(last->opcode) {
2866 ins->opcode = OP_S390_CLRJ;
2868 ins->opcode = OP_S390_CRJ;
2869 MONO_DELETE_INS(bb, last);
2874 ins->opcode = OP_S390_CLGRJ;
2876 ins->opcode = OP_S390_CGRJ;
2877 MONO_DELETE_INS(bb, last);
2879 case OP_ICOMPARE_IMM:
2880 ins->backend.data = (gpointer) last->inst_imm;
2882 ins->opcode = OP_S390_CLIJ;
2884 ins->opcode = OP_S390_CIJ;
2885 MONO_DELETE_INS(bb, last);
2887 case OP_COMPARE_IMM:
2888 case OP_LCOMPARE_IMM:
2889 ins->backend.data = (gpointer) last->inst_imm;
2891 ins->opcode = OP_S390_CLGIJ;
2893 ins->opcode = OP_S390_CGIJ;
2894 MONO_DELETE_INS(bb, last);
2900 /*========================= End of Function ========================*/
2902 /*------------------------------------------------------------------*/
2904 /* Name - mono_arch_peephole_pass_1 */
2906 /* Function - Form a peephole pass at the code looking for */
2907 /* simple optimizations. */
2909 /*------------------------------------------------------------------*/
2912 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2916 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2917 switch (ins->opcode) {
2920 compare_and_branch(bb, ins, S390_CC_EQ, FALSE);
2924 compare_and_branch(bb, ins, S390_CC_NE, TRUE);
2928 compare_and_branch(bb, ins, S390_CC_LT, FALSE);
2932 compare_and_branch(bb, ins, S390_CC_LT, TRUE);
2936 compare_and_branch(bb, ins, S390_CC_GT, FALSE);
2940 compare_and_branch(bb, ins, S390_CC_GT, TRUE);
2944 compare_and_branch(bb, ins, S390_CC_GE, FALSE);
2948 compare_and_branch(bb, ins, S390_CC_GE, TRUE);
2952 compare_and_branch(bb, ins, S390_CC_LE, FALSE);
2956 compare_and_branch(bb, ins, S390_CC_LE, TRUE);
2960 // mono_peephole_ins (bb, ins);
2965 /*========================= End of Function ========================*/
2967 /*------------------------------------------------------------------*/
2969 /* Name - mono_arch_peephole_pass_2 */
2971 /* Function - Form a peephole pass at the code looking for */
2972 /* simple optimizations. */
2974 /*------------------------------------------------------------------*/
2977 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2979 MonoInst *ins, *n, *last_ins = NULL;
2981 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2982 switch (ins->opcode) {
2983 case OP_LOADU4_MEMBASE:
2984 case OP_LOADI4_MEMBASE:
2985 if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG) &&
2986 ins->inst_basereg == last_ins->inst_destbasereg &&
2987 ins->inst_offset == last_ins->inst_offset) {
2988 ins->opcode = (ins->opcode == OP_LOADI4_MEMBASE) ? OP_ICONV_TO_I4 : OP_ICONV_TO_U4;
2989 ins->sreg1 = last_ins->sreg1;
2993 mono_peephole_ins (bb, ins);
2997 /*========================= End of Function ========================*/
2999 /*------------------------------------------------------------------*/
3001 /* Name - mono_arch_lowering_pass. */
3003 /*------------------------------------------------------------------*/
3006 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
3008 MonoInst *ins, *next;
3010 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
3011 switch (ins->opcode) {
3016 case OP_IDIV_UN_IMM:
3017 case OP_IREM_UN_IMM:
3022 case OP_LOCALLOC_IMM:
3023 mono_decompose_op_imm (cfg, bb, ins);
3026 if (!s390_is_imm16 (ins->inst_imm))
3027 /* This is created by the memcpy code which ignores is_inst_imm */
3028 mono_decompose_op_imm (cfg, bb, ins);
3035 bb->max_vreg = cfg->next_vreg;
3038 /*========================= End of Function ========================*/
3040 /*------------------------------------------------------------------*/
3042 /* Name - emit_float_to_int */
3044 /* Function - Create instructions which will convert a floating */
3045 /* point value to integer. */
3047 /*------------------------------------------------------------------*/
3050 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
3052 /* sreg is a float, dreg is an integer reg. */
3054 s390_cgdbr (code, dreg, 5, sreg);
3057 s390_ltgr (code, dreg, dreg);
3059 s390_oill (code, dreg, 0x80);
3060 s390_lghi (code, s390_r0, 0xff);
3061 s390_ngr (code, dreg, s390_r0);
3064 s390_ltgr (code, dreg, dreg);
3066 s390_oill (code, dreg, 0x8000);
3067 s390_llill(code, s390_r0, 0xffff);
3068 s390_ngr (code, dreg, s390_r0);
3073 S390_SET (code, s390_r13, 0x41e0000000000000llu);
3074 s390_ldgr (code, s390_f14, s390_r13);
3075 s390_ldr (code, s390_f15, sreg);
3076 s390_cdbr (code, s390_f15, s390_f14);
3077 s390_jl (code, 0); CODEPTR (code, o[0]);
3078 S390_SET (code, s390_r13, 0x41f0000000000000llu);
3079 s390_ldgr (code, s390_f14, s390_r13);
3080 s390_sdbr (code, s390_f15, s390_f14);
3081 s390_cfdbr (code, dreg, 7, s390_f15);
3083 PTRSLOT (code, o[0]);
3084 s390_cfdbr (code, dreg, 5, sreg);
3087 s390_lghi (code, s390_r0, 0xff);
3088 s390_ngr (code, dreg, s390_r0);
3091 s390_llill(code, s390_r0, 0xffff);
3092 s390_ngr (code, dreg, s390_r0);
3099 /*========================= End of Function ========================*/
3101 /*------------------------------------------------------------------*/
3103 /* Name - is_unsigned. */
3105 /* Function - Return TRUE if next opcode is checking for un- */
3108 /*------------------------------------------------------------------*/
3111 is_unsigned (MonoInst *next)
3114 (((next->opcode >= OP_IBNE_UN) &&
3115 (next->opcode <= OP_IBLT_UN)) ||
3116 ((next->opcode >= OP_LBNE_UN) &&
3117 (next->opcode <= OP_LBLT_UN)) ||
3118 ((next->opcode >= OP_COND_EXC_NE_UN) &&
3119 (next->opcode <= OP_COND_EXC_LT_UN)) ||
3120 ((next->opcode >= OP_COND_EXC_INE_UN) &&
3121 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
3122 ((next->opcode == OP_CLT_UN) ||
3123 (next->opcode == OP_CGT_UN) ||
3124 (next->opcode == OP_ICGE_UN) ||
3125 (next->opcode == OP_ICLE_UN)) ||
3126 ((next->opcode == OP_ICLT_UN) ||
3127 (next->opcode == OP_ICGT_UN) ||
3128 (next->opcode == OP_LCLT_UN) ||
3129 (next->opcode == OP_LCGT_UN))))
3135 /*========================= End of Function ========================*/
3137 /*------------------------------------------------------------------*/
3139 /* Name - mono_arch_output_basic_block */
3141 /* Function - Perform the "real" work of emitting instructions */
3142 /* that will do the work of in the basic block. */
3144 /*------------------------------------------------------------------*/
3147 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
3152 guint8 *code = cfg->native_code + cfg->code_len;
3153 guint last_offset = 0;
3156 /* we don't align basic blocks of loops on s390 */
3158 if (cfg->verbose_level > 2)
3159 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3161 MONO_BB_FOR_EACH_INS (bb, ins) {
3162 offset = code - cfg->native_code;
3164 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3166 if (offset > (cfg->code_size - max_len - 16)) {
3167 cfg->code_size *= 2;
3168 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3169 code = cfg->native_code + offset;
3172 mono_debug_record_line_number (cfg, ins, offset);
3174 switch (ins->opcode) {
3175 case OP_STOREI1_MEMBASE_IMM: {
3176 s390_lghi (code, s390_r0, ins->inst_imm);
3177 S390_LONG (code, stcy, stc, s390_r0, 0,
3178 ins->inst_destbasereg, ins->inst_offset);
3181 case OP_STOREI2_MEMBASE_IMM: {
3182 s390_lghi (code, s390_r0, ins->inst_imm);
3183 S390_LONG (code, sthy, sth, s390_r0, 0,
3184 ins->inst_destbasereg, ins->inst_offset);
3187 case OP_STOREI4_MEMBASE_IMM: {
3188 s390_lgfi (code, s390_r0, ins->inst_imm);
3189 S390_LONG (code, sty, st, s390_r0, 0,
3190 ins->inst_destbasereg, ins->inst_offset);
3193 case OP_STORE_MEMBASE_IMM:
3194 case OP_STOREI8_MEMBASE_IMM: {
3195 S390_SET (code, s390_r0, ins->inst_imm);
3196 S390_LONG (code, stg, stg, s390_r0, 0,
3197 ins->inst_destbasereg, ins->inst_offset);
3200 case OP_STOREI1_MEMBASE_REG: {
3201 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3202 ins->inst_destbasereg, ins->inst_offset);
3205 case OP_STOREI2_MEMBASE_REG: {
3206 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3207 ins->inst_destbasereg, ins->inst_offset);
3210 case OP_STOREI4_MEMBASE_REG: {
3211 S390_LONG (code, sty, st, ins->sreg1, 0,
3212 ins->inst_destbasereg, ins->inst_offset);
3215 case OP_STORE_MEMBASE_REG:
3216 case OP_STOREI8_MEMBASE_REG: {
3217 S390_LONG (code, stg, stg, ins->sreg1, 0,
3218 ins->inst_destbasereg, ins->inst_offset);
3222 g_assert_not_reached ();
3224 case OP_LOAD_MEMBASE:
3225 case OP_LOADI8_MEMBASE: {
3226 S390_LONG (code, lg, lg, ins->dreg, 0,
3227 ins->inst_basereg, ins->inst_offset);
3230 case OP_LOADI4_MEMBASE: {
3231 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3232 ins->inst_basereg, ins->inst_offset);
3235 case OP_LOADU4_MEMBASE: {
3236 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3237 ins->inst_basereg, ins->inst_offset);
3240 case OP_LOADU1_MEMBASE: {
3241 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3242 ins->inst_basereg, ins->inst_offset);
3245 case OP_LOADI1_MEMBASE: {
3246 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3247 ins->inst_basereg, ins->inst_offset);
3250 case OP_LOADU2_MEMBASE: {
3251 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3252 ins->inst_basereg, ins->inst_offset);
3255 case OP_LOADI2_MEMBASE: {
3256 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3257 ins->inst_basereg, ins->inst_offset);
3260 case OP_LCONV_TO_I1: {
3261 s390_lgbr (code, ins->dreg, ins->sreg1);
3264 case OP_LCONV_TO_I2: {
3265 s390_lghr (code, ins->dreg, ins->sreg1);
3268 case OP_LCONV_TO_U1: {
3269 s390_llgcr (code, ins->dreg, ins->sreg1);
3272 case OP_LCONV_TO_U2: {
3273 s390_llghr (code, ins->dreg, ins->sreg1);
3276 case OP_ICONV_TO_I1: {
3277 s390_lgbr (code, ins->dreg, ins->sreg1);
3280 case OP_ICONV_TO_I2: {
3281 s390_lghr (code, ins->dreg, ins->sreg1);
3284 case OP_ICONV_TO_U1: {
3285 s390_llgcr (code, ins->dreg, ins->sreg1);
3288 case OP_ICONV_TO_U2: {
3289 s390_llghr (code, ins->dreg, ins->sreg1);
3292 case OP_ICONV_TO_U4: {
3293 s390_llgfr (code, ins->dreg, ins->sreg1);
3296 case OP_ICONV_TO_I4: {
3297 s390_lgfr (code, ins->dreg, ins->sreg1);
3302 if (is_unsigned (ins->next))
3303 s390_clgr (code, ins->sreg1, ins->sreg2);
3305 s390_cgr (code, ins->sreg1, ins->sreg2);
3309 if (is_unsigned (ins->next))
3310 s390_clr (code, ins->sreg1, ins->sreg2);
3312 s390_cr (code, ins->sreg1, ins->sreg2);
3315 case OP_COMPARE_IMM:
3316 case OP_LCOMPARE_IMM: {
3317 gboolean branchUn = is_unsigned (ins->next);
3318 if ((ins->inst_imm == 0) && (!branchUn)) {
3319 s390_ltgr (code, ins->sreg1, ins->sreg1);
3321 S390_SET (code, s390_r0, ins->inst_imm);
3323 s390_clgr (code, ins->sreg1, s390_r0);
3325 s390_cgr (code, ins->sreg1, s390_r0);
3329 case OP_ICOMPARE_IMM: {
3330 gboolean branchUn = is_unsigned (ins->next);
3331 if ((ins->inst_imm == 0) && (!branchUn)) {
3332 s390_ltr (code, ins->sreg1, ins->sreg1);
3334 S390_SET (code, s390_r0, ins->inst_imm);
3336 s390_clr (code, ins->sreg1, s390_r0);
3338 s390_cr (code, ins->sreg1, s390_r0);
3343 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3345 S390_CALL_TEMPLATE (code, s390_r14);
3349 if (mono_hwcap_s390x_has_mlt) {
3350 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3353 s390_agr (code, ins->dreg, src2);
3358 if (mono_hwcap_s390x_has_mlt) {
3359 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3362 s390_agr (code, ins->dreg, src2);
3368 s390_alcgr (code, ins->dreg, src2);
3372 if (mono_hwcap_s390x_has_mlt) {
3373 if (s390_is_imm16 (ins->inst_imm)) {
3374 s390_aghik(code, ins->dreg, ins->sreg1, ins->inst_imm);
3376 S390_SET (code, s390_r0, ins->inst_imm);
3377 s390_agrk (code, ins->dreg, ins->sreg1, s390_r0);
3380 if (ins->dreg != ins->sreg1) {
3381 s390_lgr (code, ins->dreg, ins->sreg1);
3383 if (s390_is_imm16 (ins->inst_imm)) {
3384 s390_aghi (code, ins->dreg, ins->inst_imm);
3385 } else if (s390_is_imm32 (ins->inst_imm)) {
3386 s390_agfi (code, ins->dreg, ins->inst_imm);
3388 S390_SET (code, s390_r0, ins->inst_imm);
3389 s390_agr (code, ins->dreg, s390_r0);
3395 if (ins->dreg != ins->sreg1) {
3396 s390_lgr (code, ins->dreg, ins->sreg1);
3398 if (s390_is_imm32 (ins->inst_imm)) {
3399 s390_agfi (code, ins->dreg, ins->inst_imm);
3401 S390_SET (code, s390_r0, ins->inst_imm);
3402 s390_agr (code, ins->dreg, s390_r0);
3407 if (ins->dreg != ins->sreg1) {
3408 s390_lgr (code, ins->dreg, ins->sreg1);
3410 if (s390_is_imm16 (ins->inst_imm)) {
3411 s390_lghi (code, s390_r0, ins->inst_imm);
3412 s390_alcgr (code, ins->dreg, s390_r0);
3414 S390_SET (code, s390_r0, ins->inst_imm);
3415 s390_alcgr (code, ins->dreg, s390_r0);
3420 case OP_S390_IADD_OVF: {
3422 s390_ar (code, ins->dreg, src2);
3423 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3424 s390_lgfr (code, ins->dreg, ins->dreg);
3427 case OP_IADD_OVF_UN:
3428 case OP_S390_IADD_OVF_UN: {
3430 s390_algr (code, ins->dreg, src2);
3431 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3432 s390_llgfr (code, ins->dreg, ins->dreg);
3435 case OP_ADD_OVF_CARRY: {
3437 s390_lghi (code, s390_r0, 0);
3438 s390_lgr (code, s390_r1, s390_r0);
3439 s390_alcgr (code, s390_r0, s390_r1);
3440 s390_agr (code, ins->dreg, src2);
3441 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3442 s390_agr (code, ins->dreg, s390_r0);
3443 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3446 case OP_ADD_OVF_UN_CARRY: {
3448 s390_alcgr (code, ins->dreg, src2);
3449 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3453 if (mono_hwcap_s390x_has_mlt) {
3454 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3457 s390_sgr (code, ins->dreg, src2);
3462 if (mono_hwcap_s390x_has_mlt) {
3463 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3466 s390_sgr (code, ins->dreg, src2);
3472 s390_slbgr(code, ins->dreg, src2);
3476 if (ins->dreg != ins->sreg1) {
3477 s390_lgr (code, ins->dreg, ins->sreg1);
3479 if (s390_is_imm16 (-ins->inst_imm)) {
3480 s390_aghi (code, ins->dreg, -ins->inst_imm);
3481 } else if (s390_is_imm32 (-ins->inst_imm)) {
3482 s390_slgfi (code, ins->dreg, ins->inst_imm);
3484 S390_SET (code, s390_r0, ins->inst_imm);
3485 s390_slgr (code, ins->dreg, s390_r0);
3490 if (ins->dreg != ins->sreg1) {
3491 s390_lgr (code, ins->dreg, ins->sreg1);
3493 if (s390_is_imm16 (-ins->inst_imm)) {
3494 s390_aghi (code, ins->dreg, -ins->inst_imm);
3495 } else if (s390_is_imm32 (-ins->inst_imm)) {
3496 s390_slgfi (code, ins->dreg, ins->inst_imm);
3498 S390_SET (code, s390_r0, ins->inst_imm);
3499 s390_slgr (code, ins->dreg, s390_r0);
3504 if (ins->dreg != ins->sreg1) {
3505 s390_lgr (code, ins->dreg, ins->sreg1);
3507 if (s390_is_imm16 (-ins->inst_imm)) {
3508 s390_lghi (code, s390_r0, ins->inst_imm);
3509 s390_slbgr (code, ins->dreg, s390_r0);
3511 S390_SET (code, s390_r0, ins->inst_imm);
3512 s390_slbgr(code, ins->dreg, s390_r0);
3516 case OP_SUB_OVF_CARRY: {
3518 s390_lghi (code, s390_r0, 0);
3519 s390_lgr (code, s390_r1, s390_r0);
3520 s390_slbgr (code, s390_r0, s390_r1);
3521 s390_sgr (code, ins->dreg, src2);
3522 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3523 s390_agr (code, ins->dreg, s390_r0);
3524 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3527 case OP_SUB_OVF_UN_CARRY: {
3529 s390_slbgr (code, ins->dreg, src2);
3530 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3534 if (mono_hwcap_s390x_has_mlt) {
3535 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3537 if (ins->sreg1 == ins->dreg) {
3538 s390_ngr (code, ins->dreg, ins->sreg2);
3540 if (ins->sreg2 == ins->dreg) {
3541 s390_ngr (code, ins->dreg, ins->sreg1);
3543 s390_lgr (code, ins->dreg, ins->sreg1);
3544 s390_ngr (code, ins->dreg, ins->sreg2);
3551 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3552 if (mono_hwcap_s390x_has_mlt) {
3553 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3555 if (ins->dreg != ins->sreg1) {
3556 s390_lgr (code, ins->dreg, ins->sreg1);
3558 s390_ngr (code, ins->dreg, s390_r0);
3563 s390_lgr (code, s390_r1, ins->sreg1);
3564 s390_dsgr (code, s390_r0, ins->sreg2);
3565 s390_lgr (code, ins->dreg, s390_r1);
3569 s390_lgr (code, s390_r1, ins->sreg1);
3570 s390_lghi (code, s390_r0, 0);
3571 s390_dlgr (code, s390_r0, ins->sreg2);
3572 s390_lgr (code, ins->dreg, s390_r1);
3576 s390_lgr (code, s390_r1, ins->sreg1);
3577 s390_dsgr (code, s390_r0, ins->sreg2);
3578 s390_lgr (code, ins->dreg, s390_r0);
3582 if (s390_is_imm16 (ins->inst_imm)) {
3583 s390_lghi (code, s390_r13, ins->inst_imm);
3585 s390_lgfi (code, s390_r13, ins->inst_imm);
3587 s390_lgr (code, s390_r0, ins->sreg1);
3588 s390_dsgr (code, s390_r0, s390_r13);
3589 s390_lgfr (code, ins->dreg, s390_r0);
3593 s390_lgr (code, s390_r1, ins->sreg1);
3594 s390_lghi (code, s390_r0, 0);
3595 s390_dlgr (code, s390_r0, ins->sreg2);
3596 s390_lgr (code, ins->dreg, s390_r0);
3600 if (mono_hwcap_s390x_has_mlt) {
3601 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3603 if (ins->sreg1 == ins->dreg) {
3604 s390_ogr (code, ins->dreg, ins->sreg2);
3606 if (ins->sreg2 == ins->dreg) {
3607 s390_ogr (code, ins->dreg, ins->sreg1);
3609 s390_lgr (code, ins->dreg, ins->sreg1);
3610 s390_ogr (code, ins->dreg, ins->sreg2);
3617 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3618 if (mono_hwcap_s390x_has_mlt) {
3619 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3621 if (ins->dreg != ins->sreg1) {
3622 s390_lgr (code, ins->dreg, ins->sreg1);
3624 s390_ogr (code, ins->dreg, s390_r0);
3629 if (mono_hwcap_s390x_has_mlt) {
3630 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3632 if (ins->sreg1 == ins->dreg) {
3633 s390_xgr (code, ins->dreg, ins->sreg2);
3636 if (ins->sreg2 == ins->dreg) {
3637 s390_xgr (code, ins->dreg, ins->sreg1);
3640 s390_lgr (code, ins->dreg, ins->sreg1);
3641 s390_xgr (code, ins->dreg, ins->sreg2);
3648 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3649 if (mono_hwcap_s390x_has_mlt) {
3650 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3652 if (ins->dreg != ins->sreg1) {
3653 s390_lgr (code, ins->dreg, ins->sreg1);
3655 s390_xgr (code, ins->dreg, s390_r0);
3661 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3666 if (ins->sreg1 != ins->dreg) {
3667 s390_lgr (code, ins->dreg, ins->sreg1);
3669 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3674 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3679 if (ins->sreg1 != ins->dreg) {
3680 s390_lgr (code, ins->dreg, ins->sreg1);
3682 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3686 case OP_LSHR_UN_IMM: {
3687 if (ins->sreg1 != ins->dreg) {
3688 s390_lgr (code, ins->dreg, ins->sreg1);
3690 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3695 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3699 if (ins->sreg1 != ins->dreg) {
3700 s390_lgr (code, ins->dreg, ins->sreg1);
3702 s390_lghi (code, s390_r0, -1);
3703 s390_xgr (code, ins->dreg, s390_r0);
3707 s390_lcgr (code, ins->dreg, ins->sreg1);
3712 s390_msgr (code, ins->dreg, src2);
3717 if (ins->dreg != ins->sreg1) {
3718 s390_lgr (code, ins->dreg, ins->sreg1);
3720 if ((mono_hwcap_s390x_has_gie) &&
3721 (s390_is_imm32 (ins->inst_imm))) {
3722 s390_msgfi (code, ins->dreg, ins->inst_imm);
3724 if (s390_is_imm16 (ins->inst_imm)) {
3725 s390_lghi (code, s390_r13, ins->inst_imm);
3726 } else if (s390_is_imm32 (ins->inst_imm)) {
3727 s390_lgfi (code, s390_r13, ins->inst_imm);
3729 S390_SET (code, s390_r13, ins->inst_imm);
3731 s390_msgr (code, ins->dreg, s390_r13);
3737 if (mono_hwcap_s390x_has_mie2) {
3738 s390_msgrkc (code, ins->dreg, ins->sreg1, ins->sreg2);
3739 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3741 s390_ltgr (code, s390_r1, ins->sreg1);
3742 s390_jz (code, 0); CODEPTR(code, o[0]);
3743 s390_ltgr (code, s390_r0, ins->sreg2);
3745 s390_lghi (code, s390_r1, 0);
3746 s390_j (code, 0); CODEPTR(code, o[1]);
3747 s390_xgr (code, s390_r0, s390_r1);
3748 s390_msgr (code, s390_r1, ins->sreg2);
3749 s390_xgr (code, s390_r0, s390_r1);
3750 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3751 s390_ltgr (code, s390_r0, s390_r0);
3752 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3753 PTRSLOT (code, o[0]);
3754 PTRSLOT (code, o[1]);
3755 s390_lgr (code, ins->dreg, s390_r1);
3759 case OP_LMUL_OVF_UN: {
3760 s390_lghi (code, s390_r0, 0);
3761 s390_lgr (code, s390_r1, ins->sreg1);
3762 s390_mlgr (code, s390_r0, ins->sreg2);
3763 s390_ltgr (code, s390_r0, s390_r0);
3764 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3765 s390_lgr (code, ins->dreg, s390_r1);
3769 g_assert_not_reached ();
3771 s390_algr (code, ins->dreg, src2);
3776 s390_agr (code, ins->dreg, src2);
3780 g_assert_not_reached ();
3782 s390_alcgr (code, ins->dreg, src2);
3786 if (ins->dreg != ins->sreg1) {
3787 s390_lgfr (code, ins->dreg, ins->sreg1);
3789 if (s390_is_imm16 (ins->inst_imm)) {
3790 s390_aghi (code, ins->dreg, ins->inst_imm);
3792 s390_afi (code, ins->dreg, ins->inst_imm);
3797 if (ins->dreg != ins->sreg1) {
3798 s390_lgfr (code, ins->dreg, ins->sreg1);
3800 if (s390_is_imm16 (ins->inst_imm)) {
3801 s390_lghi (code, s390_r0, ins->inst_imm);
3802 s390_alcgr (code, ins->dreg, s390_r0);
3804 S390_SET (code, s390_r0, ins->inst_imm);
3805 s390_alcgr (code, ins->dreg, s390_r0);
3810 case OP_S390_LADD_OVF: {
3811 if (mono_hwcap_s390x_has_mlt) {
3812 s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3815 s390_agr (code, ins->dreg, src2);
3817 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3820 case OP_LADD_OVF_UN:
3821 case OP_S390_LADD_OVF_UN: {
3822 if (mono_hwcap_s390x_has_mlt) {
3823 s390_algrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3826 s390_algr (code, ins->dreg, src2);
3828 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3832 if (mono_hwcap_s390x_has_mlt) {
3833 s390_slgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3835 CHECK_SRCDST_NCOM_I;
3836 s390_slgr (code, ins->dreg, src2);
3841 if (mono_hwcap_s390x_has_mlt) {
3842 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3844 CHECK_SRCDST_NCOM_I;
3845 s390_sgr (code, ins->dreg, src2);
3850 CHECK_SRCDST_NCOM_I;
3851 s390_slbgr (code, ins->dreg, src2);
3855 if (ins->dreg != ins->sreg1) {
3856 s390_lgfr (code, ins->dreg, ins->sreg1);
3858 if (s390_is_imm16 (-ins->inst_imm)) {
3859 s390_aghi (code, ins->dreg, -ins->inst_imm);
3861 s390_agfi (code, ins->dreg, -ins->inst_imm);
3866 S390_SET (code, s390_r0, ins->inst_imm);
3867 s390_slgfr (code, ins->dreg, s390_r0);
3871 case OP_S390_ISUB_OVF: {
3872 if (mono_hwcap_s390x_has_mlt) {
3873 s390_srk (code, ins->dreg, ins->sreg1, ins->sreg2);
3874 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3877 s390_sr (code, ins->dreg, src2);
3878 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3879 s390_lgfr (code, ins->dreg, ins->dreg);
3883 case OP_ISUB_OVF_UN:
3884 case OP_S390_ISUB_OVF_UN: {
3885 if (mono_hwcap_s390x_has_mlt) {
3886 s390_slrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3889 s390_slr (code, ins->dreg, src2);
3891 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3892 s390_llgfr(code, ins->dreg, ins->dreg);
3896 case OP_S390_LSUB_OVF: {
3897 if (mono_hwcap_s390x_has_mlt) {
3898 s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3901 s390_sgr (code, ins->dreg, src2);
3903 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3906 case OP_LSUB_OVF_UN:
3907 case OP_S390_LSUB_OVF_UN: {
3909 s390_slgr (code, ins->dreg, src2);
3910 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3914 if (mono_hwcap_s390x_has_mlt) {
3915 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3917 CHECK_SRCDST_NCOM_I;
3918 s390_ngr (code, ins->dreg, src2);
3923 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3924 if (mono_hwcap_s390x_has_mlt) {
3925 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3927 if (ins->dreg != ins->sreg1) {
3928 s390_lgfr (code, ins->dreg, ins->sreg1);
3930 s390_ngr (code, ins->dreg, s390_r0);
3935 s390_lgfr (code, s390_r0, ins->sreg1);
3936 s390_srda (code, s390_r0, 0, 32);
3937 s390_dr (code, s390_r0, ins->sreg2);
3938 s390_lgfr (code, ins->dreg, s390_r1);
3942 s390_lgfr (code, s390_r0, ins->sreg1);
3943 s390_srdl (code, s390_r0, 0, 32);
3944 s390_dlr (code, s390_r0, ins->sreg2);
3945 s390_lgfr (code, ins->dreg, s390_r1);
3949 if (s390_is_imm16 (ins->inst_imm)) {
3950 s390_lghi (code, s390_r13, ins->inst_imm);
3952 s390_lgfi (code, s390_r13, ins->inst_imm);
3954 s390_lgfr (code, s390_r0, ins->sreg1);
3955 s390_srda (code, s390_r0, 0, 32);
3956 s390_dr (code, s390_r0, ins->sreg2);
3957 s390_lgfr (code, ins->dreg, s390_r1);
3961 s390_lgfr (code, s390_r0, ins->sreg1);
3962 s390_srda (code, s390_r0, 0, 32);
3963 s390_dr (code, s390_r0, ins->sreg2);
3964 s390_lgfr (code, ins->dreg, s390_r0);
3967 s390_lgfr (code, s390_r0, ins->sreg1);
3968 s390_srdl (code, s390_r0, 0, 32);
3969 s390_dlr (code, s390_r0, ins->sreg2);
3970 s390_lgfr (code, ins->dreg, s390_r0);
3974 if (s390_is_imm16 (ins->inst_imm)) {
3975 s390_lghi (code, s390_r13, ins->inst_imm);
3977 s390_lgfi (code, s390_r13, ins->inst_imm);
3979 s390_lgfr (code, s390_r0, ins->sreg1);
3980 s390_srda (code, s390_r0, 0, 32);
3981 s390_dr (code, s390_r0, ins->sreg2);
3982 s390_lgfr (code, ins->dreg, s390_r0);
3986 if (mono_hwcap_s390x_has_mlt) {
3987 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3990 s390_ogr (code, ins->dreg, src2);
3995 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3996 if (mono_hwcap_s390x_has_mlt) {
3997 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3999 if (ins->dreg != ins->sreg1) {
4000 s390_lgfr (code, ins->dreg, ins->sreg1);
4002 s390_ogr (code, ins->dreg, s390_r0);
4007 if (mono_hwcap_s390x_has_mlt) {
4008 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
4011 s390_xgr (code, ins->dreg, src2);
4016 S390_SET_MASK (code, s390_r0, ins->inst_imm);
4017 if (mono_hwcap_s390x_has_mlt) {
4018 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
4020 if (ins->dreg != ins->sreg1) {
4021 s390_lgfr (code, ins->dreg, ins->sreg1);
4023 s390_xgr (code, ins->dreg, s390_r0);
4029 s390_sll (code, ins->dreg, src2, 0);
4033 if (ins->sreg1 != ins->dreg) {
4034 s390_lgfr (code, ins->dreg, ins->sreg1);
4036 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4041 s390_sra (code, ins->dreg, src2, 0);
4045 if (ins->sreg1 != ins->dreg) {
4046 s390_lgfr (code, ins->dreg, ins->sreg1);
4048 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4051 case OP_ISHR_UN_IMM: {
4052 if (ins->sreg1 != ins->dreg) {
4053 s390_lgfr (code, ins->dreg, ins->sreg1);
4055 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4060 s390_srl (code, ins->dreg, src2, 0);
4064 if (ins->sreg1 != ins->dreg) {
4065 s390_lgfr (code, ins->dreg, ins->sreg1);
4067 s390_lghi (code, s390_r0, -1);
4068 s390_xgr (code, ins->dreg, s390_r0);
4072 s390_lcgr (code, ins->dreg, ins->sreg1);
4077 s390_msr (code, ins->dreg, src2);
4081 if (ins->dreg != ins->sreg1) {
4082 s390_lgfr (code, ins->dreg, ins->sreg1);
4084 if (s390_is_imm16 (ins->inst_imm)) {
4085 s390_lghi (code, s390_r0, ins->inst_imm);
4087 s390_lgfi (code, s390_r0, ins->inst_imm);
4089 s390_msr (code, ins->dreg, s390_r0);
4094 s390_ltr (code, s390_r1, ins->sreg1);
4095 s390_jz (code, 0); CODEPTR(code, o[0]);
4096 s390_ltr (code, s390_r0, ins->sreg2);
4098 s390_lhi (code, s390_r1, 0);
4099 s390_j (code, 0); CODEPTR(code, o[1]);
4100 s390_xr (code, s390_r0, s390_r1);
4101 s390_msr (code, s390_r1, ins->sreg2);
4102 s390_xr (code, s390_r0, s390_r1);
4103 s390_srl (code, s390_r0, 0, 31);
4104 s390_ltr (code, s390_r0, s390_r0);
4105 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4106 PTRSLOT (code, o[0]);
4107 PTRSLOT (code, o[1]);
4108 s390_lgfr (code, ins->dreg, s390_r1);
4111 case OP_IMUL_OVF_UN: {
4112 s390_lhi (code, s390_r0, 0);
4113 s390_lr (code, s390_r1, ins->sreg1);
4114 s390_mlr (code, s390_r0, ins->sreg2);
4115 s390_ltr (code, s390_r0, s390_r0);
4116 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4117 s390_lgfr (code, ins->dreg, s390_r1);
4122 S390_SET (code, ins->dreg, ins->inst_c0);
4126 mono_add_patch_info (cfg, code - cfg->native_code,
4127 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4128 S390_LOAD_TEMPLATE (code, ins->dreg);
4131 case OP_JUMP_TABLE: {
4132 mono_add_patch_info (cfg, code - cfg->native_code,
4133 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4134 S390_LOAD_TEMPLATE (code, ins->dreg);
4138 if (ins->dreg != ins->sreg1) {
4139 s390_lgr (code, ins->dreg, ins->sreg1);
4143 case OP_LCONV_TO_I8:
4145 s390_lgfr (code, ins->dreg, ins->sreg1);
4147 case OP_LCONV_TO_I4:
4148 s390_lgfr (code, ins->dreg, ins->sreg1);
4151 case OP_LCONV_TO_U8:
4152 case OP_LCONV_TO_U4:
4154 s390_llgfr (code, ins->dreg, ins->sreg1);
4156 case OP_LCONV_TO_OVF_U4:
4157 S390_SET (code, s390_r0, 4294967295);
4158 s390_clgr (code, ins->sreg1, s390_r0);
4159 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4160 s390_ltgr (code, ins->sreg1, ins->sreg1);
4161 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4162 s390_llgfr(code, ins->dreg, ins->sreg1);
4164 case OP_LCONV_TO_OVF_I4_UN:
4165 S390_SET (code, s390_r0, 2147483647);
4166 s390_cgr (code, ins->sreg1, s390_r0);
4167 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4168 s390_ltgr (code, ins->sreg1, ins->sreg1);
4169 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4170 s390_lgfr (code, ins->dreg, ins->sreg1);
4173 if (ins->dreg != ins->sreg1) {
4174 s390_ldr (code, ins->dreg, ins->sreg1);
4177 case OP_MOVE_F_TO_I8:
4178 s390_lgdr (code, ins->dreg, ins->sreg1);
4180 case OP_MOVE_I8_TO_F:
4181 s390_ldgr (code, ins->dreg, ins->sreg1);
4183 case OP_MOVE_F_TO_I4:
4184 s390_ledbr (code, s390_f0, ins->sreg1);
4185 s390_lgdr (code, ins->dreg, s390_f0);
4186 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
4188 case OP_MOVE_I4_TO_F:
4189 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
4190 s390_ldgr (code, ins->dreg, s390_r0);
4191 s390_ldebr (code, ins->dreg, ins->dreg);
4193 case OP_FCONV_TO_R4:
4194 s390_ledbr (code, ins->dreg, ins->sreg1);
4195 s390_ldebr (code, ins->dreg, ins->dreg);
4197 case OP_S390_SETF4RET:
4198 s390_ledbr (code, ins->dreg, ins->sreg1);
4201 if (s390_is_imm16 (ins->inst_offset)) {
4202 s390_lghi (code, s390_r13, ins->inst_offset);
4203 } else if (s390_is_imm32 (ins->inst_offset)) {
4204 s390_lgfi (code, s390_r13, ins->inst_offset);
4206 S390_SET (code, s390_r13, ins->inst_offset);
4208 s390_ear (code, s390_r1, 0);
4209 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4210 s390_ear (code, s390_r1, 1);
4211 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
4215 if (s390_is_imm16 (ins->inst_offset)) {
4216 s390_lghi (code, s390_r13, ins->inst_offset);
4217 } else if (s390_is_imm32 (ins->inst_offset)) {
4218 s390_lgfi (code, s390_r13, ins->inst_offset);
4220 S390_SET (code, s390_r13, ins->inst_offset);
4222 s390_ear (code, s390_r1, 0);
4223 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4224 s390_ear (code, s390_r1, 1);
4225 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
4229 if (cfg->method->save_lmf)
4230 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4232 if (cfg->flags & MONO_CFG_HAS_TAIL) {
4233 code = emit_load_volatile_arguments (code, cfg);
4236 code = backUpStackPtr(cfg, code);
4237 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
4238 mono_add_patch_info (cfg, code - cfg->native_code,
4239 MONO_PATCH_INFO_METHOD_JUMP,
4241 s390_jcl (code, S390_CC_UN, 0);
4244 case OP_CHECK_THIS: {
4245 /* ensure ins->sreg1 is not NULL */
4246 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
4247 s390_ltgr (code, s390_r0, s390_r0);
4248 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4252 int offset = cfg->sig_cookie + cfg->stack_usage;
4254 if (s390_is_imm16 (offset)) {
4255 s390_lghi (code, s390_r0, offset);
4256 } else if (s390_is_imm32 (offset)) {
4257 s390_lgfi (code, s390_r0, offset);
4259 S390_SET (code, s390_r0, offset);
4261 s390_agr (code, s390_r0, cfg->frame_reg);
4262 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
4266 call = (MonoCallInst*)ins;
4267 if (ins->flags & MONO_INST_HAS_METHOD)
4268 mono_add_patch_info (cfg, code-cfg->native_code,
4269 MONO_PATCH_INFO_METHOD,
4272 mono_add_patch_info (cfg, code-cfg->native_code,
4273 MONO_PATCH_INFO_ABS,
4275 S390_CALL_TEMPLATE (code, s390_r14);
4276 if (call->signature->ret->type == MONO_TYPE_R4)
4277 s390_ldebr (code, s390_f0, s390_f0);
4285 call = (MonoCallInst*)ins;
4286 if (ins->flags & MONO_INST_HAS_METHOD)
4287 mono_add_patch_info (cfg, code-cfg->native_code,
4288 MONO_PATCH_INFO_METHOD,
4291 mono_add_patch_info (cfg, code-cfg->native_code,
4292 MONO_PATCH_INFO_ABS,
4294 S390_CALL_TEMPLATE (code, s390_r14);
4297 case OP_FCALL_REG: {
4298 call = (MonoCallInst*)ins;
4299 s390_lgr (code, s390_r1, ins->sreg1);
4300 s390_basr (code, s390_r14, s390_r1);
4301 if (call->signature->ret->type == MONO_TYPE_R4)
4302 s390_ldebr (code, s390_f0, s390_f0);
4308 case OP_VOIDCALL_REG:
4310 s390_lgr (code, s390_r1, ins->sreg1);
4311 s390_basr (code, s390_r14, s390_r1);
4314 case OP_FCALL_MEMBASE: {
4315 call = (MonoCallInst*)ins;
4316 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4317 s390_basr (code, s390_r14, s390_r1);
4318 if (call->signature->ret->type == MONO_TYPE_R4)
4319 s390_ldebr (code, s390_f0, s390_f0);
4322 case OP_LCALL_MEMBASE:
4323 case OP_VCALL_MEMBASE:
4324 case OP_VCALL2_MEMBASE:
4325 case OP_VOIDCALL_MEMBASE:
4326 case OP_CALL_MEMBASE: {
4327 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4328 s390_basr (code, s390_r14, s390_r1);
4335 if (cfg->param_area == 0)
4336 alloca_skip = S390_MINIMAL_STACK_SIZE;
4338 alloca_skip = cfg->param_area;
4340 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4341 s390_lgr (code, s390_r1, ins->sreg1);
4342 if (ins->flags & MONO_INST_INIT)
4343 s390_lgr (code, s390_r0, ins->sreg1);
4344 s390_aghi (code, s390_r1, 14);
4345 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4346 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4347 if (cfg->method->save_lmf) {
4348 /*----------------------------------*/
4349 /* we have to adjust lmf ebp value */
4350 /*----------------------------------*/
4351 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4353 s390_lgr (code, s390_r13, cfg->frame_reg);
4354 if (s390_is_imm16(lmfOffset)) {
4355 s390_aghi (code, s390_r13, lmfOffset);
4356 } else if (s390_is_imm32(lmfOffset)) {
4357 s390_agfi (code, s390_r13, lmfOffset);
4359 S390_SET (code, s390_r13, lmfOffset);
4361 s390_lgr (code, s390_r14, STK_BASE);
4362 s390_sgr (code, s390_r14, s390_r1);
4363 s390_stg (code, s390_r14, 0, s390_r13,
4364 G_STRUCT_OFFSET(MonoLMF, ebp));
4366 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4367 s390_sgr (code, STK_BASE, s390_r1);
4368 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4369 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4370 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4371 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4372 if (ins->flags & MONO_INST_INIT) {
4373 s390_lgr (code, s390_r1, s390_r0);
4374 s390_lgr (code, s390_r0, ins->dreg);
4375 s390_lgr (code, s390_r14, s390_r12);
4376 s390_lghi (code, s390_r13, 0);
4377 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4379 s390_lgr (code, s390_r12, s390_r14);
4384 s390_lgr (code, s390_r2, ins->sreg1);
4385 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4386 (gpointer) "mono_arch_throw_exception");
4387 S390_CALL_TEMPLATE(code, s390_r14);
4391 s390_lgr (code, s390_r2, ins->sreg1);
4392 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4393 (gpointer) "mono_arch_rethrow_exception");
4394 S390_CALL_TEMPLATE(code, s390_r14);
4397 case OP_START_HANDLER: {
4398 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4400 S390_LONG (code, stg, stg, s390_r14, 0,
4401 spvar->inst_basereg,
4402 spvar->inst_offset);
4405 case OP_ENDFILTER: {
4406 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4408 if (ins->sreg1 != s390_r2)
4409 s390_lgr(code, s390_r2, ins->sreg1);
4410 S390_LONG (code, lg, lg, s390_r14, 0,
4411 spvar->inst_basereg,
4412 spvar->inst_offset);
4413 s390_br (code, s390_r14);
4416 case OP_ENDFINALLY: {
4417 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4419 S390_LONG (code, lg, lg, s390_r14, 0,
4420 spvar->inst_basereg,
4421 spvar->inst_offset);
4422 s390_br (code, s390_r14);
4425 case OP_CALL_HANDLER: {
4426 mono_add_patch_info (cfg, code-cfg->native_code,
4427 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4428 s390_brasl (code, s390_r14, 0);
4429 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4433 ins->inst_c0 = code - cfg->native_code;
4436 case OP_RELAXED_NOP:
4439 case OP_DUMMY_STORE:
4440 case OP_NOT_REACHED:
4444 case OP_IL_SEQ_POINT:
4445 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4447 case OP_SEQ_POINT: {
4450 if (cfg->compile_aot)
4454 * Read from the single stepping trigger page. This will cause a
4455 * SIGSEGV when single stepping is enabled.
4456 * We do this _before_ the breakpoint, so single stepping after
4457 * a breakpoint is hit will step to the next IL offset.
4459 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4460 breakpointCode.pTrigger = ss_trigger_page;
4461 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4462 code += BREAKPOINT_SIZE;
4465 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4468 * A placeholder for a possible breakpoint inserted by
4469 * mono_arch_set_breakpoint ().
4471 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4475 * Add an additional nop so skipping the bp doesn't cause the ip to point
4476 * to another IL offset.
4482 case OP_GENERIC_CLASS_INIT: {
4483 static int byte_offset = -1;
4484 static guint8 bitmask;
4487 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4489 if (byte_offset < 0)
4490 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4492 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4493 s390_jo (code, 0); CODEPTR(code, jump);
4495 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4496 "mono_generic_class_init");
4497 S390_CALL_TEMPLATE(code, s390_r14);
4499 PTRSLOT (code, jump);
4501 ins->flags |= MONO_INST_GC_CALLSITE;
4502 ins->backend.pc_offset = code - cfg->native_code;
4506 EMIT_UNCOND_BRANCH(ins);
4509 s390_br (code, ins->sreg1);
4515 s390_lghi(code, ins->dreg, 1);
4517 s390_lghi(code, ins->dreg, 0);
4523 s390_lghi(code, ins->dreg, 1);
4525 s390_lghi(code, ins->dreg, 0);
4531 s390_lghi(code, ins->dreg, 1);
4533 s390_lghi(code, ins->dreg, 0);
4539 s390_lghi(code, ins->dreg, 1);
4541 s390_lghi(code, ins->dreg, 0);
4547 s390_lghi(code, ins->dreg, 1);
4549 s390_lghi(code, ins->dreg, 0);
4553 s390_lghi(code, ins->dreg, 1);
4555 s390_lghi(code, ins->dreg, 0);
4559 s390_lghi(code, ins->dreg, 1);
4561 s390_lghi(code, ins->dreg, 0);
4565 s390_lghi(code, ins->dreg, 1);
4567 s390_lghi(code, ins->dreg, 0);
4571 s390_lghi(code, ins->dreg, 1);
4573 s390_lghi(code, ins->dreg, 0);
4577 s390_lghi(code, ins->dreg, 1);
4579 s390_lghi(code, ins->dreg, 0);
4582 case OP_COND_EXC_EQ:
4583 case OP_COND_EXC_IEQ:
4584 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4586 case OP_COND_EXC_NE_UN:
4587 case OP_COND_EXC_INE_UN:
4588 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4590 case OP_COND_EXC_LT:
4591 case OP_COND_EXC_ILT:
4592 case OP_COND_EXC_LT_UN:
4593 case OP_COND_EXC_ILT_UN:
4594 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4596 case OP_COND_EXC_GT:
4597 case OP_COND_EXC_IGT:
4598 case OP_COND_EXC_GT_UN:
4599 case OP_COND_EXC_IGT_UN:
4600 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4602 case OP_COND_EXC_GE:
4603 case OP_COND_EXC_IGE:
4604 case OP_COND_EXC_GE_UN:
4605 case OP_COND_EXC_IGE_UN:
4606 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4608 case OP_COND_EXC_LE:
4609 case OP_COND_EXC_ILE:
4610 case OP_COND_EXC_LE_UN:
4611 case OP_COND_EXC_ILE_UN:
4612 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4614 case OP_COND_EXC_OV:
4615 case OP_COND_EXC_IOV:
4616 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4618 case OP_COND_EXC_NO:
4619 case OP_COND_EXC_INO:
4620 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4623 case OP_COND_EXC_IC:
4624 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4626 case OP_COND_EXC_NC:
4627 case OP_COND_EXC_INC:
4628 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4632 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4636 EMIT_COND_BRANCH (ins, S390_CC_NE);
4642 EMIT_COND_BRANCH (ins, S390_CC_LT);
4648 EMIT_COND_BRANCH (ins, S390_CC_GT);
4654 EMIT_COND_BRANCH (ins, S390_CC_GE);
4660 EMIT_COND_BRANCH (ins, S390_CC_LE);
4664 EMIT_COMP_AND_BRANCH(ins, crj, cr);
4668 EMIT_COMP_AND_BRANCH(ins, clrj, clr);
4672 EMIT_COMP_AND_BRANCH(ins, cgrj, cgr);
4676 EMIT_COMP_AND_BRANCH(ins, clgrj, clgr);
4680 EMIT_COMP_AND_BRANCH_IMM(ins, crj, cr, ltr, FALSE);
4684 EMIT_COMP_AND_BRANCH_IMM(ins, clrj, clr, ltr, TRUE);
4688 EMIT_COMP_AND_BRANCH_IMM(ins, cgrj, cgr, ltgr, FALSE);
4692 EMIT_COMP_AND_BRANCH_IMM(ins, clgrj, clgr, ltgr, TRUE);
4695 /* floating point opcodes */
4697 if (*((double *) ins->inst_p0) == 0) {
4698 s390_lzdr (code, ins->dreg);
4700 S390_SET (code, s390_r13, ins->inst_p0);
4701 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4706 if (*((float *) ins->inst_p0) == 0) {
4707 s390_lzdr (code, ins->dreg);
4709 S390_SET (code, s390_r13, ins->inst_p0);
4710 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4714 case OP_STORER8_MEMBASE_REG: {
4715 S390_LONG (code, stdy, std, ins->sreg1, 0,
4716 ins->inst_destbasereg, ins->inst_offset);
4719 case OP_LOADR8_MEMBASE: {
4720 S390_LONG (code, ldy, ld, ins->dreg, 0,
4721 ins->inst_basereg, ins->inst_offset);
4724 case OP_STORER4_MEMBASE_REG: {
4725 s390_ledbr (code, s390_f15, ins->sreg1);
4726 S390_LONG (code, stey, ste, s390_f15, 0,
4727 ins->inst_destbasereg, ins->inst_offset);
4730 case OP_LOADR4_MEMBASE: {
4731 S390_LONG (code, ley, le, s390_f15, 0,
4732 ins->inst_basereg, ins->inst_offset);
4733 s390_ldebr (code, ins->dreg, s390_f15);
4736 case OP_ICONV_TO_R_UN: {
4737 if (mono_hwcap_s390x_has_fpe) {
4738 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4740 s390_llgfr (code, s390_r0, ins->sreg1);
4741 s390_cdgbr (code, ins->dreg, s390_r0);
4745 case OP_LCONV_TO_R_UN: {
4746 if (mono_hwcap_s390x_has_fpe) {
4747 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4750 s390_cxgbr (code, s390_f12, ins->sreg1);
4751 s390_ltgr (code, ins->sreg1, ins->sreg1);
4752 s390_jnl (code, 0); CODEPTR(code, jump);
4753 S390_SET (code, s390_r13, 0x403f000000000000llu);
4754 s390_lgdr (code, s390_f13, s390_r13);
4755 s390_lzdr (code, s390_f15);
4756 s390_axbr (code, s390_f12, s390_f13);
4757 PTRSLOT(code, jump);
4758 s390_ldxbr (code, s390_f13, s390_f12);
4759 s390_ldr (code, ins->dreg, s390_f13);
4763 case OP_LCONV_TO_R4:
4764 case OP_ICONV_TO_R4: {
4765 s390_cegbr (code, ins->dreg, ins->sreg1);
4766 s390_ldebr (code, ins->dreg, ins->dreg);
4769 case OP_LCONV_TO_R8:
4770 case OP_ICONV_TO_R8: {
4771 s390_cdgbr (code, ins->dreg, ins->sreg1);
4774 case OP_FCONV_TO_I1:
4775 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4776 s390_ltgr (code, ins->dreg, ins->dreg);
4778 s390_oill (code, ins->dreg, 0x80);
4779 s390_lghi (code, s390_r0, 0xff);
4780 s390_ngr (code, ins->dreg, s390_r0);
4782 case OP_FCONV_TO_U1:
4783 if (mono_hwcap_s390x_has_fpe) {
4784 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4785 s390_lghi (code, s390_r0, 0xff);
4786 s390_ngr (code, ins->dreg, s390_r0);
4788 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4791 case OP_FCONV_TO_I2:
4792 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4793 s390_ltgr (code, ins->dreg, ins->dreg);
4795 s390_oill (code, ins->dreg, 0x8000);
4796 s390_llill (code, s390_r0, 0xffff);
4797 s390_ngr (code, ins->dreg, s390_r0);
4799 case OP_FCONV_TO_U2:
4800 if (mono_hwcap_s390x_has_fpe) {
4801 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4802 s390_llill (code, s390_r0, 0xffff);
4803 s390_ngr (code, ins->dreg, s390_r0);
4805 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4808 case OP_FCONV_TO_I4:
4810 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4812 case OP_FCONV_TO_U4:
4814 if (mono_hwcap_s390x_has_fpe) {
4815 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4817 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4820 case OP_FCONV_TO_I8:
4821 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4823 case OP_FCONV_TO_U8:
4824 if (mono_hwcap_s390x_has_fpe) {
4825 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4827 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4830 case OP_LCONV_TO_OVF_I: {
4831 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4833 s390_ltgr (code, ins->sreg2, ins->sreg2);
4834 s390_jnl (code, 0); CODEPTR(code, o[0]);
4835 s390_ltgr (code, ins->sreg1, ins->sreg1);
4836 s390_jnl (code, 0); CODEPTR(code, o[1]);
4837 s390_lhi (code, s390_r13, -1);
4838 s390_cgr (code, ins->sreg1, s390_r13);
4839 s390_jnz (code, 0); CODEPTR(code, o[2]);
4840 if (ins->dreg != ins->sreg2)
4841 s390_lgr (code, ins->dreg, ins->sreg2);
4842 s390_j (code, 0); CODEPTR(code, o[3]);
4843 PTRSLOT(code, o[0]);
4844 s390_jz (code, 0); CODEPTR(code, o[4]);
4845 PTRSLOT(code, o[1]);
4846 PTRSLOT(code, o[2]);
4847 mono_add_patch_info (cfg, code - cfg->native_code,
4848 MONO_PATCH_INFO_EXC, "OverflowException");
4849 s390_brasl (code, s390_r14, 0);
4850 PTRSLOT(code, o[3]);
4851 PTRSLOT(code, o[4]);
4855 s390_lpdbr (code, ins->dreg, ins->sreg1);
4859 s390_sqdbr (code, ins->dreg, ins->sreg1);
4864 s390_adbr (code, ins->dreg, src2);
4868 CHECK_SRCDST_NCOM_F;
4869 s390_sdbr (code, ins->dreg, src2);
4874 s390_mdbr (code, ins->dreg, src2);
4878 CHECK_SRCDST_NCOM_F;
4879 s390_ddbr (code, ins->dreg, src2);
4883 s390_lcdbr (code, ins->dreg, ins->sreg1);
4887 CHECK_SRCDST_NCOM_F;
4888 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4892 s390_cdbr (code, ins->sreg1, ins->sreg2);
4896 s390_cdbr (code, ins->sreg1, ins->sreg2);
4897 s390_lghi (code, ins->dreg, 1);
4899 s390_lghi (code, ins->dreg, 0);
4903 s390_cdbr (code, ins->sreg1, ins->sreg2);
4904 s390_lghi (code, ins->dreg, 1);
4906 s390_lghi (code, ins->dreg, 0);
4910 s390_cdbr (code, ins->sreg1, ins->sreg2);
4911 s390_lghi (code, ins->dreg, 1);
4913 s390_lghi (code, ins->dreg, 0);
4917 s390_cdbr (code, ins->sreg1, ins->sreg2);
4918 s390_lghi (code, ins->dreg, 1);
4920 s390_lghi (code, ins->dreg, 0);
4924 s390_cdbr (code, ins->sreg1, ins->sreg2);
4925 s390_lghi (code, ins->dreg, 1);
4927 s390_lghi (code, ins->dreg, 0);
4931 s390_cdbr (code, ins->sreg1, ins->sreg2);
4932 s390_lghi (code, ins->dreg, 1);
4934 s390_lghi (code, ins->dreg, 0);
4938 s390_cdbr (code, ins->sreg1, ins->sreg2);
4939 s390_lghi (code, ins->dreg, 1);
4941 s390_lghi (code, ins->dreg, 0);
4945 s390_cdbr (code, ins->sreg1, ins->sreg2);
4946 s390_lghi (code, ins->dreg, 1);
4948 s390_lghi (code, ins->dreg, 0);
4953 s390_jo (code, 0); CODEPTR(code, o);
4954 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4959 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4963 s390_jo (code, 0); CODEPTR(code, o);
4964 EMIT_COND_BRANCH (ins, S390_CC_LT);
4969 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4973 s390_jo (code, 0); CODEPTR(code, o);
4974 EMIT_COND_BRANCH (ins, S390_CC_GT);
4979 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4983 s390_jo (code, 0); CODEPTR(code, o);
4984 EMIT_COND_BRANCH (ins, S390_CC_GE);
4989 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4993 s390_jo (code, 0); CODEPTR(code, o);
4994 EMIT_COND_BRANCH (ins, S390_CC_LE);
4999 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
5003 s390_lhi (code, s390_r13, 0x7f);
5004 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
5005 s390_jz (code, 0); CODEPTR(code, o);
5006 mono_add_patch_info (cfg, code - cfg->native_code,
5007 MONO_PATCH_INFO_EXC, "OverflowException");
5008 s390_brasl (code, s390_r14,0);
5012 case OP_S390_MOVE: {
5013 if (ins->backend.size > 0) {
5014 if (ins->backend.size <= 256) {
5015 s390_mvc (code, ins->backend.size, ins->dreg,
5016 ins->inst_offset, ins->sreg1, ins->inst_imm);
5018 s390_lgr (code, s390_r0, ins->dreg);
5019 if (ins->inst_offset > 0) {
5020 if (s390_is_imm16 (ins->inst_offset)) {
5021 s390_aghi (code, s390_r0, ins->inst_offset);
5022 } else if (s390_is_imm32 (ins->inst_offset)) {
5023 s390_agfi (code, s390_r0, ins->inst_offset);
5025 S390_SET (code, s390_r13, ins->inst_offset);
5026 s390_agr (code, s390_r0, s390_r13);
5029 s390_lgr (code, s390_r12, ins->sreg1);
5030 if (ins->inst_imm > 0) {
5031 if (s390_is_imm16 (ins->inst_imm)) {
5032 s390_aghi (code, s390_r12, ins->inst_imm);
5033 } else if (s390_is_imm32 (ins->inst_imm)) {
5034 s390_agfi (code, s390_r12, ins->inst_imm);
5036 S390_SET (code, s390_r13, ins->inst_imm);
5037 s390_agr (code, s390_r12, s390_r13);
5040 if (s390_is_imm16 (ins->backend.size)) {
5041 s390_lghi (code, s390_r1, ins->backend.size);
5042 } else if (s390_is_imm32 (ins->inst_offset)) {
5043 s390_agfi (code, s390_r1, ins->backend.size);
5045 S390_SET (code, s390_r13, ins->backend.size);
5046 s390_agr (code, s390_r1, s390_r13);
5048 s390_lgr (code, s390_r13, s390_r1);
5049 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
5055 case OP_ATOMIC_ADD_I8: {
5056 if (mono_hwcap_s390x_has_ia) {
5057 s390_laag (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5058 s390_agr (code, ins->dreg, ins->sreg2);
5060 s390_lgr (code, s390_r1, ins->sreg2);
5061 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5062 s390_agr (code, s390_r1, s390_r0);
5063 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5064 s390_jnz (code, -10);
5065 s390_lgr (code, ins->dreg, s390_r1);
5069 case OP_ATOMIC_EXCHANGE_I8: {
5070 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5071 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5072 s390_jnz (code, -6);
5073 s390_lgr (code, ins->dreg, s390_r0);
5076 case OP_ATOMIC_ADD_I4: {
5077 if (mono_hwcap_s390x_has_ia) {
5078 s390_laa (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5079 s390_ar (code, ins->dreg, ins->sreg2);
5081 s390_lgfr(code, s390_r1, ins->sreg2);
5082 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5083 s390_agr (code, s390_r1, s390_r0);
5084 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5085 s390_jnz (code, -9);
5086 s390_lgfr(code, ins->dreg, s390_r1);
5090 case OP_ATOMIC_EXCHANGE_I4: {
5091 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5092 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5093 s390_jnz (code, -4);
5094 s390_lgfr(code, ins->dreg, s390_r0);
5097 case OP_S390_BKCHAIN: {
5098 s390_lgr (code, ins->dreg, ins->sreg1);
5099 if (s390_is_imm16 (cfg->stack_offset)) {
5100 s390_aghi (code, ins->dreg, cfg->stack_offset);
5101 } else if (s390_is_imm32 (cfg->stack_offset)) {
5102 s390_agfi (code, ins->dreg, cfg->stack_offset);
5104 S390_SET (code, s390_r13, cfg->stack_offset);
5105 s390_agr (code, ins->dreg, s390_r13);
5109 case OP_MEMORY_BARRIER:
5112 case OP_GC_SAFE_POINT: {
5115 g_assert (mono_threads_is_coop_enabled ());
5117 s390_ltg (code, s390_r0, 0, ins->sreg1, 0);
5118 s390_jz (code, 0); CODEPTR(code, br);
5119 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
5120 mono_threads_state_poll);
5121 S390_CALL_TEMPLATE (code, s390_r14);
5125 case OP_GC_LIVENESS_DEF:
5126 case OP_GC_LIVENESS_USE:
5127 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
5128 ins->backend.pc_offset = code - cfg->native_code;
5130 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
5131 ins->backend.pc_offset = code - cfg->native_code;
5132 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
5134 #ifdef MONO_ARCH_SIMD_INTRINSICS
5136 s390x_addps (code, ins->sreg1, ins->sreg2);
5139 s390x_divps (code, ins->sreg1, ins->sreg2);
5142 s390x_mulps (code, ins->sreg1, ins->sreg2);
5145 s390x_subps (code, ins->sreg1, ins->sreg2);
5148 s390x_maxps (code, ins->sreg1, ins->sreg2);
5151 s390x_minps (code, ins->sreg1, ins->sreg2);
5154 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5155 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5158 s390x_andps (code, ins->sreg1, ins->sreg2);
5161 s390x_andnps (code, ins->sreg1, ins->sreg2);
5164 s390x_orps (code, ins->sreg1, ins->sreg2);
5167 s390x_xorps (code, ins->sreg1, ins->sreg2);
5170 s390x_sqrtps (code, ins->dreg, ins->sreg1);
5173 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
5176 s390x_rcpps (code, ins->dreg, ins->sreg1);
5179 s390x_addsubps (code, ins->sreg1, ins->sreg2);
5182 s390x_haddps (code, ins->sreg1, ins->sreg2);
5185 s390x_hsubps (code, ins->sreg1, ins->sreg2);
5188 s390x_movshdup (code, ins->dreg, ins->sreg1);
5191 s390x_movsldup (code, ins->dreg, ins->sreg1);
5194 case OP_PSHUFLEW_HIGH:
5195 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5196 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5198 case OP_PSHUFLEW_LOW:
5199 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5200 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5203 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5204 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5207 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5208 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5211 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
5212 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5216 s390x_addpd (code, ins->sreg1, ins->sreg2);
5219 s390x_divpd (code, ins->sreg1, ins->sreg2);
5222 s390x_mulpd (code, ins->sreg1, ins->sreg2);
5225 s390x_subpd (code, ins->sreg1, ins->sreg2);
5228 s390x_maxpd (code, ins->sreg1, ins->sreg2);
5231 s390x_minpd (code, ins->sreg1, ins->sreg2);
5234 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5235 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5238 s390x_andpd (code, ins->sreg1, ins->sreg2);
5241 s390x_andnpd (code, ins->sreg1, ins->sreg2);
5244 s390x_orpd (code, ins->sreg1, ins->sreg2);
5247 s390x_xorpd (code, ins->sreg1, ins->sreg2);
5250 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
5253 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
5256 s390x_haddpd (code, ins->sreg1, ins->sreg2);
5259 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
5262 s390x_movddup (code, ins->dreg, ins->sreg1);
5265 case OP_EXTRACT_MASK:
5266 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
5270 s390x_pand (code, ins->sreg1, ins->sreg2);
5273 s390x_por (code, ins->sreg1, ins->sreg2);
5276 s390x_pxor (code, ins->sreg1, ins->sreg2);
5280 s390x_paddb (code, ins->sreg1, ins->sreg2);
5283 s390x_paddw (code, ins->sreg1, ins->sreg2);
5286 s390x_paddd (code, ins->sreg1, ins->sreg2);
5289 s390x_paddq (code, ins->sreg1, ins->sreg2);
5293 s390x_psubb (code, ins->sreg1, ins->sreg2);
5296 s390x_psubw (code, ins->sreg1, ins->sreg2);
5299 s390x_psubd (code, ins->sreg1, ins->sreg2);
5302 s390x_psubq (code, ins->sreg1, ins->sreg2);
5306 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
5309 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
5312 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
5316 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
5319 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
5322 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
5326 s390x_pavgb (code, ins->sreg1, ins->sreg2);
5329 s390x_pavgw (code, ins->sreg1, ins->sreg2);
5333 s390x_pminub (code, ins->sreg1, ins->sreg2);
5336 s390x_pminuw (code, ins->sreg1, ins->sreg2);
5339 s390x_pminud (code, ins->sreg1, ins->sreg2);
5343 s390x_pminsb (code, ins->sreg1, ins->sreg2);
5346 s390x_pminsw (code, ins->sreg1, ins->sreg2);
5349 s390x_pminsd (code, ins->sreg1, ins->sreg2);
5353 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
5356 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
5359 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
5362 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
5366 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
5369 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5372 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5375 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5378 case OP_PSUM_ABS_DIFF:
5379 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5382 case OP_UNPACK_LOWB:
5383 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5385 case OP_UNPACK_LOWW:
5386 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5388 case OP_UNPACK_LOWD:
5389 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5391 case OP_UNPACK_LOWQ:
5392 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5394 case OP_UNPACK_LOWPS:
5395 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5397 case OP_UNPACK_LOWPD:
5398 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5401 case OP_UNPACK_HIGHB:
5402 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5404 case OP_UNPACK_HIGHW:
5405 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5407 case OP_UNPACK_HIGHD:
5408 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5410 case OP_UNPACK_HIGHQ:
5411 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5413 case OP_UNPACK_HIGHPS:
5414 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5416 case OP_UNPACK_HIGHPD:
5417 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5421 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5424 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5427 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5430 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5433 case OP_PADDB_SAT_UN:
5434 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5436 case OP_PSUBB_SAT_UN:
5437 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5439 case OP_PADDW_SAT_UN:
5440 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5442 case OP_PSUBW_SAT_UN:
5443 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5447 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5450 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5453 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5456 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5460 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5463 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5466 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5468 case OP_PMULW_HIGH_UN:
5469 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5472 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5476 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5479 s390x_psrlw (code, ins->dreg, ins->sreg2);
5483 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5486 s390x_psraw (code, ins->dreg, ins->sreg2);
5490 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5493 s390x_psllw (code, ins->dreg, ins->sreg2);
5497 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5500 s390x_psrld (code, ins->dreg, ins->sreg2);
5504 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5507 s390x_psrad (code, ins->dreg, ins->sreg2);
5511 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5514 s390x_pslld (code, ins->dreg, ins->sreg2);
5518 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5521 s390x_psrlq (code, ins->dreg, ins->sreg2);
5524 /*TODO: This is appart of the sse spec but not added
5526 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5529 s390x_psraq (code, ins->dreg, ins->sreg2);
5534 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5537 s390x_psllq (code, ins->dreg, ins->sreg2);
5540 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5543 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5546 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5549 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5552 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5555 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5558 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5561 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5565 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5568 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5572 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5573 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5575 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5580 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5582 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5583 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5587 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5589 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5590 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5591 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5595 amd64_movhlps (code, ins->dreg, ins->sreg1);
5597 s390x_movsd (code, ins->dreg, ins->sreg1);
5600 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5602 case OP_EXTRACTX_U2:
5603 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5605 case OP_INSERTX_U1_SLOW:
5606 /*sreg1 is the extracted ireg (scratch)
5607 /sreg2 is the to be inserted ireg (scratch)
5608 /dreg is the xreg to receive the value*/
5610 /*clear the bits from the extracted word*/
5611 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5612 /*shift the value to insert if needed*/
5613 if (ins->inst_c0 & 1)
5614 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5615 /*join them together*/
5616 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5617 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5619 case OP_INSERTX_I4_SLOW:
5620 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5621 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5622 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5624 case OP_INSERTX_I8_SLOW:
5625 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5627 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5629 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5632 case OP_INSERTX_R4_SLOW:
5633 switch (ins->inst_c0) {
5636 s390x_movss (code, ins->dreg, ins->sreg2);
5638 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5641 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5643 s390x_movss (code, ins->dreg, ins->sreg2);
5645 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5646 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5649 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5651 s390x_movss (code, ins->dreg, ins->sreg2);
5653 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5654 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5657 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5659 s390x_movss (code, ins->dreg, ins->sreg2);
5661 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5662 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5666 case OP_INSERTX_R8_SLOW:
5668 amd64_movlhps (code, ins->dreg, ins->sreg2);
5670 s390x_movsd (code, ins->dreg, ins->sreg2);
5672 case OP_STOREX_MEMBASE_REG:
5673 case OP_STOREX_MEMBASE:
5674 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5676 case OP_LOADX_MEMBASE:
5677 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5679 case OP_LOADX_ALIGNED_MEMBASE:
5680 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5682 case OP_STOREX_ALIGNED_MEMBASE_REG:
5683 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5685 case OP_STOREX_NTA_MEMBASE_REG:
5686 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5688 case OP_PREFETCH_MEMBASE:
5689 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5693 /*FIXME the peephole pass should have killed this*/
5694 if (ins->dreg != ins->sreg1)
5695 s390x_movaps (code, ins->dreg, ins->sreg1);
5698 s390x_pxor (code, ins->dreg, ins->dreg);
5700 case OP_ICONV_TO_R4_RAW:
5701 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5704 case OP_FCONV_TO_R8_X:
5705 s390x_movsd (code, ins->dreg, ins->sreg1);
5708 case OP_XCONV_R8_TO_I4:
5709 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5710 switch (ins->backend.source_opcode) {
5711 case OP_FCONV_TO_I1:
5712 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5714 case OP_FCONV_TO_U1:
5715 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5717 case OP_FCONV_TO_I2:
5718 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5720 case OP_FCONV_TO_U2:
5721 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5727 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5728 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5729 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5732 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5733 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5736 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5737 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5741 s390x_movsd (code, ins->dreg, ins->sreg1);
5743 s390x_movsd (code, ins->dreg, ins->sreg1);
5744 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5746 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5749 s390x_movsd (code, ins->dreg, ins->sreg1);
5750 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5754 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5755 g_assert_not_reached ();
5758 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5759 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5760 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5761 g_assert_not_reached ();
5764 last_offset = offset;
5767 cfg->code_len = code - cfg->native_code;
5770 /*========================= End of Function ========================*/
5772 /*------------------------------------------------------------------*/
5774 /* Name - mono_arch_register_lowlevel_calls */
5776 /* Function - Register routines to help with --trace operation. */
5778 /*------------------------------------------------------------------*/
5781 mono_arch_register_lowlevel_calls (void)
5785 /*========================= End of Function ========================*/
5787 /*------------------------------------------------------------------*/
5789 /* Name - mono_arch_patch_code */
5791 /* Function - Process the patch data created during the */
5792 /* instruction build process. This resolves jumps, */
5793 /* calls, variables etc. */
5795 /*------------------------------------------------------------------*/
5798 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5799 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5802 MonoJumpInfo *patch_info;
5806 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5807 unsigned char *ip = patch_info->ip.i + code;
5808 gconstpointer target = NULL;
5810 target = mono_resolve_patch_target (method, domain, code,
5811 patch_info, run_cctors, error);
5812 return_if_nok (error);
5814 switch (patch_info->type) {
5815 case MONO_PATCH_INFO_IP:
5816 case MONO_PATCH_INFO_LDSTR:
5817 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5818 case MONO_PATCH_INFO_LDTOKEN:
5819 case MONO_PATCH_INFO_EXC:
5820 s390_patch_addr (ip, (guint64) target);
5822 case MONO_PATCH_INFO_METHOD:
5823 case MONO_PATCH_INFO_INTERNAL_METHOD:
5824 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5825 case MONO_PATCH_INFO_RGCTX_FETCH:
5826 case MONO_PATCH_INFO_ABS: {
5827 S390_EMIT_CALL (ip, target);
5830 case MONO_PATCH_INFO_SWITCH:
5831 /*----------------------------------*/
5832 /* ip points at the basr r13,0/j +4 */
5833 /* instruction the vtable value */
5834 /* follows this (i.e. ip+6) */
5835 /*----------------------------------*/
5836 S390_EMIT_LOAD (ip, target);
5838 case MONO_PATCH_INFO_METHODCONST:
5839 case MONO_PATCH_INFO_CLASS:
5840 case MONO_PATCH_INFO_IMAGE:
5841 case MONO_PATCH_INFO_FIELD:
5842 case MONO_PATCH_INFO_IID:
5843 case MONO_PATCH_INFO_EXC_NAME:
5844 target = S390_RELATIVE(target, ip);
5845 s390_patch_rel (ip, (guint64) target);
5847 case MONO_PATCH_INFO_R4:
5848 case MONO_PATCH_INFO_R8:
5849 case MONO_PATCH_INFO_METHOD_REL:
5850 g_assert_not_reached ();
5853 target = S390_RELATIVE(target, ip);
5855 s390_patch_rel (ip, (guint64) target);
5860 /*========================= End of Function ========================*/
5862 /*------------------------------------------------------------------*/
5864 /* Name - emit_load_volatile_arguments */
5866 /* Function - Emit the instructions to reload parameter regist- */
5867 /* registers for use with "tail" operations. */
5869 /* The register loading operations performed here */
5870 /* are the mirror of the store operations performed */
5871 /* in mono_arch_emit_prolog and need to be kept in */
5872 /* synchronization with it. */
5874 /*------------------------------------------------------------------*/
5877 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5880 MonoMethod *method = cfg->method;
5881 MonoMethodSignature *sig = mono_method_signature(method);
5885 cinfo = get_call_info (NULL, NULL, sig);
5887 if (cinfo->struct_ret) {
5888 ArgInfo *ainfo = &cinfo->ret;
5889 inst = cfg->vret_addr;
5890 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5893 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5894 ArgInfo *ainfo = cinfo->args + i;
5895 inst = cfg->args [pos];
5897 if (inst->opcode == OP_REGVAR) {
5898 if (ainfo->regtype == RegTypeGeneral)
5899 s390_lgr (code, ainfo->reg, inst->dreg);
5900 else if (ainfo->regtype == RegTypeFP) {
5901 if (inst->dreg != ainfo->reg) {
5902 if (ainfo->size == 4) {
5903 s390_ldebr (code, ainfo->reg, inst->dreg);
5905 s390_ldr (code, ainfo->reg, inst->dreg);
5909 else if (ainfo->regtype == RegTypeBase) {
5911 g_assert_not_reached ();
5913 if (ainfo->regtype == RegTypeGeneral) {
5914 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5915 g_assert_not_reached();
5916 switch (ainfo->size) {
5918 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5921 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5924 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5927 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5930 } else if (ainfo->regtype == RegTypeBase) {
5931 } else if (ainfo->regtype == RegTypeFP) {
5932 if (ainfo->size == 8)
5933 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5934 else if (ainfo->size == 4)
5935 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5937 g_assert_not_reached ();
5938 } else if (ainfo->regtype == RegTypeStructByVal) {
5939 if (ainfo->reg != STK_BASE) {
5940 switch (ainfo->size) {
5942 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5945 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5948 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5951 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5955 } else if (ainfo->regtype == RegTypeStructByAddr) {
5956 if (ainfo->reg != STK_BASE) {
5957 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5960 g_assert_not_reached ();
5968 /*========================= End of Function ========================*/
5970 /*------------------------------------------------------------------*/
5972 /* Name - mono_arch_emit_prolog */
5974 /* Function - Create the instruction sequence for a function */
5977 /*------------------------------------------------------------------*/
5980 mono_arch_emit_prolog (MonoCompile *cfg)
5982 MonoMethod *method = cfg->method;
5984 MonoMethodSignature *sig;
5986 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5995 cfg->code_size = 512;
5997 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5999 cfg->code_size += 256;
6002 if (method->save_lmf)
6003 cfg->code_size += 200;
6005 cfg->native_code = code = g_malloc (cfg->code_size);
6007 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
6008 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
6009 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6010 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
6011 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
6013 if (cfg->arch.bkchain_reg != -1)
6014 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
6016 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6017 cfg->used_int_regs |= 1 << 11;
6020 alloc_size = cfg->stack_offset;
6022 cfg->stack_usage = cfa_offset = alloc_size;
6023 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
6024 s390_lgr (code, s390_r11, STK_BASE);
6025 if (s390_is_imm16 (alloc_size)) {
6026 s390_aghi (code, STK_BASE, -alloc_size);
6027 } else if (s390_is_imm32 (alloc_size)) {
6028 s390_agfi (code, STK_BASE, -alloc_size);
6030 int stackSize = alloc_size;
6031 while (stackSize > INT_MAX) {
6032 s390_agfi (code, STK_BASE, -INT_MAX);
6033 stackSize -= INT_MAX;
6035 s390_agfi (code, STK_BASE, -stackSize);
6037 s390_stg (code, s390_r11, 0, STK_BASE, 0);
6039 if (cfg->frame_reg != STK_BASE)
6040 s390_lgr (code, s390_r11, STK_BASE);
6042 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
6044 /* store runtime generic context */
6045 if (cfg->rgctx_var) {
6046 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
6048 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
6049 cfg->rgctx_var->inst_basereg,
6050 cfg->rgctx_var->inst_offset);
6053 /* compute max_offset in order to use short forward jumps
6054 * we always do it on s390 because the immediate displacement
6055 * for jumps is too small
6058 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6060 bb->max_offset = max_offset;
6062 MONO_BB_FOR_EACH_INS (bb, ins)
6063 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
6066 /* load arguments allocated to register from the stack */
6067 sig = mono_method_signature (method);
6070 cinfo = get_call_info (cfg, cfg->mempool, sig);
6072 if (cinfo->struct_ret) {
6073 ArgInfo *ainfo = &cinfo->ret;
6074 inst = cfg->vret_addr;
6075 inst->backend.size = ainfo->vtsize;
6076 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6079 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6080 ArgInfo *ainfo = cinfo->args + i;
6081 inst = cfg->args [pos];
6083 if (inst->opcode == OP_VTARG_ADDR)
6084 inst = inst->inst_left;
6086 if (inst->opcode == OP_REGVAR) {
6087 if (ainfo->regtype == RegTypeGeneral)
6088 s390_lgr (code, inst->dreg, ainfo->reg);
6089 else if (ainfo->regtype == RegTypeFP) {
6090 if (inst->dreg != ainfo->reg) {
6091 if (ainfo->size == 4) {
6092 s390_ledbr (code, inst->dreg, ainfo->reg);
6094 s390_ldr (code, inst->dreg, ainfo->reg);
6098 else if (ainfo->regtype == RegTypeBase) {
6099 s390_lgr (code, s390_r13, STK_BASE);
6100 s390_aghi (code, s390_r13, alloc_size);
6101 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
6103 g_assert_not_reached ();
6105 if (cfg->verbose_level > 2)
6106 g_print ("Argument %d assigned to register %s\n",
6107 pos, mono_arch_regname (inst->dreg));
6109 if (ainfo->regtype == RegTypeGeneral) {
6110 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
6111 g_assert_not_reached();
6112 switch (ainfo->size) {
6114 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6117 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6120 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6123 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6126 } else if (ainfo->regtype == RegTypeBase) {
6127 } else if (ainfo->regtype == RegTypeFP) {
6128 if (ainfo->size == 8)
6129 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6130 else if (ainfo->size == 4)
6131 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6133 g_assert_not_reached ();
6134 } else if (ainfo->regtype == RegTypeStructByVal) {
6135 int doffset = inst->inst_offset;
6137 if (ainfo->reg != STK_BASE)
6141 s390_lgr (code, s390_r13, STK_BASE);
6142 s390_aghi (code, s390_r13, alloc_size);
6145 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
6146 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
6151 if (ainfo->reg == STK_BASE)
6152 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
6153 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
6156 if (ainfo->reg == STK_BASE)
6157 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
6158 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
6161 if (ainfo->reg == STK_BASE)
6162 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
6163 s390_st (code, reg, 0, inst->inst_basereg, doffset);
6166 if (ainfo->reg == STK_BASE)
6167 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
6168 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
6171 } else if (ainfo->regtype == RegTypeStructByAddr) {
6172 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6173 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
6175 g_assert_not_reached ();
6180 if (method->save_lmf) {
6181 /*---------------------------------------------------------------*/
6182 /* build the MonoLMF structure on the stack - see mini-s390x.h */
6183 /*---------------------------------------------------------------*/
6184 lmfOffset = alloc_size - sizeof(MonoLMF);
6186 s390_lgr (code, s390_r13, cfg->frame_reg);
6187 s390_aghi (code, s390_r13, lmfOffset);
6189 /*---------------------------------------------------------------*/
6190 /* Preserve the parameter registers while we fix up the lmf */
6191 /*---------------------------------------------------------------*/
6192 s390_stmg (code, s390_r2, s390_r6, s390_r13,
6193 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6195 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
6196 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
6197 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
6198 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
6199 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
6201 /*---------------------------------------------------------------*/
6202 /* On return from this call r2 have the address of the &lmf */
6203 /*---------------------------------------------------------------*/
6204 mono_add_patch_info (cfg, code - cfg->native_code,
6205 MONO_PATCH_INFO_INTERNAL_METHOD,
6206 (gpointer)"mono_tls_get_lmf_addr");
6207 S390_CALL_TEMPLATE(code, s390_r1);
6209 /*---------------------------------------------------------------*/
6210 /* Set lmf.lmf_addr = jit_tls->lmf */
6211 /*---------------------------------------------------------------*/
6212 s390_stg (code, s390_r2, 0, s390_r13,
6213 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
6214 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
6216 /*---------------------------------------------------------------*/
6217 /* Get current lmf */
6218 /*---------------------------------------------------------------*/
6219 s390_lg (code, s390_r0, 0, s390_r2, 0);
6221 /*---------------------------------------------------------------*/
6222 /* Set our lmf as the current lmf */
6223 /*---------------------------------------------------------------*/
6224 s390_stg (code, s390_r13, 0, s390_r2, 0);
6226 /*---------------------------------------------------------------*/
6227 /* Have our lmf.previous_lmf point to the last lmf */
6228 /*---------------------------------------------------------------*/
6229 s390_stg (code, s390_r0, 0, s390_r13,
6230 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
6231 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
6233 /*---------------------------------------------------------------*/
6234 /* save method info */
6235 /*---------------------------------------------------------------*/
6236 S390_SET (code, s390_r1, method);
6237 s390_stg (code, s390_r1, 0, s390_r13,
6238 G_STRUCT_OFFSET(MonoLMF, method));
6239 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
6241 /*---------------------------------------------------------------*/
6242 /* save the current IP */
6243 /*---------------------------------------------------------------*/
6244 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
6245 s390_basr (code, s390_r1, 0);
6246 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
6247 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
6248 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
6250 /*---------------------------------------------------------------*/
6251 /* Save general and floating point registers */
6252 /*---------------------------------------------------------------*/
6253 s390_stmg (code, s390_r2, s390_r12, s390_r13,
6254 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
6255 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
6256 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
6257 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
6258 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
6259 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
6260 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
6261 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
6262 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
6263 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
6264 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
6265 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
6267 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
6268 for (i = 0; i < 16; i++) {
6269 s390_std (code, i, 0, s390_r13,
6270 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
6271 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
6272 fpOffset += sizeof(double);
6275 /*---------------------------------------------------------------*/
6276 /* Restore the parameter registers now that we've set up the lmf */
6277 /*---------------------------------------------------------------*/
6278 s390_lmg (code, s390_r2, s390_r6, s390_r13,
6279 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6282 if (cfg->method->save_lmf)
6283 argsClobbered = TRUE;
6286 argsClobbered = TRUE;
6287 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
6291 * Optimize the common case of the first bblock making a call with the same
6292 * arguments as the method. This works because the arguments are still in their
6293 * original argument registers.
6295 if (!argsClobbered) {
6296 MonoBasicBlock *first_bb = cfg->bb_entry;
6298 int filter = FILTER_IL_SEQ_POINT;
6300 next = mono_bb_first_inst (first_bb, filter);
6301 if (!next && first_bb->next_bb) {
6302 first_bb = first_bb->next_bb;
6303 next = mono_bb_first_inst (first_bb, filter);
6306 if (first_bb->in_count > 1)
6309 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
6310 ArgInfo *ainfo = cinfo->args + i;
6311 gboolean match = FALSE;
6313 inst = cfg->args [i];
6314 if (inst->opcode != OP_REGVAR) {
6315 switch (ainfo->regtype) {
6316 case RegTypeGeneral: {
6317 if (((next->opcode == OP_LOAD_MEMBASE) ||
6318 (next->opcode == OP_LOADI4_MEMBASE)) &&
6319 next->inst_basereg == inst->inst_basereg &&
6320 next->inst_offset == inst->inst_offset) {
6321 if (next->dreg == ainfo->reg) {
6325 next->opcode = OP_MOVE;
6326 next->sreg1 = ainfo->reg;
6327 /* Only continue if the instruction doesn't change argument regs */
6328 if (next->dreg == ainfo->reg)
6338 /* Argument allocated to (non-volatile) register */
6339 switch (ainfo->regtype) {
6340 case RegTypeGeneral:
6341 if (next->opcode == OP_MOVE &&
6342 next->sreg1 == inst->dreg &&
6343 next->dreg == ainfo->reg) {
6354 next = mono_inst_next (next, filter);
6361 cfg->code_len = code - cfg->native_code;
6362 g_assert (cfg->code_len < cfg->code_size);
6367 /*========================= End of Function ========================*/
6369 /*------------------------------------------------------------------*/
6371 /* Name - mono_arch_emit_epilog */
6373 /* Function - Emit the instructions for a function epilog. */
6375 /*------------------------------------------------------------------*/
6378 mono_arch_emit_epilog (MonoCompile *cfg)
6380 MonoMethod *method = cfg->method;
6383 int max_epilog_size = 96;
6385 if (cfg->method->save_lmf)
6386 max_epilog_size += 128;
6388 if (mono_jit_trace_calls != NULL)
6389 max_epilog_size += 128;
6391 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6392 cfg->code_size *= 2;
6393 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6394 cfg->stat_code_reallocs++;
6397 code = cfg->native_code + cfg->code_len;
6399 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6400 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6404 if (method->save_lmf)
6405 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6407 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6408 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6410 code = backUpStackPtr(cfg, code);
6412 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6413 s390_br (code, s390_r14);
6415 cfg->code_len = code - cfg->native_code;
6417 g_assert (cfg->code_len < cfg->code_size);
6421 /*========================= End of Function ========================*/
6423 /*------------------------------------------------------------------*/
6425 /* Name - mono_arch_emit_exceptions */
6427 /* Function - Emit the blocks to handle exception conditions. */
6429 /*------------------------------------------------------------------*/
6432 mono_arch_emit_exceptions (MonoCompile *cfg)
6434 MonoJumpInfo *patch_info;
6440 MonoClass *exc_classes [MAX_EXC];
6441 guint8 *exc_throw_start [MAX_EXC];
6443 for (patch_info = cfg->patch_info;
6445 patch_info = patch_info->next) {
6446 if (patch_info->type == MONO_PATCH_INFO_EXC)
6450 code_size = exc_count * 48;
6452 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6453 cfg->code_size *= 2;
6454 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6455 cfg->stat_code_reallocs++;
6458 code = cfg->native_code + cfg->code_len;
6460 /*---------------------------------------------------------------------*/
6461 /* Add code to raise exceptions */
6462 /*---------------------------------------------------------------------*/
6463 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6464 switch (patch_info->type) {
6465 case MONO_PATCH_INFO_EXC: {
6466 guint8 *ip = patch_info->ip.i + cfg->native_code;
6467 MonoClass *exc_class;
6470 /*-----------------------------------------------------*/
6471 /* Patch the branch in epilog to come here */
6472 /*-----------------------------------------------------*/
6473 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6475 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6477 patch_info->data.name);
6478 throw_ip = patch_info->ip.i;
6480 for (iExc = 0; iExc < nThrows; ++iExc)
6481 if (exc_classes [iExc] == exc_class)
6484 if (iExc < nThrows) {
6485 s390_jcl (code, S390_CC_UN,
6486 (guint64) exc_throw_start [iExc]);
6487 patch_info->type = MONO_PATCH_INFO_NONE;
6490 if (nThrows < MAX_EXC) {
6491 exc_classes [nThrows] = exc_class;
6492 exc_throw_start [nThrows] = code;
6495 /*---------------------------------------------*/
6496 /* Patch the parameter passed to the handler */
6497 /*---------------------------------------------*/
6498 S390_SET (code, s390_r2, exc_class->type_token);
6499 /*---------------------------------------------*/
6500 /* Load return address & parameter register */
6501 /*---------------------------------------------*/
6502 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6503 cfg->native_code + 8), code));
6504 /*---------------------------------------------*/
6505 /* Reuse the current patch to set the jump */
6506 /*---------------------------------------------*/
6507 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6508 patch_info->data.name = "mono_arch_throw_corlib_exception";
6509 patch_info->ip.i = code - cfg->native_code;
6510 S390_BR_TEMPLATE (code, s390_r1);
6520 cfg->code_len = code - cfg->native_code;
6522 g_assert (cfg->code_len < cfg->code_size);
6526 /*========================= End of Function ========================*/
6528 /*------------------------------------------------------------------*/
6530 /* Name - mono_arch_finish_init */
6532 /* Function - Setup the JIT's Thread Level Specific Data. */
6534 /*------------------------------------------------------------------*/
6537 mono_arch_finish_init (void)
6541 /*========================= End of Function ========================*/
6543 /*------------------------------------------------------------------*/
6545 /* Name - mono_arch_free_jit_tls_data */
6547 /* Function - Free tls data. */
6549 /*------------------------------------------------------------------*/
6552 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6556 /*========================= End of Function ========================*/
6558 /*------------------------------------------------------------------*/
6560 /* Name - mono_arch_emit_inst_for_method */
6562 /*------------------------------------------------------------------*/
6565 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6570 /*========================= End of Function ========================*/
6572 /*------------------------------------------------------------------*/
6574 /* Name - mono_arch_decompose_opts */
6576 /* Function - Decompose opcode into a System z opcode. */
6578 /*------------------------------------------------------------------*/
6581 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6584 * Have to rename these to avoid being decomposed normally, since the normal
6585 * decomposition does not work on S390.
6587 switch (ins->opcode) {
6589 ins->opcode = OP_S390_ISUB_OVF;
6591 case OP_ISUB_OVF_UN:
6592 ins->opcode = OP_S390_ISUB_OVF_UN;
6595 ins->opcode = OP_S390_IADD_OVF;
6597 case OP_IADD_OVF_UN:
6598 ins->opcode = OP_S390_IADD_OVF_UN;
6601 ins->opcode = OP_S390_LADD_OVF;
6603 case OP_LADD_OVF_UN:
6604 ins->opcode = OP_S390_LADD_OVF_UN;
6607 ins->opcode = OP_S390_LSUB_OVF;
6609 case OP_LSUB_OVF_UN:
6610 ins->opcode = OP_S390_LSUB_OVF_UN;
6617 /*========================= End of Function ========================*/
6619 /*------------------------------------------------------------------*/
6621 /* Name - mono_arch_regalloc_cost */
6623 /* Function - Determine the cost, in the number of memory */
6624 /* references, of the action of allocating the var- */
6625 /* iable VMV into a register during global register */
6628 /* Returns - Cost */
6630 /*------------------------------------------------------------------*/
6633 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6639 /*========================= End of Function ========================*/
6641 /*------------------------------------------------------------------*/
6643 /* Name - mono_arch_flush_register_windows */
6649 /*------------------------------------------------------------------*/
6652 mono_arch_flush_register_windows (void)
6656 /*========================= End of Function ========================*/
6658 /*------------------------------------------------------------------*/
6660 /* Name - mono_arch_is_inst_imm */
6662 /* Function - Determine if operand qualifies as an immediate */
6663 /* value. For s390 this is a value -32768-32768 */
6665 /* Returns - True|False - is [not] immediate value. */
6667 /*------------------------------------------------------------------*/
6670 mono_arch_is_inst_imm (gint64 imm)
6672 return s390_is_imm32 (imm);
6675 /*========================= End of Function ========================*/
6677 /*------------------------------------------------------------------*/
6679 /* Name - mono_arch_get_patch_offset */
6681 /* Function - Dummy entry point until s390x supports aot. */
6683 /* Returns - Offset for patch. */
6685 /*------------------------------------------------------------------*/
6688 mono_arch_get_patch_offset (guint8 *code)
6693 /*========================= End of Function ========================*/
6695 /*------------------------------------------------------------------*/
6697 /* Name - mono_arch_context_get_int_reg. */
6701 /* Returns - Return a register from the context. */
6703 /*------------------------------------------------------------------*/
6706 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6708 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6711 /*========================= End of Function ========================*/
6713 /*------------------------------------------------------------------*/
6715 /* Name - mono_arch_context_set_int_reg. */
6717 /* Function - Set a value in a specified register. */
6719 /*------------------------------------------------------------------*/
6722 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6724 ctx->uc_mcontext.gregs[reg] = val;
6727 /*========================= End of Function ========================*/
6729 /*------------------------------------------------------------------*/
6731 /* Name - mono_arch_get_this_arg_from_call. */
6735 /*------------------------------------------------------------------*/
6738 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6740 return (gpointer) regs [s390_r2];
6743 /*========================= End of Function ========================*/
6745 /*------------------------------------------------------------------*/
6747 /* Name - get_delegate_invoke_impl. */
6751 /*------------------------------------------------------------------*/
6754 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6756 guint8 *code, *start;
6761 start = code = mono_global_codeman_reserve (size);
6763 /* Replace the this argument with the target */
6764 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6765 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6766 s390_br (code, s390_r1);
6767 g_assert ((code - start) <= size);
6769 mono_arch_flush_icache (start, size);
6773 size = 32 + param_count * 8;
6774 start = code = mono_global_codeman_reserve (size);
6776 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6777 /* slide down the arguments */
6778 for (i = 0; i < param_count; ++i) {
6779 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6781 s390_br (code, s390_r1);
6783 g_assert ((code - start) <= size);
6785 mono_arch_flush_icache (start, size);
6789 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6791 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6792 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6799 /*========================= End of Function ========================*/
6801 /*------------------------------------------------------------------*/
6803 /* Name - mono_arch_get_delegate_invoke_impls. */
6807 /*------------------------------------------------------------------*/
6810 mono_arch_get_delegate_invoke_impls (void)
6813 MonoTrampInfo *info;
6816 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6817 res = g_slist_prepend (res, info);
6819 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6820 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6821 res = g_slist_prepend (res, info);
6827 /*========================= End of Function ========================*/
6829 /*------------------------------------------------------------------*/
6831 /* Name - mono_arch_get_delegate_invoke_impl. */
6835 /*------------------------------------------------------------------*/
6838 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6840 guint8 *code, *start;
6842 /* FIXME: Support more cases */
6843 if (MONO_TYPE_ISSTRUCT (sig->ret))
6847 static guint8* cached = NULL;
6852 if (mono_aot_only) {
6853 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6855 MonoTrampInfo *info;
6856 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6857 mono_tramp_info_register (info, NULL);
6860 mono_memory_barrier ();
6864 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6867 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6869 for (i = 0; i < sig->param_count; ++i)
6870 if (!mono_is_regsize_var (sig->params [i]))
6874 code = cache [sig->param_count];
6878 if (mono_aot_only) {
6879 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6880 start = mono_aot_get_trampoline (name);
6883 MonoTrampInfo *info;
6884 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6885 mono_tramp_info_register (info, NULL);
6888 mono_memory_barrier ();
6890 cache [sig->param_count] = start;
6895 /*========================= End of Function ========================*/
6897 /*------------------------------------------------------------------*/
6899 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6903 /*------------------------------------------------------------------*/
6906 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6907 int offset, gboolean load_imt_reg)
6909 guint8 *code, *start;
6912 start = code = mono_global_codeman_reserve (size);
6915 * Replace the "this" argument with the target
6917 s390_lgr (code, s390_r1, s390_r2);
6918 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6921 * Load the IMT register, if needed
6924 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6930 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6932 s390_agfi(code, s390_r1, offset);
6934 s390_lg (code, s390_r1, 0, s390_r1, 0);
6935 s390_br (code, s390_r1);
6940 /*========================= End of Function ========================*/
6942 /*------------------------------------------------------------------*/
6944 /* Name - mono_arch_build_imt_trampoline. */
6948 /*------------------------------------------------------------------*/
6951 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6952 MonoIMTCheckItem **imt_entries, int count,
6953 gpointer fail_tramp)
6957 guchar *code, *start;
6960 for (i = 0; i < count; ++i) {
6961 MonoIMTCheckItem *item = imt_entries [i];
6962 if (item->is_equals) {
6963 if (item->check_target_idx) {
6964 if (!item->compare_done)
6965 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6966 if (item->has_target_code)
6967 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6969 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6973 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6975 if (!item->has_target_code)
6976 item->chunk_size += LOAD_SIZE;
6978 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6979 #if ENABLE_WRONG_METHOD_CHECK
6980 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6985 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6986 imt_entries [item->check_target_idx]->compare_done = TRUE;
6988 size += item->chunk_size;
6992 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6994 code = mono_domain_code_reserve (domain, size);
6998 for (i = 0; i < count; ++i) {
6999 MonoIMTCheckItem *item = imt_entries [i];
7000 item->code_target = (guint8 *) code;
7001 if (item->is_equals) {
7002 if (item->check_target_idx) {
7003 if (!item->compare_done) {
7004 S390_SET (code, s390_r0, item->key);
7005 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
7007 item->jmp_code = (guint8*) code;
7008 s390_jcl (code, S390_CC_NE, 0);
7010 if (item->has_target_code) {
7011 S390_SET (code, s390_r1, item->value.target_code);
7013 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7014 s390_lg (code, s390_r1, 0, s390_r1, 0);
7016 s390_br (code, s390_r1);
7021 S390_SET (code, s390_r0, item->key);
7022 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
7023 item->jmp_code = (guint8*) code;
7024 s390_jcl (code, S390_CC_NE, 0);
7025 if (item->has_target_code) {
7026 S390_SET (code, s390_r1, item->value.target_code);
7029 S390_SET (code, s390_r1,
7030 (&(vtable->vtable [item->value.vtable_slot])));
7031 s390_lg (code, s390_r1, 0, s390_r1, 0);
7033 s390_br (code, s390_r1);
7034 target = (gint64) S390_RELATIVE(code, item->jmp_code);
7035 s390_patch_rel(item->jmp_code+2, target);
7036 S390_SET (code, s390_r1, fail_tramp);
7037 s390_br (code, s390_r1);
7038 item->jmp_code = NULL;
7040 /* enable the commented code to assert on wrong method */
7041 #if ENABLE_WRONG_METHOD_CHECK
7042 g_assert_not_reached ();
7044 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7045 s390_lg (code, s390_r1, 0, s390_r1, 0);
7046 s390_br (code, s390_r1);
7050 S390_SET (code, s390_r0, item->key);
7051 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
7052 item->jmp_code = (guint8 *) code;
7053 s390_jcl (code, S390_CC_GE, 0);
7057 * patch the branches to get to the target items
7059 for (i = 0; i < count; ++i) {
7060 MonoIMTCheckItem *item = imt_entries [i];
7061 if (item->jmp_code) {
7062 if (item->check_target_idx) {
7064 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
7066 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
7071 mono_arch_flush_icache ((guint8*)start, (code - start));
7074 UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
7076 g_assert (code - start <= size);
7078 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
7079 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
7084 /*========================= End of Function ========================*/
7086 /*------------------------------------------------------------------*/
7088 /* Name - mono_arch_find_imt_method. */
7090 /* Function - Get the method address from MONO_ARCH_IMT_REG */
7091 /* found in the save area. */
7093 /*------------------------------------------------------------------*/
7096 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
7098 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
7101 /*========================= End of Function ========================*/
7103 /*------------------------------------------------------------------*/
7105 /* Name - mono_arch_find_static_call_vtable */
7107 /* Function - Find the static call vtable. */
7109 /*------------------------------------------------------------------*/
7112 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
7114 mgreg_t *r = (mgreg_t*)regs;
7116 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
7119 /*========================= End of Function ========================*/
7121 /*------------------------------------------------------------------*/
7123 /* Name - mono_arch_get_cie_program */
7125 /* Function - Find the static call vtable. */
7127 /*------------------------------------------------------------------*/
7130 mono_arch_get_cie_program (void)
7134 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
7139 /*========================= End of Function ========================*/
7141 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7143 /*------------------------------------------------------------------*/
7145 /* Name - mono_arch_set_breakpoint. */
7147 /* Function - Set a breakpoint at the native code corresponding */
7148 /* to JI at NATIVE_OFFSET. The location should */
7149 /* contain code emitted by OP_SEQ_POINT. */
7151 /*------------------------------------------------------------------*/
7154 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
7158 breakpointCode.pTrigger = bp_trigger_page;
7159 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
7160 code += BREAKPOINT_SIZE;
7163 /*========================= End of Function ========================*/
7165 /*------------------------------------------------------------------*/
7167 /* Name - mono_arch_clear_breakpoint. */
7169 /* Function - Clear the breakpoint at IP. */
7171 /*------------------------------------------------------------------*/
7174 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
7179 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
7183 /*========================= End of Function ========================*/
7185 /*------------------------------------------------------------------*/
7187 /* Name - mono_arch_is_breakpoint_event. */
7191 /*------------------------------------------------------------------*/
7194 mono_arch_is_breakpoint_event (void *info, void *sigctx)
7196 siginfo_t* sinfo = (siginfo_t*) info;
7199 * Sometimes the address is off by 4
7201 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
7207 /*========================= End of Function ========================*/
7209 /*------------------------------------------------------------------*/
7211 /* Name - mono_arch_skip_breakpoint. */
7213 /* Function - Modify the CTX so the IP is placed after the */
7214 /* breakpoint instruction, so when we resume, the */
7215 /* instruction is not executed again. */
7217 /*------------------------------------------------------------------*/
7220 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
7222 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
7225 /*========================= End of Function ========================*/
7227 /*------------------------------------------------------------------*/
7229 /* Name - mono_arch_start_single_stepping. */
7231 /* Function - Start single stepping. */
7233 /*------------------------------------------------------------------*/
7236 mono_arch_start_single_stepping (void)
7238 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
7241 /*========================= End of Function ========================*/
7243 /*------------------------------------------------------------------*/
7245 /* Name - mono_arch_stop_single_stepping. */
7247 /* Function - Stop single stepping. */
7249 /*------------------------------------------------------------------*/
7252 mono_arch_stop_single_stepping (void)
7254 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
7257 /*========================= End of Function ========================*/
7259 /*------------------------------------------------------------------*/
7261 /* Name - mono_arch_is_single_step_event. */
7263 /* Function - Return whether the machine state in sigctx cor- */
7264 /* responds to a single step event. */
7266 /*------------------------------------------------------------------*/
7269 mono_arch_is_single_step_event (void *info, void *sigctx)
7271 siginfo_t* sinfo = (siginfo_t*) info;
7274 * Sometimes the address is off by 4
7276 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7282 /*========================= End of Function ========================*/
7284 /*------------------------------------------------------------------*/
7286 /* Name - mono_arch_skip_single_step. */
7288 /* Function - Modify the ctx so the IP is placed after the */
7289 /* single step trigger instruction, so that the */
7290 /* instruction is not executed again. */
7292 /*------------------------------------------------------------------*/
7295 mono_arch_skip_single_step (MonoContext *ctx)
7297 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7300 /*========================= End of Function ========================*/
7302 /*------------------------------------------------------------------*/
7304 /* Name - mono_arch_create_seq_point_info. */
7306 /* Function - Return a pointer to a data struction which is */
7307 /* used by the sequence point implementation in */
7310 /*------------------------------------------------------------------*/
7313 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7319 /*========================= End of Function ========================*/
7321 /*------------------------------------------------------------------*/
7323 /* Name - mono_arch_init_lmf_ext. */
7327 /*------------------------------------------------------------------*/
7330 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7332 ext->lmf.previous_lmf = prev_lmf;
7333 /* Mark that this is a MonoLMFExt */
7334 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7335 ext->lmf.ebp = (gssize)ext;
7338 /*========================= End of Function ========================*/
7342 /*------------------------------------------------------------------*/
7344 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7346 /* Function - If this CPU supports vector operations then it */
7347 /* supports the equivalent of SSE1-4. */
7349 /*------------------------------------------------------------------*/
7352 mono_arch_cpu_enumerate_simd_versions (void)
7354 guint32 sseOpts = 0;
7356 if (mono_hwcap_s390x_has_vec)
7357 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7358 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7359 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7360 SIMD_VERSION_SSE4a);
7365 /*========================= End of Function ========================*/
7367 /*------------------------------------------------------------------*/
7369 /* Name - mono_arch_opcode_supported. */
7371 /* Function - Check if a given return code is supported. */
7373 /*------------------------------------------------------------------*/
7376 mono_arch_opcode_supported (int opcode)
7379 case OP_ATOMIC_ADD_I4:
7380 case OP_ATOMIC_ADD_I8:
7381 case OP_ATOMIC_EXCHANGE_I4:
7382 case OP_ATOMIC_EXCHANGE_I8:
7389 /*========================= End of Function ========================*/