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 (s390_is_imm16 (ins->inst_imm)) {
3721 s390_lghi (code, s390_r13, ins->inst_imm);
3722 } else if (s390_is_imm32 (ins->inst_imm)) {
3723 s390_lgfi (code, s390_r13, ins->inst_imm);
3725 S390_SET (code, s390_r13, ins->inst_imm);
3727 s390_msgr (code, ins->dreg, s390_r13);
3732 s390_ltgr (code, s390_r1, ins->sreg1);
3733 s390_jz (code, 0); CODEPTR(code, o[0]);
3734 s390_ltgr (code, s390_r0, ins->sreg2);
3736 s390_lghi (code, s390_r1, 0);
3737 s390_j (code, 0); CODEPTR(code, o[1]);
3738 s390_xgr (code, s390_r0, s390_r1);
3739 s390_msgr (code, s390_r1, ins->sreg2);
3740 s390_xgr (code, s390_r0, s390_r1);
3741 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3742 s390_ltgr (code, s390_r0, s390_r0);
3743 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3744 PTRSLOT (code, o[0]);
3745 PTRSLOT (code, o[1]);
3746 s390_lgr (code, ins->dreg, s390_r1);
3749 case OP_LMUL_OVF_UN: {
3750 s390_lghi (code, s390_r0, 0);
3751 s390_lgr (code, s390_r1, ins->sreg1);
3752 s390_mlgr (code, s390_r0, ins->sreg2);
3753 s390_ltgr (code, s390_r0, s390_r0);
3754 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3755 s390_lgr (code, ins->dreg, s390_r1);
3759 g_assert_not_reached ();
3761 s390_algr (code, ins->dreg, src2);
3766 s390_agr (code, ins->dreg, src2);
3770 g_assert_not_reached ();
3772 s390_alcgr (code, ins->dreg, src2);
3776 if (ins->dreg != ins->sreg1) {
3777 s390_lgfr (code, ins->dreg, ins->sreg1);
3779 if (s390_is_imm16 (ins->inst_imm)) {
3780 s390_aghi (code, ins->dreg, ins->inst_imm);
3782 s390_afi (code, ins->dreg, ins->inst_imm);
3787 if (ins->dreg != ins->sreg1) {
3788 s390_lgfr (code, ins->dreg, ins->sreg1);
3790 if (s390_is_imm16 (ins->inst_imm)) {
3791 s390_lghi (code, s390_r0, ins->inst_imm);
3792 s390_alcgr (code, ins->dreg, s390_r0);
3794 S390_SET (code, s390_r0, ins->inst_imm);
3795 s390_alcgr (code, ins->dreg, s390_r0);
3800 case OP_S390_LADD_OVF: {
3802 s390_agr (code, ins->dreg, src2);
3803 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3806 case OP_LADD_OVF_UN:
3807 case OP_S390_LADD_OVF_UN: {
3809 s390_algr (code, ins->dreg, src2);
3810 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3814 CHECK_SRCDST_NCOM_I;
3815 s390_slgr (code, ins->dreg, src2);
3819 CHECK_SRCDST_NCOM_I;
3820 s390_sgr (code, ins->dreg, src2);
3824 CHECK_SRCDST_NCOM_I;
3825 s390_slbgr (code, ins->dreg, src2);
3829 if (ins->dreg != ins->sreg1) {
3830 s390_lgfr (code, ins->dreg, ins->sreg1);
3832 if (s390_is_imm16 (-ins->inst_imm)) {
3833 s390_aghi (code, ins->dreg, -ins->inst_imm);
3835 s390_agfi (code, ins->dreg, -ins->inst_imm);
3840 S390_SET (code, s390_r0, ins->inst_imm);
3841 s390_slgfr (code, ins->dreg, s390_r0);
3845 case OP_S390_ISUB_OVF: {
3847 s390_sr (code, ins->dreg, src2);
3848 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3849 s390_lgfr (code, ins->dreg, ins->dreg);
3852 case OP_ISUB_OVF_UN:
3853 case OP_S390_ISUB_OVF_UN: {
3855 s390_slr (code, ins->dreg, src2);
3856 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3857 s390_llgfr(code, ins->dreg, ins->dreg);
3861 case OP_S390_LSUB_OVF: {
3863 s390_sgr (code, ins->dreg, src2);
3864 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3867 case OP_LSUB_OVF_UN:
3868 case OP_S390_LSUB_OVF_UN: {
3870 s390_slgr (code, ins->dreg, src2);
3871 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3875 if (mono_hwcap_s390x_has_mlt) {
3876 s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3878 CHECK_SRCDST_NCOM_I;
3879 s390_ngr (code, ins->dreg, src2);
3884 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3885 if (mono_hwcap_s390x_has_mlt) {
3886 s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3888 if (ins->dreg != ins->sreg1) {
3889 s390_lgfr (code, ins->dreg, ins->sreg1);
3891 s390_ngr (code, ins->dreg, s390_r0);
3896 s390_lgfr (code, s390_r0, ins->sreg1);
3897 s390_srda (code, s390_r0, 0, 32);
3898 s390_dr (code, s390_r0, ins->sreg2);
3899 s390_lgfr (code, ins->dreg, s390_r1);
3903 s390_lgfr (code, s390_r0, ins->sreg1);
3904 s390_srdl (code, s390_r0, 0, 32);
3905 s390_dlr (code, s390_r0, ins->sreg2);
3906 s390_lgfr (code, ins->dreg, s390_r1);
3910 if (s390_is_imm16 (ins->inst_imm)) {
3911 s390_lghi (code, s390_r13, ins->inst_imm);
3913 s390_lgfi (code, s390_r13, ins->inst_imm);
3915 s390_lgfr (code, s390_r0, ins->sreg1);
3916 s390_srda (code, s390_r0, 0, 32);
3917 s390_dr (code, s390_r0, ins->sreg2);
3918 s390_lgfr (code, ins->dreg, s390_r1);
3922 s390_lgfr (code, s390_r0, ins->sreg1);
3923 s390_srda (code, s390_r0, 0, 32);
3924 s390_dr (code, s390_r0, ins->sreg2);
3925 s390_lgfr (code, ins->dreg, s390_r0);
3928 s390_lgfr (code, s390_r0, ins->sreg1);
3929 s390_srdl (code, s390_r0, 0, 32);
3930 s390_dlr (code, s390_r0, ins->sreg2);
3931 s390_lgfr (code, ins->dreg, s390_r0);
3935 if (s390_is_imm16 (ins->inst_imm)) {
3936 s390_lghi (code, s390_r13, ins->inst_imm);
3938 s390_lgfi (code, s390_r13, ins->inst_imm);
3940 s390_lgfr (code, s390_r0, ins->sreg1);
3941 s390_srda (code, s390_r0, 0, 32);
3942 s390_dr (code, s390_r0, ins->sreg2);
3943 s390_lgfr (code, ins->dreg, s390_r0);
3947 if (mono_hwcap_s390x_has_mlt) {
3948 s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3951 s390_ogr (code, ins->dreg, src2);
3956 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3957 if (mono_hwcap_s390x_has_mlt) {
3958 s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3960 if (ins->dreg != ins->sreg1) {
3961 s390_lgfr (code, ins->dreg, ins->sreg1);
3963 s390_ogr (code, ins->dreg, s390_r0);
3968 if (mono_hwcap_s390x_has_mlt) {
3969 s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3972 s390_xgr (code, ins->dreg, src2);
3977 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3978 if (mono_hwcap_s390x_has_mlt) {
3979 s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3981 if (ins->dreg != ins->sreg1) {
3982 s390_lgfr (code, ins->dreg, ins->sreg1);
3984 s390_xgr (code, ins->dreg, s390_r0);
3990 s390_sll (code, ins->dreg, src2, 0);
3994 if (ins->sreg1 != ins->dreg) {
3995 s390_lgfr (code, ins->dreg, ins->sreg1);
3997 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4002 s390_sra (code, ins->dreg, src2, 0);
4006 if (ins->sreg1 != ins->dreg) {
4007 s390_lgfr (code, ins->dreg, ins->sreg1);
4009 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4012 case OP_ISHR_UN_IMM: {
4013 if (ins->sreg1 != ins->dreg) {
4014 s390_lgfr (code, ins->dreg, ins->sreg1);
4016 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4021 s390_srl (code, ins->dreg, src2, 0);
4025 if (ins->sreg1 != ins->dreg) {
4026 s390_lgfr (code, ins->dreg, ins->sreg1);
4028 s390_lghi (code, s390_r0, -1);
4029 s390_xgr (code, ins->dreg, s390_r0);
4033 s390_lcgr (code, ins->dreg, ins->sreg1);
4038 s390_msr (code, ins->dreg, src2);
4042 if (ins->dreg != ins->sreg1) {
4043 s390_lgfr (code, ins->dreg, ins->sreg1);
4045 if (s390_is_imm16 (ins->inst_imm)) {
4046 s390_lghi (code, s390_r0, ins->inst_imm);
4048 s390_lgfi (code, s390_r0, ins->inst_imm);
4050 s390_msr (code, ins->dreg, s390_r0);
4055 s390_ltr (code, s390_r1, ins->sreg1);
4056 s390_jz (code, 0); CODEPTR(code, o[0]);
4057 s390_ltr (code, s390_r0, ins->sreg2);
4059 s390_lhi (code, s390_r1, 0);
4060 s390_j (code, 0); CODEPTR(code, o[1]);
4061 s390_xr (code, s390_r0, s390_r1);
4062 s390_msr (code, s390_r1, ins->sreg2);
4063 s390_xr (code, s390_r0, s390_r1);
4064 s390_srl (code, s390_r0, 0, 31);
4065 s390_ltr (code, s390_r0, s390_r0);
4066 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4067 PTRSLOT (code, o[0]);
4068 PTRSLOT (code, o[1]);
4069 s390_lgfr (code, ins->dreg, s390_r1);
4072 case OP_IMUL_OVF_UN: {
4073 s390_lhi (code, s390_r0, 0);
4074 s390_lr (code, s390_r1, ins->sreg1);
4075 s390_mlr (code, s390_r0, ins->sreg2);
4076 s390_ltr (code, s390_r0, s390_r0);
4077 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4078 s390_lgfr (code, ins->dreg, s390_r1);
4083 S390_SET (code, ins->dreg, ins->inst_c0);
4087 mono_add_patch_info (cfg, code - cfg->native_code,
4088 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4089 S390_LOAD_TEMPLATE (code, ins->dreg);
4092 case OP_JUMP_TABLE: {
4093 mono_add_patch_info (cfg, code - cfg->native_code,
4094 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4095 S390_LOAD_TEMPLATE (code, ins->dreg);
4099 if (ins->dreg != ins->sreg1) {
4100 s390_lgr (code, ins->dreg, ins->sreg1);
4104 case OP_LCONV_TO_I8:
4106 s390_lgfr (code, ins->dreg, ins->sreg1);
4108 case OP_LCONV_TO_I4:
4109 s390_lgfr (code, ins->dreg, ins->sreg1);
4112 case OP_LCONV_TO_U8:
4113 case OP_LCONV_TO_U4:
4115 s390_llgfr (code, ins->dreg, ins->sreg1);
4117 case OP_LCONV_TO_OVF_U4:
4118 S390_SET (code, s390_r0, 4294967295);
4119 s390_clgr (code, ins->sreg1, s390_r0);
4120 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4121 s390_ltgr (code, ins->sreg1, ins->sreg1);
4122 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4123 s390_llgfr(code, ins->dreg, ins->sreg1);
4125 case OP_LCONV_TO_OVF_I4_UN:
4126 S390_SET (code, s390_r0, 2147483647);
4127 s390_cgr (code, ins->sreg1, s390_r0);
4128 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4129 s390_ltgr (code, ins->sreg1, ins->sreg1);
4130 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4131 s390_lgfr (code, ins->dreg, ins->sreg1);
4134 if (ins->dreg != ins->sreg1) {
4135 s390_ldr (code, ins->dreg, ins->sreg1);
4138 case OP_MOVE_F_TO_I8:
4139 s390_lgdr (code, ins->dreg, ins->sreg1);
4141 case OP_MOVE_I8_TO_F:
4142 s390_ldgr (code, ins->dreg, ins->sreg1);
4144 case OP_MOVE_F_TO_I4:
4145 s390_ledbr (code, s390_f0, ins->sreg1);
4146 s390_lgdr (code, ins->dreg, s390_f0);
4147 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
4149 case OP_MOVE_I4_TO_F:
4150 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
4151 s390_ldgr (code, ins->dreg, s390_r0);
4152 s390_ldebr (code, ins->dreg, ins->dreg);
4154 case OP_FCONV_TO_R4:
4155 s390_ledbr (code, ins->dreg, ins->sreg1);
4156 s390_ldebr (code, ins->dreg, ins->dreg);
4158 case OP_S390_SETF4RET:
4159 s390_ledbr (code, ins->dreg, ins->sreg1);
4162 if (s390_is_imm16 (ins->inst_offset)) {
4163 s390_lghi (code, s390_r13, ins->inst_offset);
4164 } else if (s390_is_imm32 (ins->inst_offset)) {
4165 s390_lgfi (code, s390_r13, ins->inst_offset);
4167 S390_SET (code, s390_r13, ins->inst_offset);
4169 s390_ear (code, s390_r1, 0);
4170 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4171 s390_ear (code, s390_r1, 1);
4172 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
4176 if (s390_is_imm16 (ins->inst_offset)) {
4177 s390_lghi (code, s390_r13, ins->inst_offset);
4178 } else if (s390_is_imm32 (ins->inst_offset)) {
4179 s390_lgfi (code, s390_r13, ins->inst_offset);
4181 S390_SET (code, s390_r13, ins->inst_offset);
4183 s390_ear (code, s390_r1, 0);
4184 s390_sllg(code, s390_r1, s390_r1, 0, 32);
4185 s390_ear (code, s390_r1, 1);
4186 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
4190 if (cfg->method->save_lmf)
4191 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4193 if (cfg->flags & MONO_CFG_HAS_TAIL) {
4194 code = emit_load_volatile_arguments (code, cfg);
4197 code = backUpStackPtr(cfg, code);
4198 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
4199 mono_add_patch_info (cfg, code - cfg->native_code,
4200 MONO_PATCH_INFO_METHOD_JUMP,
4202 s390_jcl (code, S390_CC_UN, 0);
4205 case OP_CHECK_THIS: {
4206 /* ensure ins->sreg1 is not NULL */
4207 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
4208 s390_ltgr (code, s390_r0, s390_r0);
4209 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4213 int offset = cfg->sig_cookie + cfg->stack_usage;
4215 if (s390_is_imm16 (offset)) {
4216 s390_lghi (code, s390_r0, offset);
4217 } else if (s390_is_imm32 (offset)) {
4218 s390_lgfi (code, s390_r0, offset);
4220 S390_SET (code, s390_r0, offset);
4222 s390_agr (code, s390_r0, cfg->frame_reg);
4223 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
4227 call = (MonoCallInst*)ins;
4228 if (ins->flags & MONO_INST_HAS_METHOD)
4229 mono_add_patch_info (cfg, code-cfg->native_code,
4230 MONO_PATCH_INFO_METHOD,
4233 mono_add_patch_info (cfg, code-cfg->native_code,
4234 MONO_PATCH_INFO_ABS,
4236 S390_CALL_TEMPLATE (code, s390_r14);
4237 if (call->signature->ret->type == MONO_TYPE_R4)
4238 s390_ldebr (code, s390_f0, s390_f0);
4246 call = (MonoCallInst*)ins;
4247 if (ins->flags & MONO_INST_HAS_METHOD)
4248 mono_add_patch_info (cfg, code-cfg->native_code,
4249 MONO_PATCH_INFO_METHOD,
4252 mono_add_patch_info (cfg, code-cfg->native_code,
4253 MONO_PATCH_INFO_ABS,
4255 S390_CALL_TEMPLATE (code, s390_r14);
4258 case OP_FCALL_REG: {
4259 call = (MonoCallInst*)ins;
4260 s390_lgr (code, s390_r1, ins->sreg1);
4261 s390_basr (code, s390_r14, s390_r1);
4262 if (call->signature->ret->type == MONO_TYPE_R4)
4263 s390_ldebr (code, s390_f0, s390_f0);
4269 case OP_VOIDCALL_REG:
4271 s390_lgr (code, s390_r1, ins->sreg1);
4272 s390_basr (code, s390_r14, s390_r1);
4275 case OP_FCALL_MEMBASE: {
4276 call = (MonoCallInst*)ins;
4277 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4278 s390_basr (code, s390_r14, s390_r1);
4279 if (call->signature->ret->type == MONO_TYPE_R4)
4280 s390_ldebr (code, s390_f0, s390_f0);
4283 case OP_LCALL_MEMBASE:
4284 case OP_VCALL_MEMBASE:
4285 case OP_VCALL2_MEMBASE:
4286 case OP_VOIDCALL_MEMBASE:
4287 case OP_CALL_MEMBASE: {
4288 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4289 s390_basr (code, s390_r14, s390_r1);
4296 if (cfg->param_area == 0)
4297 alloca_skip = S390_MINIMAL_STACK_SIZE;
4299 alloca_skip = cfg->param_area;
4301 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4302 s390_lgr (code, s390_r1, ins->sreg1);
4303 if (ins->flags & MONO_INST_INIT)
4304 s390_lgr (code, s390_r0, ins->sreg1);
4305 s390_aghi (code, s390_r1, 14);
4306 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4307 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4308 if (cfg->method->save_lmf) {
4309 /*----------------------------------*/
4310 /* we have to adjust lmf ebp value */
4311 /*----------------------------------*/
4312 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4314 s390_lgr (code, s390_r13, cfg->frame_reg);
4315 if (s390_is_imm16(lmfOffset)) {
4316 s390_aghi (code, s390_r13, lmfOffset);
4317 } else if (s390_is_imm32(lmfOffset)) {
4318 s390_agfi (code, s390_r13, lmfOffset);
4320 S390_SET (code, s390_r13, lmfOffset);
4322 s390_lgr (code, s390_r14, STK_BASE);
4323 s390_sgr (code, s390_r14, s390_r1);
4324 s390_stg (code, s390_r14, 0, s390_r13,
4325 G_STRUCT_OFFSET(MonoLMF, ebp));
4327 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4328 s390_sgr (code, STK_BASE, s390_r1);
4329 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4330 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4331 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4332 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4333 if (ins->flags & MONO_INST_INIT) {
4334 s390_lgr (code, s390_r1, s390_r0);
4335 s390_lgr (code, s390_r0, ins->dreg);
4336 s390_lgr (code, s390_r14, s390_r12);
4337 s390_lghi (code, s390_r13, 0);
4338 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4340 s390_lgr (code, s390_r12, s390_r14);
4345 s390_lgr (code, s390_r2, ins->sreg1);
4346 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4347 (gpointer) "mono_arch_throw_exception");
4348 S390_CALL_TEMPLATE(code, s390_r14);
4352 s390_lgr (code, s390_r2, ins->sreg1);
4353 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4354 (gpointer) "mono_arch_rethrow_exception");
4355 S390_CALL_TEMPLATE(code, s390_r14);
4358 case OP_START_HANDLER: {
4359 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4361 S390_LONG (code, stg, stg, s390_r14, 0,
4362 spvar->inst_basereg,
4363 spvar->inst_offset);
4366 case OP_ENDFILTER: {
4367 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4369 if (ins->sreg1 != s390_r2)
4370 s390_lgr(code, s390_r2, ins->sreg1);
4371 S390_LONG (code, lg, lg, s390_r14, 0,
4372 spvar->inst_basereg,
4373 spvar->inst_offset);
4374 s390_br (code, s390_r14);
4377 case OP_ENDFINALLY: {
4378 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4380 S390_LONG (code, lg, lg, s390_r14, 0,
4381 spvar->inst_basereg,
4382 spvar->inst_offset);
4383 s390_br (code, s390_r14);
4386 case OP_CALL_HANDLER: {
4387 mono_add_patch_info (cfg, code-cfg->native_code,
4388 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4389 s390_brasl (code, s390_r14, 0);
4390 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4394 ins->inst_c0 = code - cfg->native_code;
4397 case OP_RELAXED_NOP:
4400 case OP_DUMMY_STORE:
4401 case OP_NOT_REACHED:
4405 case OP_IL_SEQ_POINT:
4406 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4408 case OP_SEQ_POINT: {
4411 if (cfg->compile_aot)
4415 * Read from the single stepping trigger page. This will cause a
4416 * SIGSEGV when single stepping is enabled.
4417 * We do this _before_ the breakpoint, so single stepping after
4418 * a breakpoint is hit will step to the next IL offset.
4420 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4421 breakpointCode.pTrigger = ss_trigger_page;
4422 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4423 code += BREAKPOINT_SIZE;
4426 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4429 * A placeholder for a possible breakpoint inserted by
4430 * mono_arch_set_breakpoint ().
4432 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4436 * Add an additional nop so skipping the bp doesn't cause the ip to point
4437 * to another IL offset.
4443 case OP_GENERIC_CLASS_INIT: {
4444 static int byte_offset = -1;
4445 static guint8 bitmask;
4448 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4450 if (byte_offset < 0)
4451 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4453 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4454 s390_jo (code, 0); CODEPTR(code, jump);
4456 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4457 "mono_generic_class_init");
4458 S390_CALL_TEMPLATE(code, s390_r14);
4460 PTRSLOT (code, jump);
4462 ins->flags |= MONO_INST_GC_CALLSITE;
4463 ins->backend.pc_offset = code - cfg->native_code;
4467 EMIT_UNCOND_BRANCH(ins);
4470 s390_br (code, ins->sreg1);
4476 s390_lghi(code, ins->dreg, 1);
4478 s390_lghi(code, ins->dreg, 0);
4484 s390_lghi(code, ins->dreg, 1);
4486 s390_lghi(code, ins->dreg, 0);
4492 s390_lghi(code, ins->dreg, 1);
4494 s390_lghi(code, ins->dreg, 0);
4500 s390_lghi(code, ins->dreg, 1);
4502 s390_lghi(code, ins->dreg, 0);
4508 s390_lghi(code, ins->dreg, 1);
4510 s390_lghi(code, ins->dreg, 0);
4514 s390_lghi(code, ins->dreg, 1);
4516 s390_lghi(code, ins->dreg, 0);
4520 s390_lghi(code, ins->dreg, 1);
4522 s390_lghi(code, ins->dreg, 0);
4526 s390_lghi(code, ins->dreg, 1);
4528 s390_lghi(code, ins->dreg, 0);
4532 s390_lghi(code, ins->dreg, 1);
4534 s390_lghi(code, ins->dreg, 0);
4538 s390_lghi(code, ins->dreg, 1);
4540 s390_lghi(code, ins->dreg, 0);
4543 case OP_COND_EXC_EQ:
4544 case OP_COND_EXC_IEQ:
4545 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4547 case OP_COND_EXC_NE_UN:
4548 case OP_COND_EXC_INE_UN:
4549 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4551 case OP_COND_EXC_LT:
4552 case OP_COND_EXC_ILT:
4553 case OP_COND_EXC_LT_UN:
4554 case OP_COND_EXC_ILT_UN:
4555 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4557 case OP_COND_EXC_GT:
4558 case OP_COND_EXC_IGT:
4559 case OP_COND_EXC_GT_UN:
4560 case OP_COND_EXC_IGT_UN:
4561 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4563 case OP_COND_EXC_GE:
4564 case OP_COND_EXC_IGE:
4565 case OP_COND_EXC_GE_UN:
4566 case OP_COND_EXC_IGE_UN:
4567 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4569 case OP_COND_EXC_LE:
4570 case OP_COND_EXC_ILE:
4571 case OP_COND_EXC_LE_UN:
4572 case OP_COND_EXC_ILE_UN:
4573 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4575 case OP_COND_EXC_OV:
4576 case OP_COND_EXC_IOV:
4577 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4579 case OP_COND_EXC_NO:
4580 case OP_COND_EXC_INO:
4581 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4584 case OP_COND_EXC_IC:
4585 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4587 case OP_COND_EXC_NC:
4588 case OP_COND_EXC_INC:
4589 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4593 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4597 EMIT_COND_BRANCH (ins, S390_CC_NE);
4603 EMIT_COND_BRANCH (ins, S390_CC_LT);
4609 EMIT_COND_BRANCH (ins, S390_CC_GT);
4615 EMIT_COND_BRANCH (ins, S390_CC_GE);
4621 EMIT_COND_BRANCH (ins, S390_CC_LE);
4625 EMIT_COMP_AND_BRANCH(ins, crj, cr);
4629 EMIT_COMP_AND_BRANCH(ins, clrj, clr);
4633 EMIT_COMP_AND_BRANCH(ins, cgrj, cgr);
4637 EMIT_COMP_AND_BRANCH(ins, clgrj, clgr);
4641 EMIT_COMP_AND_BRANCH_IMM(ins, crj, cr, ltr, FALSE);
4645 EMIT_COMP_AND_BRANCH_IMM(ins, clrj, clr, ltr, TRUE);
4649 EMIT_COMP_AND_BRANCH_IMM(ins, cgrj, cgr, ltgr, FALSE);
4653 EMIT_COMP_AND_BRANCH_IMM(ins, clgrj, clgr, ltgr, TRUE);
4656 /* floating point opcodes */
4658 if (*((double *) ins->inst_p0) == 0) {
4659 s390_lzdr (code, ins->dreg);
4661 S390_SET (code, s390_r13, ins->inst_p0);
4662 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4667 if (*((float *) ins->inst_p0) == 0) {
4668 s390_lzdr (code, ins->dreg);
4670 S390_SET (code, s390_r13, ins->inst_p0);
4671 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4675 case OP_STORER8_MEMBASE_REG: {
4676 S390_LONG (code, stdy, std, ins->sreg1, 0,
4677 ins->inst_destbasereg, ins->inst_offset);
4680 case OP_LOADR8_MEMBASE: {
4681 S390_LONG (code, ldy, ld, ins->dreg, 0,
4682 ins->inst_basereg, ins->inst_offset);
4685 case OP_STORER4_MEMBASE_REG: {
4686 s390_ledbr (code, s390_f15, ins->sreg1);
4687 S390_LONG (code, stey, ste, s390_f15, 0,
4688 ins->inst_destbasereg, ins->inst_offset);
4691 case OP_LOADR4_MEMBASE: {
4692 S390_LONG (code, ley, le, s390_f15, 0,
4693 ins->inst_basereg, ins->inst_offset);
4694 s390_ldebr (code, ins->dreg, s390_f15);
4697 case OP_ICONV_TO_R_UN: {
4698 if (mono_hwcap_s390x_has_fpe) {
4699 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4701 s390_llgfr (code, s390_r0, ins->sreg1);
4702 s390_cdgbr (code, ins->dreg, s390_r0);
4706 case OP_LCONV_TO_R_UN: {
4707 if (mono_hwcap_s390x_has_fpe) {
4708 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4711 s390_cxgbr (code, s390_f12, ins->sreg1);
4712 s390_ltgr (code, ins->sreg1, ins->sreg1);
4713 s390_jnl (code, 0); CODEPTR(code, jump);
4714 S390_SET (code, s390_r13, 0x403f000000000000llu);
4715 s390_lgdr (code, s390_f13, s390_r13);
4716 s390_lzdr (code, s390_f15);
4717 s390_axbr (code, s390_f12, s390_f13);
4718 PTRSLOT(code, jump);
4719 s390_ldxbr (code, s390_f13, s390_f12);
4720 s390_ldr (code, ins->dreg, s390_f13);
4724 case OP_LCONV_TO_R4:
4725 case OP_ICONV_TO_R4: {
4726 s390_cegbr (code, ins->dreg, ins->sreg1);
4727 s390_ldebr (code, ins->dreg, ins->dreg);
4730 case OP_LCONV_TO_R8:
4731 case OP_ICONV_TO_R8: {
4732 s390_cdgbr (code, ins->dreg, ins->sreg1);
4735 case OP_FCONV_TO_I1:
4736 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4737 s390_ltgr (code, ins->dreg, ins->dreg);
4739 s390_oill (code, ins->dreg, 0x80);
4740 s390_lghi (code, s390_r0, 0xff);
4741 s390_ngr (code, ins->dreg, s390_r0);
4743 case OP_FCONV_TO_U1:
4744 if (mono_hwcap_s390x_has_fpe) {
4745 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4746 s390_lghi (code, s390_r0, 0xff);
4747 s390_ngr (code, ins->dreg, s390_r0);
4749 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4752 case OP_FCONV_TO_I2:
4753 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4754 s390_ltgr (code, ins->dreg, ins->dreg);
4756 s390_oill (code, ins->dreg, 0x8000);
4757 s390_llill (code, s390_r0, 0xffff);
4758 s390_ngr (code, ins->dreg, s390_r0);
4760 case OP_FCONV_TO_U2:
4761 if (mono_hwcap_s390x_has_fpe) {
4762 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4763 s390_llill (code, s390_r0, 0xffff);
4764 s390_ngr (code, ins->dreg, s390_r0);
4766 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4769 case OP_FCONV_TO_I4:
4771 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4773 case OP_FCONV_TO_U4:
4775 if (mono_hwcap_s390x_has_fpe) {
4776 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4778 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4781 case OP_FCONV_TO_I8:
4782 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4784 case OP_FCONV_TO_U8:
4785 if (mono_hwcap_s390x_has_fpe) {
4786 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4788 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4791 case OP_LCONV_TO_OVF_I: {
4792 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4794 s390_ltgr (code, ins->sreg2, ins->sreg2);
4795 s390_jnl (code, 0); CODEPTR(code, o[0]);
4796 s390_ltgr (code, ins->sreg1, ins->sreg1);
4797 s390_jnl (code, 0); CODEPTR(code, o[1]);
4798 s390_lhi (code, s390_r13, -1);
4799 s390_cgr (code, ins->sreg1, s390_r13);
4800 s390_jnz (code, 0); CODEPTR(code, o[2]);
4801 if (ins->dreg != ins->sreg2)
4802 s390_lgr (code, ins->dreg, ins->sreg2);
4803 s390_j (code, 0); CODEPTR(code, o[3]);
4804 PTRSLOT(code, o[0]);
4805 s390_jz (code, 0); CODEPTR(code, o[4]);
4806 PTRSLOT(code, o[1]);
4807 PTRSLOT(code, o[2]);
4808 mono_add_patch_info (cfg, code - cfg->native_code,
4809 MONO_PATCH_INFO_EXC, "OverflowException");
4810 s390_brasl (code, s390_r14, 0);
4811 PTRSLOT(code, o[3]);
4812 PTRSLOT(code, o[4]);
4816 s390_lpdbr (code, ins->dreg, ins->sreg1);
4820 s390_sqdbr (code, ins->dreg, ins->sreg1);
4825 s390_adbr (code, ins->dreg, src2);
4829 CHECK_SRCDST_NCOM_F;
4830 s390_sdbr (code, ins->dreg, src2);
4835 s390_mdbr (code, ins->dreg, src2);
4839 CHECK_SRCDST_NCOM_F;
4840 s390_ddbr (code, ins->dreg, src2);
4844 s390_lcdbr (code, ins->dreg, ins->sreg1);
4848 CHECK_SRCDST_NCOM_F;
4849 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4853 s390_cdbr (code, ins->sreg1, ins->sreg2);
4857 s390_cdbr (code, ins->sreg1, ins->sreg2);
4858 s390_lghi (code, ins->dreg, 1);
4860 s390_lghi (code, ins->dreg, 0);
4864 s390_cdbr (code, ins->sreg1, ins->sreg2);
4865 s390_lghi (code, ins->dreg, 1);
4867 s390_lghi (code, ins->dreg, 0);
4871 s390_cdbr (code, ins->sreg1, ins->sreg2);
4872 s390_lghi (code, ins->dreg, 1);
4874 s390_lghi (code, ins->dreg, 0);
4878 s390_cdbr (code, ins->sreg1, ins->sreg2);
4879 s390_lghi (code, ins->dreg, 1);
4881 s390_lghi (code, ins->dreg, 0);
4885 s390_cdbr (code, ins->sreg1, ins->sreg2);
4886 s390_lghi (code, ins->dreg, 1);
4888 s390_lghi (code, ins->dreg, 0);
4892 s390_cdbr (code, ins->sreg1, ins->sreg2);
4893 s390_lghi (code, ins->dreg, 1);
4895 s390_lghi (code, ins->dreg, 0);
4899 s390_cdbr (code, ins->sreg1, ins->sreg2);
4900 s390_lghi (code, ins->dreg, 1);
4902 s390_lghi (code, ins->dreg, 0);
4906 s390_cdbr (code, ins->sreg1, ins->sreg2);
4907 s390_lghi (code, ins->dreg, 1);
4909 s390_lghi (code, ins->dreg, 0);
4914 s390_jo (code, 0); CODEPTR(code, o);
4915 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4920 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4924 s390_jo (code, 0); CODEPTR(code, o);
4925 EMIT_COND_BRANCH (ins, S390_CC_LT);
4930 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4934 s390_jo (code, 0); CODEPTR(code, o);
4935 EMIT_COND_BRANCH (ins, S390_CC_GT);
4940 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4944 s390_jo (code, 0); CODEPTR(code, o);
4945 EMIT_COND_BRANCH (ins, S390_CC_GE);
4950 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4954 s390_jo (code, 0); CODEPTR(code, o);
4955 EMIT_COND_BRANCH (ins, S390_CC_LE);
4960 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4964 s390_lhi (code, s390_r13, 0x7f);
4965 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4966 s390_jz (code, 0); CODEPTR(code, o);
4967 mono_add_patch_info (cfg, code - cfg->native_code,
4968 MONO_PATCH_INFO_EXC, "OverflowException");
4969 s390_brasl (code, s390_r14,0);
4973 case OP_S390_MOVE: {
4974 if (ins->backend.size > 0) {
4975 if (ins->backend.size <= 256) {
4976 s390_mvc (code, ins->backend.size, ins->dreg,
4977 ins->inst_offset, ins->sreg1, ins->inst_imm);
4979 s390_lgr (code, s390_r0, ins->dreg);
4980 if (ins->inst_offset > 0) {
4981 if (s390_is_imm16 (ins->inst_offset)) {
4982 s390_aghi (code, s390_r0, ins->inst_offset);
4983 } else if (s390_is_imm32 (ins->inst_offset)) {
4984 s390_agfi (code, s390_r0, ins->inst_offset);
4986 S390_SET (code, s390_r13, ins->inst_offset);
4987 s390_agr (code, s390_r0, s390_r13);
4990 s390_lgr (code, s390_r12, ins->sreg1);
4991 if (ins->inst_imm > 0) {
4992 if (s390_is_imm16 (ins->inst_imm)) {
4993 s390_aghi (code, s390_r12, ins->inst_imm);
4994 } else if (s390_is_imm32 (ins->inst_imm)) {
4995 s390_agfi (code, s390_r12, ins->inst_imm);
4997 S390_SET (code, s390_r13, ins->inst_imm);
4998 s390_agr (code, s390_r12, s390_r13);
5001 if (s390_is_imm16 (ins->backend.size)) {
5002 s390_lghi (code, s390_r1, ins->backend.size);
5003 } else if (s390_is_imm32 (ins->inst_offset)) {
5004 s390_agfi (code, s390_r1, ins->backend.size);
5006 S390_SET (code, s390_r13, ins->backend.size);
5007 s390_agr (code, s390_r1, s390_r13);
5009 s390_lgr (code, s390_r13, s390_r1);
5010 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
5016 case OP_ATOMIC_ADD_I8: {
5017 if (mono_hwcap_s390x_has_ia) {
5018 s390_laag (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5019 s390_agr (code, ins->dreg, ins->sreg2);
5021 s390_lgr (code, s390_r1, ins->sreg2);
5022 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5023 s390_agr (code, s390_r1, s390_r0);
5024 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5025 s390_jnz (code, -10);
5026 s390_lgr (code, ins->dreg, s390_r1);
5030 case OP_ATOMIC_EXCHANGE_I8: {
5031 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5032 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5033 s390_jnz (code, -6);
5034 s390_lgr (code, ins->dreg, s390_r0);
5037 case OP_ATOMIC_ADD_I4: {
5038 if (mono_hwcap_s390x_has_ia) {
5039 s390_laa (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5040 s390_ar (code, ins->dreg, ins->sreg2);
5042 s390_lgfr(code, s390_r1, ins->sreg2);
5043 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5044 s390_agr (code, s390_r1, s390_r0);
5045 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5046 s390_jnz (code, -9);
5047 s390_lgfr(code, ins->dreg, s390_r1);
5051 case OP_ATOMIC_EXCHANGE_I4: {
5052 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5053 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5054 s390_jnz (code, -4);
5055 s390_lgfr(code, ins->dreg, s390_r0);
5058 case OP_S390_BKCHAIN: {
5059 s390_lgr (code, ins->dreg, ins->sreg1);
5060 if (s390_is_imm16 (cfg->stack_offset)) {
5061 s390_aghi (code, ins->dreg, cfg->stack_offset);
5062 } else if (s390_is_imm32 (cfg->stack_offset)) {
5063 s390_agfi (code, ins->dreg, cfg->stack_offset);
5065 S390_SET (code, s390_r13, cfg->stack_offset);
5066 s390_agr (code, ins->dreg, s390_r13);
5070 case OP_MEMORY_BARRIER:
5073 case OP_GC_SAFE_POINT: {
5076 g_assert (mono_threads_is_coop_enabled ());
5078 s390_ltg (code, s390_r0, 0, ins->sreg1, 0);
5079 s390_jz (code, 0); CODEPTR(code, br);
5080 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
5081 mono_threads_state_poll);
5082 S390_CALL_TEMPLATE (code, s390_r14);
5086 case OP_GC_LIVENESS_DEF:
5087 case OP_GC_LIVENESS_USE:
5088 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
5089 ins->backend.pc_offset = code - cfg->native_code;
5091 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
5092 ins->backend.pc_offset = code - cfg->native_code;
5093 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
5095 #ifdef MONO_ARCH_SIMD_INTRINSICS
5097 s390x_addps (code, ins->sreg1, ins->sreg2);
5100 s390x_divps (code, ins->sreg1, ins->sreg2);
5103 s390x_mulps (code, ins->sreg1, ins->sreg2);
5106 s390x_subps (code, ins->sreg1, ins->sreg2);
5109 s390x_maxps (code, ins->sreg1, ins->sreg2);
5112 s390x_minps (code, ins->sreg1, ins->sreg2);
5115 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5116 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5119 s390x_andps (code, ins->sreg1, ins->sreg2);
5122 s390x_andnps (code, ins->sreg1, ins->sreg2);
5125 s390x_orps (code, ins->sreg1, ins->sreg2);
5128 s390x_xorps (code, ins->sreg1, ins->sreg2);
5131 s390x_sqrtps (code, ins->dreg, ins->sreg1);
5134 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
5137 s390x_rcpps (code, ins->dreg, ins->sreg1);
5140 s390x_addsubps (code, ins->sreg1, ins->sreg2);
5143 s390x_haddps (code, ins->sreg1, ins->sreg2);
5146 s390x_hsubps (code, ins->sreg1, ins->sreg2);
5149 s390x_movshdup (code, ins->dreg, ins->sreg1);
5152 s390x_movsldup (code, ins->dreg, ins->sreg1);
5155 case OP_PSHUFLEW_HIGH:
5156 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5157 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5159 case OP_PSHUFLEW_LOW:
5160 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5161 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5164 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5165 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5168 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5169 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5172 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
5173 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5177 s390x_addpd (code, ins->sreg1, ins->sreg2);
5180 s390x_divpd (code, ins->sreg1, ins->sreg2);
5183 s390x_mulpd (code, ins->sreg1, ins->sreg2);
5186 s390x_subpd (code, ins->sreg1, ins->sreg2);
5189 s390x_maxpd (code, ins->sreg1, ins->sreg2);
5192 s390x_minpd (code, ins->sreg1, ins->sreg2);
5195 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5196 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5199 s390x_andpd (code, ins->sreg1, ins->sreg2);
5202 s390x_andnpd (code, ins->sreg1, ins->sreg2);
5205 s390x_orpd (code, ins->sreg1, ins->sreg2);
5208 s390x_xorpd (code, ins->sreg1, ins->sreg2);
5211 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
5214 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
5217 s390x_haddpd (code, ins->sreg1, ins->sreg2);
5220 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
5223 s390x_movddup (code, ins->dreg, ins->sreg1);
5226 case OP_EXTRACT_MASK:
5227 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
5231 s390x_pand (code, ins->sreg1, ins->sreg2);
5234 s390x_por (code, ins->sreg1, ins->sreg2);
5237 s390x_pxor (code, ins->sreg1, ins->sreg2);
5241 s390x_paddb (code, ins->sreg1, ins->sreg2);
5244 s390x_paddw (code, ins->sreg1, ins->sreg2);
5247 s390x_paddd (code, ins->sreg1, ins->sreg2);
5250 s390x_paddq (code, ins->sreg1, ins->sreg2);
5254 s390x_psubb (code, ins->sreg1, ins->sreg2);
5257 s390x_psubw (code, ins->sreg1, ins->sreg2);
5260 s390x_psubd (code, ins->sreg1, ins->sreg2);
5263 s390x_psubq (code, ins->sreg1, ins->sreg2);
5267 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
5270 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
5273 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
5277 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
5280 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
5283 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
5287 s390x_pavgb (code, ins->sreg1, ins->sreg2);
5290 s390x_pavgw (code, ins->sreg1, ins->sreg2);
5294 s390x_pminub (code, ins->sreg1, ins->sreg2);
5297 s390x_pminuw (code, ins->sreg1, ins->sreg2);
5300 s390x_pminud (code, ins->sreg1, ins->sreg2);
5304 s390x_pminsb (code, ins->sreg1, ins->sreg2);
5307 s390x_pminsw (code, ins->sreg1, ins->sreg2);
5310 s390x_pminsd (code, ins->sreg1, ins->sreg2);
5314 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
5317 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
5320 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
5323 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
5327 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
5330 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5333 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5336 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5339 case OP_PSUM_ABS_DIFF:
5340 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5343 case OP_UNPACK_LOWB:
5344 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5346 case OP_UNPACK_LOWW:
5347 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5349 case OP_UNPACK_LOWD:
5350 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5352 case OP_UNPACK_LOWQ:
5353 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5355 case OP_UNPACK_LOWPS:
5356 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5358 case OP_UNPACK_LOWPD:
5359 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5362 case OP_UNPACK_HIGHB:
5363 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5365 case OP_UNPACK_HIGHW:
5366 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5368 case OP_UNPACK_HIGHD:
5369 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5371 case OP_UNPACK_HIGHQ:
5372 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5374 case OP_UNPACK_HIGHPS:
5375 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5377 case OP_UNPACK_HIGHPD:
5378 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5382 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5385 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5388 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5391 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5394 case OP_PADDB_SAT_UN:
5395 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5397 case OP_PSUBB_SAT_UN:
5398 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5400 case OP_PADDW_SAT_UN:
5401 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5403 case OP_PSUBW_SAT_UN:
5404 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5408 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5411 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5414 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5417 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5421 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5424 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5427 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5429 case OP_PMULW_HIGH_UN:
5430 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5433 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5437 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5440 s390x_psrlw (code, ins->dreg, ins->sreg2);
5444 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5447 s390x_psraw (code, ins->dreg, ins->sreg2);
5451 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5454 s390x_psllw (code, ins->dreg, ins->sreg2);
5458 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5461 s390x_psrld (code, ins->dreg, ins->sreg2);
5465 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5468 s390x_psrad (code, ins->dreg, ins->sreg2);
5472 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5475 s390x_pslld (code, ins->dreg, ins->sreg2);
5479 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5482 s390x_psrlq (code, ins->dreg, ins->sreg2);
5485 /*TODO: This is appart of the sse spec but not added
5487 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5490 s390x_psraq (code, ins->dreg, ins->sreg2);
5495 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5498 s390x_psllq (code, ins->dreg, ins->sreg2);
5501 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5504 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5507 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5510 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5513 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5516 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5519 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5522 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5526 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5529 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5533 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5534 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5536 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5541 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5543 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5544 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5548 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5550 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5551 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5552 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5556 amd64_movhlps (code, ins->dreg, ins->sreg1);
5558 s390x_movsd (code, ins->dreg, ins->sreg1);
5561 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5563 case OP_EXTRACTX_U2:
5564 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5566 case OP_INSERTX_U1_SLOW:
5567 /*sreg1 is the extracted ireg (scratch)
5568 /sreg2 is the to be inserted ireg (scratch)
5569 /dreg is the xreg to receive the value*/
5571 /*clear the bits from the extracted word*/
5572 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5573 /*shift the value to insert if needed*/
5574 if (ins->inst_c0 & 1)
5575 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5576 /*join them together*/
5577 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5578 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5580 case OP_INSERTX_I4_SLOW:
5581 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5582 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5583 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5585 case OP_INSERTX_I8_SLOW:
5586 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5588 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5590 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5593 case OP_INSERTX_R4_SLOW:
5594 switch (ins->inst_c0) {
5597 s390x_movss (code, ins->dreg, ins->sreg2);
5599 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5602 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5604 s390x_movss (code, ins->dreg, ins->sreg2);
5606 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5607 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5610 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5612 s390x_movss (code, ins->dreg, ins->sreg2);
5614 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5615 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5618 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5620 s390x_movss (code, ins->dreg, ins->sreg2);
5622 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5623 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5627 case OP_INSERTX_R8_SLOW:
5629 amd64_movlhps (code, ins->dreg, ins->sreg2);
5631 s390x_movsd (code, ins->dreg, ins->sreg2);
5633 case OP_STOREX_MEMBASE_REG:
5634 case OP_STOREX_MEMBASE:
5635 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5637 case OP_LOADX_MEMBASE:
5638 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5640 case OP_LOADX_ALIGNED_MEMBASE:
5641 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5643 case OP_STOREX_ALIGNED_MEMBASE_REG:
5644 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5646 case OP_STOREX_NTA_MEMBASE_REG:
5647 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5649 case OP_PREFETCH_MEMBASE:
5650 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5654 /*FIXME the peephole pass should have killed this*/
5655 if (ins->dreg != ins->sreg1)
5656 s390x_movaps (code, ins->dreg, ins->sreg1);
5659 s390x_pxor (code, ins->dreg, ins->dreg);
5661 case OP_ICONV_TO_R4_RAW:
5662 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5665 case OP_FCONV_TO_R8_X:
5666 s390x_movsd (code, ins->dreg, ins->sreg1);
5669 case OP_XCONV_R8_TO_I4:
5670 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5671 switch (ins->backend.source_opcode) {
5672 case OP_FCONV_TO_I1:
5673 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5675 case OP_FCONV_TO_U1:
5676 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5678 case OP_FCONV_TO_I2:
5679 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5681 case OP_FCONV_TO_U2:
5682 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5688 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5689 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5690 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5693 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5694 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5697 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5698 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5702 s390x_movsd (code, ins->dreg, ins->sreg1);
5704 s390x_movsd (code, ins->dreg, ins->sreg1);
5705 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5707 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5710 s390x_movsd (code, ins->dreg, ins->sreg1);
5711 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5715 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5716 g_assert_not_reached ();
5719 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5720 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5721 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5722 g_assert_not_reached ();
5725 last_offset = offset;
5728 cfg->code_len = code - cfg->native_code;
5731 /*========================= End of Function ========================*/
5733 /*------------------------------------------------------------------*/
5735 /* Name - mono_arch_register_lowlevel_calls */
5737 /* Function - Register routines to help with --trace operation. */
5739 /*------------------------------------------------------------------*/
5742 mono_arch_register_lowlevel_calls (void)
5746 /*========================= End of Function ========================*/
5748 /*------------------------------------------------------------------*/
5750 /* Name - mono_arch_patch_code */
5752 /* Function - Process the patch data created during the */
5753 /* instruction build process. This resolves jumps, */
5754 /* calls, variables etc. */
5756 /*------------------------------------------------------------------*/
5759 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5760 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5763 MonoJumpInfo *patch_info;
5767 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5768 unsigned char *ip = patch_info->ip.i + code;
5769 gconstpointer target = NULL;
5771 target = mono_resolve_patch_target (method, domain, code,
5772 patch_info, run_cctors, error);
5773 return_if_nok (error);
5775 switch (patch_info->type) {
5776 case MONO_PATCH_INFO_IP:
5777 case MONO_PATCH_INFO_LDSTR:
5778 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5779 case MONO_PATCH_INFO_LDTOKEN:
5780 case MONO_PATCH_INFO_EXC:
5781 s390_patch_addr (ip, (guint64) target);
5783 case MONO_PATCH_INFO_METHOD:
5784 case MONO_PATCH_INFO_INTERNAL_METHOD:
5785 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5786 case MONO_PATCH_INFO_RGCTX_FETCH:
5787 case MONO_PATCH_INFO_ABS: {
5788 S390_EMIT_CALL (ip, target);
5791 case MONO_PATCH_INFO_SWITCH:
5792 /*----------------------------------*/
5793 /* ip points at the basr r13,0/j +4 */
5794 /* instruction the vtable value */
5795 /* follows this (i.e. ip+6) */
5796 /*----------------------------------*/
5797 S390_EMIT_LOAD (ip, target);
5799 case MONO_PATCH_INFO_METHODCONST:
5800 case MONO_PATCH_INFO_CLASS:
5801 case MONO_PATCH_INFO_IMAGE:
5802 case MONO_PATCH_INFO_FIELD:
5803 case MONO_PATCH_INFO_IID:
5804 case MONO_PATCH_INFO_EXC_NAME:
5805 target = S390_RELATIVE(target, ip);
5806 s390_patch_rel (ip, (guint64) target);
5808 case MONO_PATCH_INFO_R4:
5809 case MONO_PATCH_INFO_R8:
5810 case MONO_PATCH_INFO_METHOD_REL:
5811 g_assert_not_reached ();
5814 target = S390_RELATIVE(target, ip);
5816 s390_patch_rel (ip, (guint64) target);
5821 /*========================= End of Function ========================*/
5823 /*------------------------------------------------------------------*/
5825 /* Name - emit_load_volatile_arguments */
5827 /* Function - Emit the instructions to reload parameter regist- */
5828 /* registers for use with "tail" operations. */
5830 /* The register loading operations performed here */
5831 /* are the mirror of the store operations performed */
5832 /* in mono_arch_emit_prolog and need to be kept in */
5833 /* synchronization with it. */
5835 /*------------------------------------------------------------------*/
5838 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5841 MonoMethod *method = cfg->method;
5842 MonoMethodSignature *sig = mono_method_signature(method);
5846 cinfo = get_call_info (NULL, NULL, sig);
5848 if (cinfo->struct_ret) {
5849 ArgInfo *ainfo = &cinfo->ret;
5850 inst = cfg->vret_addr;
5851 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5854 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5855 ArgInfo *ainfo = cinfo->args + i;
5856 inst = cfg->args [pos];
5858 if (inst->opcode == OP_REGVAR) {
5859 if (ainfo->regtype == RegTypeGeneral)
5860 s390_lgr (code, ainfo->reg, inst->dreg);
5861 else if (ainfo->regtype == RegTypeFP) {
5862 if (inst->dreg != ainfo->reg) {
5863 if (ainfo->size == 4) {
5864 s390_ldebr (code, ainfo->reg, inst->dreg);
5866 s390_ldr (code, ainfo->reg, inst->dreg);
5870 else if (ainfo->regtype == RegTypeBase) {
5872 g_assert_not_reached ();
5874 if (ainfo->regtype == RegTypeGeneral) {
5875 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5876 g_assert_not_reached();
5877 switch (ainfo->size) {
5879 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5882 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5885 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5888 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5891 } else if (ainfo->regtype == RegTypeBase) {
5892 } else if (ainfo->regtype == RegTypeFP) {
5893 if (ainfo->size == 8)
5894 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5895 else if (ainfo->size == 4)
5896 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5898 g_assert_not_reached ();
5899 } else if (ainfo->regtype == RegTypeStructByVal) {
5900 if (ainfo->reg != STK_BASE) {
5901 switch (ainfo->size) {
5903 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5906 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5909 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5912 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5916 } else if (ainfo->regtype == RegTypeStructByAddr) {
5917 if (ainfo->reg != STK_BASE) {
5918 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5921 g_assert_not_reached ();
5929 /*========================= End of Function ========================*/
5931 /*------------------------------------------------------------------*/
5933 /* Name - mono_arch_emit_prolog */
5935 /* Function - Create the instruction sequence for a function */
5938 /*------------------------------------------------------------------*/
5941 mono_arch_emit_prolog (MonoCompile *cfg)
5943 MonoMethod *method = cfg->method;
5945 MonoMethodSignature *sig;
5947 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5956 cfg->code_size = 512;
5958 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5960 cfg->code_size += 256;
5963 if (method->save_lmf)
5964 cfg->code_size += 200;
5966 cfg->native_code = code = g_malloc (cfg->code_size);
5968 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5969 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5970 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5971 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5972 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5974 if (cfg->arch.bkchain_reg != -1)
5975 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5977 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5978 cfg->used_int_regs |= 1 << 11;
5981 alloc_size = cfg->stack_offset;
5983 cfg->stack_usage = cfa_offset = alloc_size;
5984 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5985 s390_lgr (code, s390_r11, STK_BASE);
5986 if (s390_is_imm16 (alloc_size)) {
5987 s390_aghi (code, STK_BASE, -alloc_size);
5988 } else if (s390_is_imm32 (alloc_size)) {
5989 s390_agfi (code, STK_BASE, -alloc_size);
5991 int stackSize = alloc_size;
5992 while (stackSize > INT_MAX) {
5993 s390_agfi (code, STK_BASE, -INT_MAX);
5994 stackSize -= INT_MAX;
5996 s390_agfi (code, STK_BASE, -stackSize);
5998 s390_stg (code, s390_r11, 0, STK_BASE, 0);
6000 if (cfg->frame_reg != STK_BASE)
6001 s390_lgr (code, s390_r11, STK_BASE);
6003 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
6005 /* store runtime generic context */
6006 if (cfg->rgctx_var) {
6007 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
6009 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
6010 cfg->rgctx_var->inst_basereg,
6011 cfg->rgctx_var->inst_offset);
6014 /* compute max_offset in order to use short forward jumps
6015 * we always do it on s390 because the immediate displacement
6016 * for jumps is too small
6019 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6021 bb->max_offset = max_offset;
6023 MONO_BB_FOR_EACH_INS (bb, ins)
6024 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
6027 /* load arguments allocated to register from the stack */
6028 sig = mono_method_signature (method);
6031 cinfo = get_call_info (cfg, cfg->mempool, sig);
6033 if (cinfo->struct_ret) {
6034 ArgInfo *ainfo = &cinfo->ret;
6035 inst = cfg->vret_addr;
6036 inst->backend.size = ainfo->vtsize;
6037 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6040 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6041 ArgInfo *ainfo = cinfo->args + i;
6042 inst = cfg->args [pos];
6044 if (inst->opcode == OP_VTARG_ADDR)
6045 inst = inst->inst_left;
6047 if (inst->opcode == OP_REGVAR) {
6048 if (ainfo->regtype == RegTypeGeneral)
6049 s390_lgr (code, inst->dreg, ainfo->reg);
6050 else if (ainfo->regtype == RegTypeFP) {
6051 if (inst->dreg != ainfo->reg) {
6052 if (ainfo->size == 4) {
6053 s390_ledbr (code, inst->dreg, ainfo->reg);
6055 s390_ldr (code, inst->dreg, ainfo->reg);
6059 else if (ainfo->regtype == RegTypeBase) {
6060 s390_lgr (code, s390_r13, STK_BASE);
6061 s390_aghi (code, s390_r13, alloc_size);
6062 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
6064 g_assert_not_reached ();
6066 if (cfg->verbose_level > 2)
6067 g_print ("Argument %d assigned to register %s\n",
6068 pos, mono_arch_regname (inst->dreg));
6070 if (ainfo->regtype == RegTypeGeneral) {
6071 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
6072 g_assert_not_reached();
6073 switch (ainfo->size) {
6075 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6078 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6081 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6084 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6087 } else if (ainfo->regtype == RegTypeBase) {
6088 } else if (ainfo->regtype == RegTypeFP) {
6089 if (ainfo->size == 8)
6090 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6091 else if (ainfo->size == 4)
6092 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6094 g_assert_not_reached ();
6095 } else if (ainfo->regtype == RegTypeStructByVal) {
6096 int doffset = inst->inst_offset;
6098 if (ainfo->reg != STK_BASE)
6102 s390_lgr (code, s390_r13, STK_BASE);
6103 s390_aghi (code, s390_r13, alloc_size);
6106 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
6107 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
6112 if (ainfo->reg == STK_BASE)
6113 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
6114 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
6117 if (ainfo->reg == STK_BASE)
6118 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
6119 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
6122 if (ainfo->reg == STK_BASE)
6123 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
6124 s390_st (code, reg, 0, inst->inst_basereg, doffset);
6127 if (ainfo->reg == STK_BASE)
6128 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
6129 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
6132 } else if (ainfo->regtype == RegTypeStructByAddr) {
6133 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6134 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
6136 g_assert_not_reached ();
6141 if (method->save_lmf) {
6142 /*---------------------------------------------------------------*/
6143 /* build the MonoLMF structure on the stack - see mini-s390x.h */
6144 /*---------------------------------------------------------------*/
6145 lmfOffset = alloc_size - sizeof(MonoLMF);
6147 s390_lgr (code, s390_r13, cfg->frame_reg);
6148 s390_aghi (code, s390_r13, lmfOffset);
6150 /*---------------------------------------------------------------*/
6151 /* Preserve the parameter registers while we fix up the lmf */
6152 /*---------------------------------------------------------------*/
6153 s390_stmg (code, s390_r2, s390_r6, s390_r13,
6154 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6156 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
6157 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
6158 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
6159 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
6160 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
6162 /*---------------------------------------------------------------*/
6163 /* On return from this call r2 have the address of the &lmf */
6164 /*---------------------------------------------------------------*/
6165 mono_add_patch_info (cfg, code - cfg->native_code,
6166 MONO_PATCH_INFO_INTERNAL_METHOD,
6167 (gpointer)"mono_tls_get_lmf_addr");
6168 S390_CALL_TEMPLATE(code, s390_r1);
6170 /*---------------------------------------------------------------*/
6171 /* Set lmf.lmf_addr = jit_tls->lmf */
6172 /*---------------------------------------------------------------*/
6173 s390_stg (code, s390_r2, 0, s390_r13,
6174 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
6175 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
6177 /*---------------------------------------------------------------*/
6178 /* Get current lmf */
6179 /*---------------------------------------------------------------*/
6180 s390_lg (code, s390_r0, 0, s390_r2, 0);
6182 /*---------------------------------------------------------------*/
6183 /* Set our lmf as the current lmf */
6184 /*---------------------------------------------------------------*/
6185 s390_stg (code, s390_r13, 0, s390_r2, 0);
6187 /*---------------------------------------------------------------*/
6188 /* Have our lmf.previous_lmf point to the last lmf */
6189 /*---------------------------------------------------------------*/
6190 s390_stg (code, s390_r0, 0, s390_r13,
6191 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
6192 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
6194 /*---------------------------------------------------------------*/
6195 /* save method info */
6196 /*---------------------------------------------------------------*/
6197 S390_SET (code, s390_r1, method);
6198 s390_stg (code, s390_r1, 0, s390_r13,
6199 G_STRUCT_OFFSET(MonoLMF, method));
6200 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
6202 /*---------------------------------------------------------------*/
6203 /* save the current IP */
6204 /*---------------------------------------------------------------*/
6205 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
6206 s390_basr (code, s390_r1, 0);
6207 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
6208 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
6209 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
6211 /*---------------------------------------------------------------*/
6212 /* Save general and floating point registers */
6213 /*---------------------------------------------------------------*/
6214 s390_stmg (code, s390_r2, s390_r12, s390_r13,
6215 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
6216 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
6217 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
6218 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
6219 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
6220 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
6221 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
6222 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
6223 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
6224 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
6225 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
6226 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
6228 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
6229 for (i = 0; i < 16; i++) {
6230 s390_std (code, i, 0, s390_r13,
6231 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
6232 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
6233 fpOffset += sizeof(double);
6236 /*---------------------------------------------------------------*/
6237 /* Restore the parameter registers now that we've set up the lmf */
6238 /*---------------------------------------------------------------*/
6239 s390_lmg (code, s390_r2, s390_r6, s390_r13,
6240 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6243 if (cfg->method->save_lmf)
6244 argsClobbered = TRUE;
6247 argsClobbered = TRUE;
6248 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
6252 * Optimize the common case of the first bblock making a call with the same
6253 * arguments as the method. This works because the arguments are still in their
6254 * original argument registers.
6256 if (!argsClobbered) {
6257 MonoBasicBlock *first_bb = cfg->bb_entry;
6259 int filter = FILTER_IL_SEQ_POINT;
6261 next = mono_bb_first_inst (first_bb, filter);
6262 if (!next && first_bb->next_bb) {
6263 first_bb = first_bb->next_bb;
6264 next = mono_bb_first_inst (first_bb, filter);
6267 if (first_bb->in_count > 1)
6270 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
6271 ArgInfo *ainfo = cinfo->args + i;
6272 gboolean match = FALSE;
6274 inst = cfg->args [i];
6275 if (inst->opcode != OP_REGVAR) {
6276 switch (ainfo->regtype) {
6277 case RegTypeGeneral: {
6278 if (((next->opcode == OP_LOAD_MEMBASE) ||
6279 (next->opcode == OP_LOADI4_MEMBASE)) &&
6280 next->inst_basereg == inst->inst_basereg &&
6281 next->inst_offset == inst->inst_offset) {
6282 if (next->dreg == ainfo->reg) {
6286 next->opcode = OP_MOVE;
6287 next->sreg1 = ainfo->reg;
6288 /* Only continue if the instruction doesn't change argument regs */
6289 if (next->dreg == ainfo->reg)
6299 /* Argument allocated to (non-volatile) register */
6300 switch (ainfo->regtype) {
6301 case RegTypeGeneral:
6302 if (next->opcode == OP_MOVE &&
6303 next->sreg1 == inst->dreg &&
6304 next->dreg == ainfo->reg) {
6315 next = mono_inst_next (next, filter);
6322 cfg->code_len = code - cfg->native_code;
6323 g_assert (cfg->code_len < cfg->code_size);
6328 /*========================= End of Function ========================*/
6330 /*------------------------------------------------------------------*/
6332 /* Name - mono_arch_emit_epilog */
6334 /* Function - Emit the instructions for a function epilog. */
6336 /*------------------------------------------------------------------*/
6339 mono_arch_emit_epilog (MonoCompile *cfg)
6341 MonoMethod *method = cfg->method;
6344 int max_epilog_size = 96;
6346 if (cfg->method->save_lmf)
6347 max_epilog_size += 128;
6349 if (mono_jit_trace_calls != NULL)
6350 max_epilog_size += 128;
6352 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6353 cfg->code_size *= 2;
6354 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6355 cfg->stat_code_reallocs++;
6358 code = cfg->native_code + cfg->code_len;
6360 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6361 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6365 if (method->save_lmf)
6366 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6368 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6369 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6371 code = backUpStackPtr(cfg, code);
6373 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6374 s390_br (code, s390_r14);
6376 cfg->code_len = code - cfg->native_code;
6378 g_assert (cfg->code_len < cfg->code_size);
6382 /*========================= End of Function ========================*/
6384 /*------------------------------------------------------------------*/
6386 /* Name - mono_arch_emit_exceptions */
6388 /* Function - Emit the blocks to handle exception conditions. */
6390 /*------------------------------------------------------------------*/
6393 mono_arch_emit_exceptions (MonoCompile *cfg)
6395 MonoJumpInfo *patch_info;
6401 MonoClass *exc_classes [MAX_EXC];
6402 guint8 *exc_throw_start [MAX_EXC];
6404 for (patch_info = cfg->patch_info;
6406 patch_info = patch_info->next) {
6407 if (patch_info->type == MONO_PATCH_INFO_EXC)
6411 code_size = exc_count * 48;
6413 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6414 cfg->code_size *= 2;
6415 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6416 cfg->stat_code_reallocs++;
6419 code = cfg->native_code + cfg->code_len;
6421 /*---------------------------------------------------------------------*/
6422 /* Add code to raise exceptions */
6423 /*---------------------------------------------------------------------*/
6424 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6425 switch (patch_info->type) {
6426 case MONO_PATCH_INFO_EXC: {
6427 guint8 *ip = patch_info->ip.i + cfg->native_code;
6428 MonoClass *exc_class;
6431 /*-----------------------------------------------------*/
6432 /* Patch the branch in epilog to come here */
6433 /*-----------------------------------------------------*/
6434 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6436 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6438 patch_info->data.name);
6439 throw_ip = patch_info->ip.i;
6441 for (iExc = 0; iExc < nThrows; ++iExc)
6442 if (exc_classes [iExc] == exc_class)
6445 if (iExc < nThrows) {
6446 s390_jcl (code, S390_CC_UN,
6447 (guint64) exc_throw_start [iExc]);
6448 patch_info->type = MONO_PATCH_INFO_NONE;
6451 if (nThrows < MAX_EXC) {
6452 exc_classes [nThrows] = exc_class;
6453 exc_throw_start [nThrows] = code;
6456 /*---------------------------------------------*/
6457 /* Patch the parameter passed to the handler */
6458 /*---------------------------------------------*/
6459 S390_SET (code, s390_r2, exc_class->type_token);
6460 /*---------------------------------------------*/
6461 /* Load return address & parameter register */
6462 /*---------------------------------------------*/
6463 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6464 cfg->native_code + 8), code));
6465 /*---------------------------------------------*/
6466 /* Reuse the current patch to set the jump */
6467 /*---------------------------------------------*/
6468 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6469 patch_info->data.name = "mono_arch_throw_corlib_exception";
6470 patch_info->ip.i = code - cfg->native_code;
6471 S390_BR_TEMPLATE (code, s390_r1);
6481 cfg->code_len = code - cfg->native_code;
6483 g_assert (cfg->code_len < cfg->code_size);
6487 /*========================= End of Function ========================*/
6489 /*------------------------------------------------------------------*/
6491 /* Name - mono_arch_finish_init */
6493 /* Function - Setup the JIT's Thread Level Specific Data. */
6495 /*------------------------------------------------------------------*/
6498 mono_arch_finish_init (void)
6502 /*========================= End of Function ========================*/
6504 /*------------------------------------------------------------------*/
6506 /* Name - mono_arch_free_jit_tls_data */
6508 /* Function - Free tls data. */
6510 /*------------------------------------------------------------------*/
6513 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6517 /*========================= End of Function ========================*/
6519 /*------------------------------------------------------------------*/
6521 /* Name - mono_arch_emit_inst_for_method */
6523 /*------------------------------------------------------------------*/
6526 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6531 /*========================= End of Function ========================*/
6533 /*------------------------------------------------------------------*/
6535 /* Name - mono_arch_decompose_opts */
6537 /* Function - Decompose opcode into a System z opcode. */
6539 /*------------------------------------------------------------------*/
6542 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6545 * Have to rename these to avoid being decomposed normally, since the normal
6546 * decomposition does not work on S390.
6548 switch (ins->opcode) {
6550 ins->opcode = OP_S390_ISUB_OVF;
6552 case OP_ISUB_OVF_UN:
6553 ins->opcode = OP_S390_ISUB_OVF_UN;
6556 ins->opcode = OP_S390_IADD_OVF;
6558 case OP_IADD_OVF_UN:
6559 ins->opcode = OP_S390_IADD_OVF_UN;
6562 ins->opcode = OP_S390_LADD_OVF;
6564 case OP_LADD_OVF_UN:
6565 ins->opcode = OP_S390_LADD_OVF_UN;
6568 ins->opcode = OP_S390_LSUB_OVF;
6570 case OP_LSUB_OVF_UN:
6571 ins->opcode = OP_S390_LSUB_OVF_UN;
6578 /*========================= End of Function ========================*/
6580 /*------------------------------------------------------------------*/
6582 /* Name - mono_arch_regalloc_cost */
6584 /* Function - Determine the cost, in the number of memory */
6585 /* references, of the action of allocating the var- */
6586 /* iable VMV into a register during global register */
6589 /* Returns - Cost */
6591 /*------------------------------------------------------------------*/
6594 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6600 /*========================= End of Function ========================*/
6602 /*------------------------------------------------------------------*/
6604 /* Name - mono_arch_flush_register_windows */
6610 /*------------------------------------------------------------------*/
6613 mono_arch_flush_register_windows (void)
6617 /*========================= End of Function ========================*/
6619 /*------------------------------------------------------------------*/
6621 /* Name - mono_arch_is_inst_imm */
6623 /* Function - Determine if operand qualifies as an immediate */
6624 /* value. For s390 this is a value -32768-32768 */
6626 /* Returns - True|False - is [not] immediate value. */
6628 /*------------------------------------------------------------------*/
6631 mono_arch_is_inst_imm (gint64 imm)
6633 return s390_is_imm32 (imm);
6636 /*========================= End of Function ========================*/
6638 /*------------------------------------------------------------------*/
6640 /* Name - mono_arch_get_patch_offset */
6642 /* Function - Dummy entry point until s390x supports aot. */
6644 /* Returns - Offset for patch. */
6646 /*------------------------------------------------------------------*/
6649 mono_arch_get_patch_offset (guint8 *code)
6654 /*========================= End of Function ========================*/
6656 /*------------------------------------------------------------------*/
6658 /* Name - mono_arch_context_get_int_reg. */
6662 /* Returns - Return a register from the context. */
6664 /*------------------------------------------------------------------*/
6667 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6669 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6672 /*========================= End of Function ========================*/
6674 /*------------------------------------------------------------------*/
6676 /* Name - mono_arch_context_set_int_reg. */
6678 /* Function - Set a value in a specified register. */
6680 /*------------------------------------------------------------------*/
6683 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6685 ctx->uc_mcontext.gregs[reg] = val;
6688 /*========================= End of Function ========================*/
6690 /*------------------------------------------------------------------*/
6692 /* Name - mono_arch_get_this_arg_from_call. */
6696 /*------------------------------------------------------------------*/
6699 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6701 return (gpointer) regs [s390_r2];
6704 /*========================= End of Function ========================*/
6706 /*------------------------------------------------------------------*/
6708 /* Name - get_delegate_invoke_impl. */
6712 /*------------------------------------------------------------------*/
6715 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6717 guint8 *code, *start;
6722 start = code = mono_global_codeman_reserve (size);
6724 /* Replace the this argument with the target */
6725 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6726 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6727 s390_br (code, s390_r1);
6728 g_assert ((code - start) <= size);
6730 mono_arch_flush_icache (start, size);
6734 size = 32 + param_count * 8;
6735 start = code = mono_global_codeman_reserve (size);
6737 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6738 /* slide down the arguments */
6739 for (i = 0; i < param_count; ++i) {
6740 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6742 s390_br (code, s390_r1);
6744 g_assert ((code - start) <= size);
6746 mono_arch_flush_icache (start, size);
6750 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6752 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6753 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6760 /*========================= End of Function ========================*/
6762 /*------------------------------------------------------------------*/
6764 /* Name - mono_arch_get_delegate_invoke_impls. */
6768 /*------------------------------------------------------------------*/
6771 mono_arch_get_delegate_invoke_impls (void)
6774 MonoTrampInfo *info;
6777 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6778 res = g_slist_prepend (res, info);
6780 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6781 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6782 res = g_slist_prepend (res, info);
6788 /*========================= End of Function ========================*/
6790 /*------------------------------------------------------------------*/
6792 /* Name - mono_arch_get_delegate_invoke_impl. */
6796 /*------------------------------------------------------------------*/
6799 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6801 guint8 *code, *start;
6803 /* FIXME: Support more cases */
6804 if (MONO_TYPE_ISSTRUCT (sig->ret))
6808 static guint8* cached = NULL;
6813 if (mono_aot_only) {
6814 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6816 MonoTrampInfo *info;
6817 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6818 mono_tramp_info_register (info, NULL);
6821 mono_memory_barrier ();
6825 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6828 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6830 for (i = 0; i < sig->param_count; ++i)
6831 if (!mono_is_regsize_var (sig->params [i]))
6835 code = cache [sig->param_count];
6839 if (mono_aot_only) {
6840 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6841 start = mono_aot_get_trampoline (name);
6844 MonoTrampInfo *info;
6845 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6846 mono_tramp_info_register (info, NULL);
6849 mono_memory_barrier ();
6851 cache [sig->param_count] = start;
6856 /*========================= End of Function ========================*/
6858 /*------------------------------------------------------------------*/
6860 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6864 /*------------------------------------------------------------------*/
6867 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6868 int offset, gboolean load_imt_reg)
6870 guint8 *code, *start;
6873 start = code = mono_global_codeman_reserve (size);
6876 * Replace the "this" argument with the target
6878 s390_lgr (code, s390_r1, s390_r2);
6879 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6882 * Load the IMT register, if needed
6885 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6891 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6893 s390_agfi(code, s390_r1, offset);
6895 s390_lg (code, s390_r1, 0, s390_r1, 0);
6896 s390_br (code, s390_r1);
6901 /*========================= End of Function ========================*/
6903 /*------------------------------------------------------------------*/
6905 /* Name - mono_arch_build_imt_trampoline. */
6909 /*------------------------------------------------------------------*/
6912 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6913 MonoIMTCheckItem **imt_entries, int count,
6914 gpointer fail_tramp)
6918 guchar *code, *start;
6921 for (i = 0; i < count; ++i) {
6922 MonoIMTCheckItem *item = imt_entries [i];
6923 if (item->is_equals) {
6924 if (item->check_target_idx) {
6925 if (!item->compare_done)
6926 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6927 if (item->has_target_code)
6928 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6930 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6934 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6936 if (!item->has_target_code)
6937 item->chunk_size += LOAD_SIZE;
6939 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6940 #if ENABLE_WRONG_METHOD_CHECK
6941 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6946 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6947 imt_entries [item->check_target_idx]->compare_done = TRUE;
6949 size += item->chunk_size;
6953 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6955 code = mono_domain_code_reserve (domain, size);
6959 for (i = 0; i < count; ++i) {
6960 MonoIMTCheckItem *item = imt_entries [i];
6961 item->code_target = (guint8 *) code;
6962 if (item->is_equals) {
6963 if (item->check_target_idx) {
6964 if (!item->compare_done) {
6965 S390_SET (code, s390_r0, item->key);
6966 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6968 item->jmp_code = (guint8*) code;
6969 s390_jcl (code, S390_CC_NE, 0);
6971 if (item->has_target_code) {
6972 S390_SET (code, s390_r1, item->value.target_code);
6974 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6975 s390_lg (code, s390_r1, 0, s390_r1, 0);
6977 s390_br (code, s390_r1);
6982 S390_SET (code, s390_r0, item->key);
6983 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6984 item->jmp_code = (guint8*) code;
6985 s390_jcl (code, S390_CC_NE, 0);
6986 if (item->has_target_code) {
6987 S390_SET (code, s390_r1, item->value.target_code);
6990 S390_SET (code, s390_r1,
6991 (&(vtable->vtable [item->value.vtable_slot])));
6992 s390_lg (code, s390_r1, 0, s390_r1, 0);
6994 s390_br (code, s390_r1);
6995 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6996 s390_patch_rel(item->jmp_code+2, target);
6997 S390_SET (code, s390_r1, fail_tramp);
6998 s390_br (code, s390_r1);
6999 item->jmp_code = NULL;
7001 /* enable the commented code to assert on wrong method */
7002 #if ENABLE_WRONG_METHOD_CHECK
7003 g_assert_not_reached ();
7005 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7006 s390_lg (code, s390_r1, 0, s390_r1, 0);
7007 s390_br (code, s390_r1);
7011 S390_SET (code, s390_r0, item->key);
7012 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
7013 item->jmp_code = (guint8 *) code;
7014 s390_jcl (code, S390_CC_GE, 0);
7018 * patch the branches to get to the target items
7020 for (i = 0; i < count; ++i) {
7021 MonoIMTCheckItem *item = imt_entries [i];
7022 if (item->jmp_code) {
7023 if (item->check_target_idx) {
7025 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
7027 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
7032 mono_arch_flush_icache ((guint8*)start, (code - start));
7035 UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
7037 g_assert (code - start <= size);
7039 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
7040 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
7045 /*========================= End of Function ========================*/
7047 /*------------------------------------------------------------------*/
7049 /* Name - mono_arch_find_imt_method. */
7051 /* Function - Get the method address from MONO_ARCH_IMT_REG */
7052 /* found in the save area. */
7054 /*------------------------------------------------------------------*/
7057 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
7059 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
7062 /*========================= End of Function ========================*/
7064 /*------------------------------------------------------------------*/
7066 /* Name - mono_arch_find_static_call_vtable */
7068 /* Function - Find the static call vtable. */
7070 /*------------------------------------------------------------------*/
7073 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
7075 mgreg_t *r = (mgreg_t*)regs;
7077 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
7080 /*========================= End of Function ========================*/
7082 /*------------------------------------------------------------------*/
7084 /* Name - mono_arch_get_cie_program */
7086 /* Function - Find the static call vtable. */
7088 /*------------------------------------------------------------------*/
7091 mono_arch_get_cie_program (void)
7095 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
7100 /*========================= End of Function ========================*/
7102 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7104 /*------------------------------------------------------------------*/
7106 /* Name - mono_arch_set_breakpoint. */
7108 /* Function - Set a breakpoint at the native code corresponding */
7109 /* to JI at NATIVE_OFFSET. The location should */
7110 /* contain code emitted by OP_SEQ_POINT. */
7112 /*------------------------------------------------------------------*/
7115 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
7119 breakpointCode.pTrigger = bp_trigger_page;
7120 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
7121 code += BREAKPOINT_SIZE;
7124 /*========================= End of Function ========================*/
7126 /*------------------------------------------------------------------*/
7128 /* Name - mono_arch_clear_breakpoint. */
7130 /* Function - Clear the breakpoint at IP. */
7132 /*------------------------------------------------------------------*/
7135 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
7140 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
7144 /*========================= End of Function ========================*/
7146 /*------------------------------------------------------------------*/
7148 /* Name - mono_arch_is_breakpoint_event. */
7152 /*------------------------------------------------------------------*/
7155 mono_arch_is_breakpoint_event (void *info, void *sigctx)
7157 siginfo_t* sinfo = (siginfo_t*) info;
7160 * Sometimes the address is off by 4
7162 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
7168 /*========================= End of Function ========================*/
7170 /*------------------------------------------------------------------*/
7172 /* Name - mono_arch_skip_breakpoint. */
7174 /* Function - Modify the CTX so the IP is placed after the */
7175 /* breakpoint instruction, so when we resume, the */
7176 /* instruction is not executed again. */
7178 /*------------------------------------------------------------------*/
7181 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
7183 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
7186 /*========================= End of Function ========================*/
7188 /*------------------------------------------------------------------*/
7190 /* Name - mono_arch_start_single_stepping. */
7192 /* Function - Start single stepping. */
7194 /*------------------------------------------------------------------*/
7197 mono_arch_start_single_stepping (void)
7199 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
7202 /*========================= End of Function ========================*/
7204 /*------------------------------------------------------------------*/
7206 /* Name - mono_arch_stop_single_stepping. */
7208 /* Function - Stop single stepping. */
7210 /*------------------------------------------------------------------*/
7213 mono_arch_stop_single_stepping (void)
7215 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
7218 /*========================= End of Function ========================*/
7220 /*------------------------------------------------------------------*/
7222 /* Name - mono_arch_is_single_step_event. */
7224 /* Function - Return whether the machine state in sigctx cor- */
7225 /* responds to a single step event. */
7227 /*------------------------------------------------------------------*/
7230 mono_arch_is_single_step_event (void *info, void *sigctx)
7232 siginfo_t* sinfo = (siginfo_t*) info;
7235 * Sometimes the address is off by 4
7237 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7243 /*========================= End of Function ========================*/
7245 /*------------------------------------------------------------------*/
7247 /* Name - mono_arch_skip_single_step. */
7249 /* Function - Modify the ctx so the IP is placed after the */
7250 /* single step trigger instruction, so that the */
7251 /* instruction is not executed again. */
7253 /*------------------------------------------------------------------*/
7256 mono_arch_skip_single_step (MonoContext *ctx)
7258 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7261 /*========================= End of Function ========================*/
7263 /*------------------------------------------------------------------*/
7265 /* Name - mono_arch_create_seq_point_info. */
7267 /* Function - Return a pointer to a data struction which is */
7268 /* used by the sequence point implementation in */
7271 /*------------------------------------------------------------------*/
7274 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7280 /*========================= End of Function ========================*/
7282 /*------------------------------------------------------------------*/
7284 /* Name - mono_arch_init_lmf_ext. */
7288 /*------------------------------------------------------------------*/
7291 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7293 ext->lmf.previous_lmf = prev_lmf;
7294 /* Mark that this is a MonoLMFExt */
7295 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7296 ext->lmf.ebp = (gssize)ext;
7299 /*========================= End of Function ========================*/
7303 /*------------------------------------------------------------------*/
7305 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7307 /* Function - If this CPU supports vector operations then it */
7308 /* supports the equivalent of SSE1-4. */
7310 /*------------------------------------------------------------------*/
7313 mono_arch_cpu_enumerate_simd_versions (void)
7315 guint32 sseOpts = 0;
7317 if (mono_hwcap_s390x_has_vec)
7318 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7319 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7320 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7321 SIMD_VERSION_SSE4a);
7326 /*========================= End of Function ========================*/
7328 /*------------------------------------------------------------------*/
7330 /* Name - mono_arch_opcode_supported. */
7332 /* Function - Check if a given return code is supported. */
7334 /*------------------------------------------------------------------*/
7337 mono_arch_opcode_supported (int opcode)
7340 case OP_ATOMIC_ADD_I4:
7341 case OP_ATOMIC_ADD_I8:
7342 case OP_ATOMIC_EXCHANGE_I4:
7343 case OP_ATOMIC_EXCHANGE_I8:
7350 /*========================= End of Function ========================*/