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 CHECK_SRCDST_COM \
65 if (ins->dreg == ins->sreg2) { \
69 if (ins->dreg != ins->sreg1) { \
70 s390_lgr (code, ins->dreg, ins->sreg1); \
74 #define CHECK_SRCDST_NCOM \
75 if (ins->dreg == ins->sreg2) { \
77 s390_lgr (code, s390_r13, ins->sreg2); \
81 if (ins->dreg != ins->sreg1) { \
82 s390_lgr (code, ins->dreg, ins->sreg1); \
85 #define CHECK_SRCDST_COM_I \
86 if (ins->dreg == ins->sreg2) { \
90 if (ins->dreg != ins->sreg1) { \
91 s390_lgfr (code, ins->dreg, ins->sreg1); \
95 #define CHECK_SRCDST_NCOM_I \
96 if (ins->dreg == ins->sreg2) { \
98 s390_lgfr (code, s390_r13, ins->sreg2); \
102 if (ins->dreg != ins->sreg1) { \
103 s390_lgfr (code, ins->dreg, ins->sreg1); \
106 #define CHECK_SRCDST_COM_F \
107 if (ins->dreg == ins->sreg2) { \
111 if (ins->dreg != ins->sreg1) { \
112 s390_ldr (code, ins->dreg, ins->sreg1); \
116 #define CHECK_SRCDST_NCOM_F \
117 if (ins->dreg == ins->sreg2) { \
119 s390_ldr (code, s390_r13, ins->sreg2); \
123 if (ins->dreg != ins->sreg1) { \
124 s390_ldr (code, ins->dreg, ins->sreg1); \
127 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
130 MONO_INST_NEW (cfg, inst, OP_NOP); \
133 inst->inst_offset = offset; \
135 inst->inst_imm = imm; \
137 if (s390_is_uimm12(offset)) { \
139 inst->inst_offset = offset; \
141 dReg = mono_alloc_preg (cfg); \
142 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
143 dReg, dest, offset); \
145 inst->inst_offset = 0; \
147 if (s390_is_uimm12(imm)) { \
149 inst->inst_imm = imm; \
151 sReg = mono_alloc_preg (cfg); \
152 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
154 inst->sreg1 = sReg; \
155 inst->inst_imm = 0; \
158 inst->opcode = OP_S390_MOVE; \
159 inst->backend.size = size; \
160 MONO_ADD_INS (cfg->cbb, inst); \
163 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
164 int reg = mono_alloc_preg (cfg); \
167 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
170 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
174 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
178 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
182 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
186 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
189 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
193 tmpr = mono_alloc_preg (cfg); \
194 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
195 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
199 tmpr = mono_alloc_preg (cfg); \
200 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
202 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
206 tmpr = mono_alloc_preg (cfg); \
207 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
209 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
213 tmpr = mono_alloc_preg (cfg); \
214 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
216 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
220 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
226 #define DEBUG(a) if (cfg->verbose_level > 1) a
230 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
232 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
233 #define S390X_NOP_SIZE sizeof(RR_Format)
235 #define MAX(a, b) ((a) > (b) ? (a) : (b))
238 * imt trampoline size values
241 #define LOADCON_SIZE 20
245 #define ENABLE_WRONG_METHOD_CHECK 0
247 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
248 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
250 /*========================= End of Defines =========================*/
252 /*------------------------------------------------------------------*/
253 /* I n c l u d e s */
254 /*------------------------------------------------------------------*/
258 #include <sys/types.h>
261 #include <mono/metadata/abi-details.h>
262 #include <mono/metadata/appdomain.h>
263 #include <mono/metadata/debug-helpers.h>
264 #include <mono/metadata/profiler-private.h>
265 #include <mono/utils/mono-error.h>
266 #include <mono/utils/mono-error-internals.h>
267 #include <mono/utils/mono-math.h>
268 #include <mono/utils/mono-mmap.h>
269 #include <mono/utils/mono-hwcap.h>
270 #include <mono/utils/mono-threads.h>
272 #include "mini-s390x.h"
273 #include "cpu-s390x.h"
274 #include "support-s390x.h"
275 #include "jit-icalls.h"
280 /*========================= End of Includes ========================*/
282 /*------------------------------------------------------------------*/
283 /* T y p e d e f s */
284 /*------------------------------------------------------------------*/
296 /*------------------------------------------------------------------*/
297 /* Used by the instrument_emit_epilog */
298 /*------------------------------------------------------------------*/
309 typedef struct InstList InstList;
323 RegTypeStructByValInFP,
325 RegTypeStructByAddrOnStack
329 gint32 offset; /* offset from caller's stack */
330 gint32 offparm; /* offset from callee's stack */
331 guint16 vtsize; /* in param area */
334 guint32 size; /* Size of structure used by RegTypeStructByVal */
335 gint32 type; /* Data type of argument */
351 gint64 gr[5]; /* R2-R6 */
352 gdouble fp[3]; /* F0-F2 */
353 } __attribute__ ((__packed__)) RegParm;
361 } __attribute__ ((__packed__)) breakpoint_t;
363 /*========================= End of Typedefs ========================*/
365 /*------------------------------------------------------------------*/
366 /* P r o t o t y p e s */
367 /*------------------------------------------------------------------*/
369 static void indent (int);
370 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
371 static void decodeParm (MonoType *, void *, int);
372 static void enter_method (MonoMethod *, RegParm *, char *);
373 static void leave_method (MonoMethod *, ...);
374 static inline void add_general (guint *, size_data *, ArgInfo *);
375 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
376 static inline void add_float (guint *, size_data *, ArgInfo *);
377 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
378 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
379 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
380 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
382 /*========================= End of Prototypes ======================*/
384 /*------------------------------------------------------------------*/
385 /* G l o b a l V a r i a b l e s */
386 /*------------------------------------------------------------------*/
388 int mono_exc_esp_offset = 0;
390 __thread int indent_level = 0;
393 * The code generated for sequence points reads from this location,
394 * which is made read-only when single stepping is enabled.
396 static gpointer ss_trigger_page;
399 * Enabled breakpoints read from this trigger page
401 static gpointer bp_trigger_page;
403 breakpoint_t breakpointCode;
405 static mono_mutex_t mini_arch_mutex;
407 static const char * grNames[] = {
408 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
409 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
410 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
414 static const char * fpNames[] = {
415 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
416 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
417 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
421 static const char * vrNames[] = {
422 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
423 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
424 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
425 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
428 /*====================== End of Global Variables ===================*/
430 /*------------------------------------------------------------------*/
432 /* Name - mono_arch_regname */
434 /* Function - Returns the name of the register specified by */
435 /* the input parameter. */
437 /*------------------------------------------------------------------*/
440 mono_arch_regname (int reg)
442 if (reg >= 0 && reg < 16)
443 return grNames [reg];
448 /*========================= End of Function ========================*/
450 /*------------------------------------------------------------------*/
452 /* Name - mono_arch_fregname */
454 /* Function - Returns the name of the register specified by */
455 /* the input parameter. */
457 /*------------------------------------------------------------------*/
460 mono_arch_fregname (int reg)
462 if (reg >= 0 && reg < 16)
463 return fpNames [reg];
468 /*========================= End of Function ========================*/
470 /*------------------------------------------------------------------*/
472 /* Name - mono_arch_xregname */
474 /* Function - Returns the name of the register specified by */
475 /* the input parameter. */
477 /*------------------------------------------------------------------*/
480 mono_arch_xregname (int reg)
482 if (reg < s390_VR_NREG)
483 return vrNames [reg];
488 /*========================= End of Function ========================*/
490 /*------------------------------------------------------------------*/
492 /* Name - arch_get_argument_info */
494 /* Function - Gathers information on parameters such as size, */
495 /* alignment, and padding. arg_info should be large */
496 /* enough to hold param_count + 1 entries. */
498 /* Parameters - @csig - Method signature */
499 /* @param_count - No. of parameters to consider */
500 /* @arg_info - An array to store the result info */
502 /* Returns - Size of the activation frame */
504 /*------------------------------------------------------------------*/
507 mono_arch_get_argument_info (MonoMethodSignature *csig,
509 MonoJitArgumentInfo *arg_info)
511 int k, frame_size = 0;
512 int size, align, pad;
515 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
516 frame_size += sizeof (gpointer);
520 arg_info [0].offset = offset;
523 frame_size += sizeof (gpointer);
527 arg_info [0].size = frame_size;
529 for (k = 0; k < param_count; k++) {
532 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
534 size = mini_type_stack_size (csig->params [k], &align);
536 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
537 arg_info [k].pad = pad;
539 arg_info [k + 1].pad = 0;
540 arg_info [k + 1].size = size;
542 arg_info [k + 1].offset = offset;
546 align = MONO_ARCH_FRAME_ALIGNMENT;
547 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
548 arg_info [k].pad = pad;
553 /*========================= End of Function ========================*/
555 /*------------------------------------------------------------------*/
557 /* Name - emit_unwind_regs. */
559 /* Function - Determines if a value can be returned in one or */
562 /*------------------------------------------------------------------*/
564 static void __inline__
565 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
569 for (i = start; i < end; i++) {
570 mono_emit_unwind_op_offset (cfg, code, i, offset);
571 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
572 offset += sizeof(gulong);
576 /*========================= End of Function ========================*/
578 /*------------------------------------------------------------------*/
580 /* Name - retFitsInReg. */
582 /* Function - Determines if a value can be returned in one or */
585 /*------------------------------------------------------------------*/
587 static inline gboolean
588 retFitsInReg(guint32 size)
603 /*========================= End of Function ========================*/
605 /*------------------------------------------------------------------*/
607 /* Name - backStackPtr. */
609 /* Function - Restore Stack Pointer to previous frame. */
611 /*------------------------------------------------------------------*/
613 static inline guint8 *
614 backUpStackPtr(MonoCompile *cfg, guint8 *code)
616 int stackSize = cfg->stack_usage;
618 if (cfg->frame_reg != STK_BASE)
619 s390_lgr (code, STK_BASE, cfg->frame_reg);
621 if (s390_is_imm16 (stackSize)) {
622 s390_aghi (code, STK_BASE, stackSize);
624 while (stackSize > 32767) {
625 s390_aghi (code, STK_BASE, 32767);
628 s390_aghi (code, STK_BASE, stackSize);
633 /*========================= End of Function ========================*/
635 /*------------------------------------------------------------------*/
639 /* Function - Perform nice indenting to current level */
641 /*------------------------------------------------------------------*/
647 indent_level += diff;
649 printf("%p [%3d] ",(void *)pthread_self(),v);
654 indent_level += diff;
657 /*========================= End of Function ========================*/
659 /*------------------------------------------------------------------*/
661 /* Name - cvtMonoType */
663 /* Function - Convert a mono-type to a string. */
665 /*------------------------------------------------------------------*/
668 cvtMonoType(MonoTypeEnum t)
673 return "MONO_TYPE_END";
675 return "MONO_TYPE_VOID";
676 case MONO_TYPE_BOOLEAN:
677 return "MONO_TYPE_BOOLEAN";
679 return "MONO_TYPE_CHAR";
681 return "MONO_TYPE_I1";
683 return "MONO_TYPE_U1";
685 return "MONO_TYPE_I2";
687 return "MONO_TYPE_U2";
689 return "MONO_TYPE_I4";
691 return "MONO_TYPE_U4";
693 return "MONO_TYPE_I8";
695 return "MONO_TYPE_U8";
697 return "MONO_TYPE_R4";
699 return "MONO_TYPE_R8";
700 case MONO_TYPE_STRING:
701 return "MONO_TYPE_STRING";
703 return "MONO_TYPE_PTR";
704 case MONO_TYPE_BYREF:
705 return "MONO_TYPE_BYREF";
706 case MONO_TYPE_VALUETYPE:
707 return "MONO_TYPE_VALUETYPE";
708 case MONO_TYPE_CLASS:
709 return "MONO_TYPE_CLASS";
711 return "MONO_TYPE_VAR";
712 case MONO_TYPE_ARRAY:
713 return "MONO_TYPE_ARRAY";
714 case MONO_TYPE_GENERICINST:
715 return "MONO_TYPE_GENERICINST";
716 case MONO_TYPE_TYPEDBYREF:
717 return "MONO_TYPE_TYPEDBYREF";
719 return "MONO_TYPE_I";
721 return "MONO_TYPE_U";
722 case MONO_TYPE_FNPTR:
723 return "MONO_TYPE_FNPTR";
724 case MONO_TYPE_OBJECT:
725 return "MONO_TYPE_OBJECT";
726 case MONO_TYPE_SZARRAY:
727 return "MONO_TYPE_SZARRAY";
729 return "MONO_TYPE_MVAR";
730 case MONO_TYPE_CMOD_REQD:
731 return "MONO_TYPE_CMOD_REQD";
732 case MONO_TYPE_CMOD_OPT:
733 return "MONO_TYPE_CMOD_OPT";
734 case MONO_TYPE_INTERNAL:
735 return "MONO_TYPE_INTERNAL";
736 case MONO_TYPE_MODIFIER:
737 return "MONO_TYPE_MODIFIER";
738 case MONO_TYPE_SENTINEL:
739 return "MONO_TYPE_SENTINEL";
740 case MONO_TYPE_PINNED:
741 return "MONO_TYPE_PINNED";
748 /*========================= End of Function ========================*/
750 /*------------------------------------------------------------------*/
752 /* Name - decodeParm */
754 /* Function - Decode a parameter for the trace. */
756 /*------------------------------------------------------------------*/
759 decodeParmString (MonoString *s)
762 char *str = mono_string_to_utf8_checked(s, &error);
763 if (is_ok (&error)) {
764 printf("[STRING:%p:%s], ", s, str);
767 mono_error_cleanup (&error);
768 printf("[STRING:%p:], ", s);
773 decodeParm(MonoType *type, void *curParm, int size)
778 printf("[BYREF:%p], ", *((char **) curParm));
780 simpleType = mini_get_underlying_type(type)->type;
782 switch (simpleType) {
784 printf ("[INTPTR:%p], ", *((int **) curParm));
787 printf ("[UINTPTR:%p], ", *((int **) curParm));
789 case MONO_TYPE_BOOLEAN :
790 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
792 case MONO_TYPE_CHAR :
793 printf ("[CHAR:%c], ", *((int *) curParm));
796 printf ("[INT1:%ld], ", *((gint64 *) curParm));
799 printf ("[INT2:%ld], ", *((gint64 *) curParm));
802 printf ("[INT4:%ld], ", *((gint64 *) curParm));
805 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
808 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
811 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
814 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
816 case MONO_TYPE_STRING : {
817 MonoString *s = *((MonoString **) curParm);
819 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
820 decodeParmString (s);
822 printf("[STRING:null], ");
826 case MONO_TYPE_CLASS :
827 case MONO_TYPE_OBJECT : {
828 MonoObject *obj = *((MonoObject **) curParm);
830 if ((obj) && (obj->vtable)) {
831 printf("[CLASS/OBJ:");
832 klass = obj->vtable->klass;
833 printf("%p [%p] ",obj,curParm);
834 if (klass == mono_defaults.string_class) {
835 decodeParmString ((MonoString *)obj);
836 } else if (klass == mono_defaults.int32_class) {
837 printf("[INT32:%p:%d]",
838 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
841 klass->name_space, klass->name, obj);
844 printf("[OBJECT:null], ");
849 printf("[PTR:%p], ", *((gpointer **) (curParm)));
851 case MONO_TYPE_FNPTR :
852 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
854 case MONO_TYPE_ARRAY :
855 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
857 case MONO_TYPE_SZARRAY :
858 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
861 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
864 printf("[FLOAT4:%g], ", *((float *) (curParm)));
867 printf("[FLOAT8:%g], ", *((double *) (curParm)));
869 case MONO_TYPE_VALUETYPE : {
871 MonoMarshalType *info;
873 if (type->data.klass->enumtype) {
874 simpleType = mono_class_enum_basetype (type->data.klass)->type;
875 printf("{VALUETYPE} - ");
879 info = mono_marshal_load_type_info (type->data.klass);
881 if ((info->native_size == sizeof(float)) &&
882 (info->num_fields == 1) &&
883 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
884 printf("[FLOAT4:%f], ", *((float *) (curParm)));
888 if ((info->native_size == sizeof(double)) &&
889 (info->num_fields == 1) &&
890 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
891 printf("[FLOAT8:%g], ", *((double *) (curParm)));
895 printf("[VALUETYPE:");
896 for (i = 0; i < size; i++)
897 printf("%02x,", *((guint8 *)curParm+i));
901 case MONO_TYPE_TYPEDBYREF: {
903 printf("[TYPEDBYREF:");
904 for (i = 0; i < size; i++)
905 printf("%02x,", *((guint8 *)curParm+i));
910 printf("[%s], ",cvtMonoType(simpleType));
915 /*========================= End of Function ========================*/
917 /*------------------------------------------------------------------*/
919 /* Name - enter_method */
921 /* Function - Perform tracing of the entry to the current */
924 /*------------------------------------------------------------------*/
927 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
929 int i, oParm = 0, iParm = 0;
932 MonoMethodSignature *sig;
939 fname = mono_method_full_name (method, TRUE);
941 printf ("ENTER: %s ", fname);
944 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
945 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
950 sig = mono_method_signature (method);
952 cinfo = get_call_info (NULL, NULL, sig);
954 if (cinfo->struct_ret) {
955 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
960 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
961 obj = (MonoObject *) this_arg;
962 switch(method->klass->this_arg.type) {
963 case MONO_TYPE_VALUETYPE:
965 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
966 printf("this:[value:%p:%016lx], ", this_arg, *value);
968 printf ("this:[NULL], ");
970 case MONO_TYPE_STRING:
973 klass = obj->vtable->klass;
974 if (klass == mono_defaults.string_class) {
976 decodeParmString((MonoString *)obj);
978 printf ("this:%p[%s.%s], ",
979 obj, klass->name_space, klass->name);
982 printf("vtable:[NULL], ");
984 printf ("this:[NULL], ");
987 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
992 for (i = 0; i < sig->param_count; ++i) {
993 ainfo = &cinfo->args[i + oParm];
994 switch (ainfo->regtype) {
995 case RegTypeGeneral :
996 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
999 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1002 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1004 case RegTypeStructByVal :
1005 if (ainfo->reg != STK_BASE) {
1006 int offset = sizeof(glong) - ainfo->size;
1007 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1010 curParm = sp+ainfo->offset;
1012 if (retFitsInReg (ainfo->vtsize))
1013 decodeParm(sig->params[i],
1017 decodeParm(sig->params[i],
1018 *((char **) curParm),
1021 case RegTypeStructByAddr :
1022 if (ainfo->reg != STK_BASE)
1023 curParm = &(rParm->gr[ainfo->reg-2]);
1025 curParm = sp+ainfo->offset;
1027 decodeParm(sig->params[i],
1028 *((char **) curParm),
1040 /*========================= End of Function ========================*/
1042 /*------------------------------------------------------------------*/
1044 /* Name - leave_method */
1048 /*------------------------------------------------------------------*/
1051 leave_method (MonoMethod *method, ...)
1058 va_start(ap, method);
1060 fname = mono_method_full_name (method, TRUE);
1062 printf ("LEAVE: %s", fname);
1065 type = mono_method_signature (method)->ret;
1068 switch (type->type) {
1069 case MONO_TYPE_VOID:
1071 case MONO_TYPE_BOOLEAN: {
1072 int val = va_arg (ap, int);
1074 printf ("[TRUE:%d]", val);
1080 case MONO_TYPE_CHAR: {
1081 int val = va_arg (ap, int);
1082 printf ("[CHAR:%d]", val);
1085 case MONO_TYPE_I1: {
1086 int val = va_arg (ap, int);
1087 printf ("[INT1:%d]", val);
1090 case MONO_TYPE_U1: {
1091 int val = va_arg (ap, int);
1092 printf ("[UINT1:%d]", val);
1095 case MONO_TYPE_I2: {
1096 int val = va_arg (ap, int);
1097 printf ("[INT2:%d]", val);
1100 case MONO_TYPE_U2: {
1101 int val = va_arg (ap, int);
1102 printf ("[UINT2:%d]", val);
1105 case MONO_TYPE_I4: {
1106 int val = va_arg (ap, int);
1107 printf ("[INT4:%d]", val);
1110 case MONO_TYPE_U4: {
1111 int val = va_arg (ap, int);
1112 printf ("[UINT4:%d]", val);
1116 gint64 val = va_arg (ap, gint64);
1117 printf ("[INT:%ld]", val);
1122 gint64 val = va_arg (ap, gint64);
1123 printf ("[UINT:%lu]", val);
1127 case MONO_TYPE_STRING: {
1128 MonoString *s = va_arg (ap, MonoString *);
1131 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1132 decodeParmString (s);
1134 printf ("[STRING:null], ");
1137 case MONO_TYPE_CLASS:
1138 case MONO_TYPE_OBJECT: {
1139 MonoObject *o = va_arg (ap, MonoObject *);
1141 if ((o) && (o->vtable)) {
1142 if (o->vtable->klass == mono_defaults.boolean_class) {
1143 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1144 } else if (o->vtable->klass == mono_defaults.int32_class) {
1145 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1146 } else if (o->vtable->klass == mono_defaults.int64_class) {
1147 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1149 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1151 printf ("[OBJECT:%p]", o);
1156 case MONO_TYPE_FNPTR:
1157 case MONO_TYPE_ARRAY:
1158 case MONO_TYPE_SZARRAY: {
1159 gpointer p = va_arg (ap, gpointer);
1160 printf ("[result=%p]", p);
1163 case MONO_TYPE_I8: {
1164 gint64 l = va_arg (ap, gint64);
1165 printf ("[LONG:%ld]", l);
1168 case MONO_TYPE_U8: {
1169 guint64 l = va_arg (ap, guint64);
1170 printf ("[ULONG:%lu]", l);
1173 case MONO_TYPE_R4: {
1174 double f = va_arg (ap, double);
1175 printf ("[FLOAT4:%g]\n", f);
1178 case MONO_TYPE_R8: {
1179 double f = va_arg (ap, double);
1180 printf ("[FLOAT8:%g]\n", f);
1183 case MONO_TYPE_VALUETYPE: {
1184 MonoMarshalType *info;
1185 if (type->data.klass->enumtype) {
1186 type = mono_class_enum_basetype (type->data.klass);
1191 info = mono_marshal_load_type_info (type->data.klass);
1193 if ((info->native_size == sizeof(float)) &&
1194 (info->num_fields == 1) &&
1195 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1196 double f = va_arg (ap, double);
1197 printf("[FLOAT4:%g]\n", (double) f);
1201 if ((info->native_size == sizeof(double)) &&
1202 (info->num_fields == 1) &&
1203 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1204 double f = va_arg (ap, double);
1205 printf("[FLOAT8:%g]\n", f);
1209 size = mono_type_size (type, &align);
1212 guint32 p = va_arg (ap, guint32);
1213 printf ("[%02x]\n",p);
1217 guint32 p = va_arg (ap, guint32);
1218 printf ("[%04x]\n",p);
1222 guint32 p = va_arg (ap, guint32);
1223 printf ("[%08x]\n",p);
1227 guint64 p = va_arg (ap, guint64);
1228 printf ("[%016lx]\n",p);
1232 gpointer p = va_arg (ap, gpointer);
1233 printf ("[VALUETYPE] %p\n",p);
1239 case MONO_TYPE_TYPEDBYREF: {
1240 guint8 *p = va_arg (ap, gpointer);
1242 size = mono_type_size (type, &align);
1249 for (j = 0; p && j < size; j++)
1250 printf ("%02x,", p [j]);
1254 printf ("[TYPEDBYREF]\n");
1258 case MONO_TYPE_GENERICINST: {
1259 printf("[GENERICINST]\n");
1262 case MONO_TYPE_MVAR: {
1266 case MONO_TYPE_CMOD_REQD: {
1267 printf("[CMOD_REQD]\n");
1270 case MONO_TYPE_CMOD_OPT: {
1271 printf("[CMOD_OPT]\n");
1274 case MONO_TYPE_INTERNAL: {
1275 printf("[INTERNAL]\n");
1279 printf ("(unknown return type %x)",
1280 mono_method_signature (method)->ret->type);
1283 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1284 printf (" ip: %p\n", (gpointer) ip);
1288 /*========================= End of Function ========================*/
1290 /*------------------------------------------------------------------*/
1292 /* Name - mono_arch_cpu_init */
1294 /* Function - Perform CPU specific initialization to execute */
1297 /*------------------------------------------------------------------*/
1300 mono_arch_cpu_init (void)
1304 /*========================= End of Function ========================*/
1306 /*------------------------------------------------------------------*/
1308 /* Name - mono_arch_init. */
1310 /* Function - Initialize architecture specific code. */
1312 /*------------------------------------------------------------------*/
1315 mono_arch_init (void)
1319 mono_set_partial_sharing_supported (FALSE);
1320 mono_os_mutex_init_recursive (&mini_arch_mutex);
1322 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1323 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1324 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1326 code = (guint8 *) &breakpointCode;
1327 s390_basr(code, s390_r13, 0);
1329 s390_llong(code, 0);
1330 s390_lg(code, s390_r13, 0, s390_r13, 4);
1331 s390_lg(code, s390_r0, 0, s390_r13, 0);
1334 /*========================= End of Function ========================*/
1336 /*------------------------------------------------------------------*/
1338 /* Name - mono_arch_cleanup. */
1340 /* Function - Cleanup architecture specific code . */
1342 /*------------------------------------------------------------------*/
1345 mono_arch_cleanup (void)
1347 if (ss_trigger_page)
1348 mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1349 if (bp_trigger_page)
1350 mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1351 mono_os_mutex_destroy (&mini_arch_mutex);
1354 /*========================= End of Function ========================*/
1356 /*------------------------------------------------------------------*/
1358 /* Name - mono_arch_have_fast_tls */
1360 /* Function - Returns whether we use fast inlined thread local */
1361 /* storage managed access, instead of falling back */
1362 /* to native code. */
1364 /*------------------------------------------------------------------*/
1367 mono_arch_have_fast_tls (void)
1372 /*========================= End of Function ========================*/
1374 /*------------------------------------------------------------------*/
1376 /* Name - mono_arch_cpu_optimizations */
1378 /* Function - Returns the optimizations supported on this CPU */
1380 /*------------------------------------------------------------------*/
1383 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1387 /*----------------------------------------------------------*/
1388 /* No s390-specific optimizations yet */
1389 /*----------------------------------------------------------*/
1390 *exclude_mask = MONO_OPT_LINEARS;
1394 /*========================= End of Function ========================*/
1396 /*------------------------------------------------------------------*/
1398 /* Name - mono_arch_get_allocatable_int_vars */
1402 /*------------------------------------------------------------------*/
1405 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1410 for (i = 0; i < cfg->num_varinfo; i++) {
1411 MonoInst *ins = cfg->varinfo [i];
1412 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1415 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1418 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1419 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1422 /* we can only allocate 32 bit values */
1423 if (mono_is_regsize_var(ins->inst_vtype)) {
1424 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1425 g_assert (i == vmv->idx);
1426 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1433 /*========================= End of Function ========================*/
1435 /*------------------------------------------------------------------*/
1437 /* Name - mono_arch_global_int_regs */
1439 /* Function - Return a list of usable integer registers. */
1441 /*------------------------------------------------------------------*/
1444 mono_arch_get_global_int_regs (MonoCompile *cfg)
1447 MonoMethodHeader *header;
1450 header = cfg->header;
1451 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1452 cfg->frame_reg = s390_r11;
1455 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1457 for (i = 8; i < top; ++i) {
1458 if (cfg->frame_reg != i)
1459 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1465 /*========================= End of Function ========================*/
1467 /*------------------------------------------------------------------*/
1469 /* Name - mono_arch_flush_icache */
1471 /* Function - Flush the CPU icache. */
1473 /*------------------------------------------------------------------*/
1476 mono_arch_flush_icache (guint8 *code, gint size)
1480 /*========================= End of Function ========================*/
1482 /*------------------------------------------------------------------*/
1484 /* Name - add_general */
1486 /* Function - Determine code and stack size incremements for a */
1489 /*------------------------------------------------------------------*/
1492 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1494 if (*gr > S390_LAST_ARG_REG) {
1495 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1496 ainfo->offset = sz->stack_size;
1497 ainfo->reg = STK_BASE;
1498 ainfo->regtype = RegTypeBase;
1499 sz->stack_size += sizeof(long);
1500 sz->local_size += sizeof(long);
1501 sz->offStruct += sizeof(long);
1502 sz->code_size += 12;
1510 /*========================= End of Function ========================*/
1512 /*------------------------------------------------------------------*/
1514 /* Name - add_stackParm */
1516 /* Function - Determine code and stack size incremements for a */
1519 /*------------------------------------------------------------------*/
1522 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1524 if (*gr > S390_LAST_ARG_REG) {
1525 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1526 ainfo->reg = STK_BASE;
1527 ainfo->offset = sz->stack_size;
1528 ainfo->regtype = RegTypeStructByAddrOnStack;
1529 sz->stack_size += sizeof (gpointer);
1530 sz->parm_size += sizeof(gpointer);
1531 sz->offStruct += sizeof(gpointer);
1534 ainfo->offset = sz->stack_size;
1535 ainfo->regtype = RegTypeStructByAddr;
1538 ainfo->offparm = sz->offset;
1539 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1541 ainfo->vtsize = size;
1542 sz->parm_size += size;
1545 /*========================= End of Function ========================*/
1547 /*------------------------------------------------------------------*/
1549 /* Name - add_float */
1551 /* Function - Determine code and stack size incremements for a */
1552 /* float parameter. */
1554 /*------------------------------------------------------------------*/
1557 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1559 if ((*fr) <= S390_LAST_FPARG_REG) {
1560 ainfo->regtype = RegTypeFP;
1566 ainfo->offset = sz->stack_size;
1567 ainfo->reg = STK_BASE;
1568 ainfo->regtype = RegTypeBase;
1570 sz->stack_size += sizeof(double);
1571 sz->local_size += sizeof(double);
1572 sz->offStruct += sizeof(double);
1576 /*========================= End of Function ========================*/
1578 /*------------------------------------------------------------------*/
1580 /* Name - get_call_info */
1582 /* Function - Determine the amount of space required for code */
1583 /* and stack. In addition determine starting points */
1584 /* for stack-based parameters, and area for struct- */
1585 /* ures being returned on the stack. */
1587 /*------------------------------------------------------------------*/
1590 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1592 guint i, fr, gr, size, pstart;
1593 int nParm = sig->hasthis + sig->param_count;
1595 guint32 simpleType, align;
1596 gboolean is_pinvoke = sig->pinvoke;
1601 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1603 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1608 cinfo->struct_ret = 0;
1612 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1613 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1620 /*----------------------------------------------------------*/
1621 /* We determine the size of the return code/stack in case we*/
1622 /* need to reserve a register to be used to address a stack */
1623 /* area that the callee will use. */
1624 /*----------------------------------------------------------*/
1626 ret_type = mini_get_underlying_type (sig->ret);
1627 simpleType = ret_type->type;
1629 switch (simpleType) {
1630 case MONO_TYPE_BOOLEAN:
1635 case MONO_TYPE_CHAR:
1640 case MONO_TYPE_CLASS:
1641 case MONO_TYPE_OBJECT:
1642 case MONO_TYPE_SZARRAY:
1643 case MONO_TYPE_ARRAY:
1645 case MONO_TYPE_FNPTR:
1646 case MONO_TYPE_STRING:
1647 cinfo->ret.reg = s390_r2;
1652 cinfo->ret.reg = s390_f0;
1657 cinfo->ret.reg = s390_r2;
1660 case MONO_TYPE_GENERICINST:
1661 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1662 cinfo->ret.reg = s390_r2;
1667 case MONO_TYPE_VALUETYPE: {
1668 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1669 if (klass->enumtype) {
1670 simpleType = mono_class_enum_basetype (klass)->type;
1673 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1675 cinfo->struct_ret = 1;
1676 cinfo->ret.size = size;
1677 cinfo->ret.vtsize = size;
1680 case MONO_TYPE_TYPEDBYREF:
1681 size = sizeof (MonoTypedRef);
1682 cinfo->struct_ret = 1;
1683 cinfo->ret.size = size;
1684 cinfo->ret.vtsize = size;
1686 case MONO_TYPE_VOID:
1689 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1695 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1696 * the first argument, allowing 'this' to be always passed in the first arg reg.
1697 * Also do this if the first argument is a reference type, since virtual calls
1698 * are sometimes made using calli without sig->hasthis set, like in the delegate
1701 if (cinfo->struct_ret && !is_pinvoke &&
1703 (sig->param_count > 0 &&
1704 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1706 cinfo->args[nParm].size = sizeof (gpointer);
1707 add_general (&gr, sz, cinfo->args + nParm);
1709 cinfo->args[nParm].size = sizeof (gpointer);
1710 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1714 cinfo->vret_arg_index = 1;
1715 cinfo->ret.reg = gr;
1720 cinfo->args[nParm].size = sizeof (gpointer);
1721 add_general (&gr, sz, cinfo->args + nParm);
1725 if (cinfo->struct_ret) {
1726 cinfo->ret.reg = gr;
1731 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1732 gr = S390_LAST_ARG_REG + 1;
1733 fr = S390_LAST_FPARG_REG + 1;
1735 /* Emit the signature cookie just before the implicit arguments */
1736 add_general (&gr, sz, &cinfo->sigCookie);
1739 /*----------------------------------------------------------*/
1740 /* We determine the size of the parameter code and stack */
1741 /* requirements by checking the types and sizes of the */
1743 /*----------------------------------------------------------*/
1745 for (i = pstart; i < sig->param_count; ++i) {
1748 /*--------------------------------------------------*/
1749 /* Handle vararg type calls. All args are put on */
1751 /*--------------------------------------------------*/
1752 if ((sig->call_convention == MONO_CALL_VARARG) &&
1753 (i == sig->sentinelpos)) {
1754 gr = S390_LAST_ARG_REG + 1;
1755 fr = S390_LAST_FPARG_REG + 1;
1756 add_general (&gr, sz, &cinfo->sigCookie);
1759 if (sig->params [i]->byref) {
1760 add_general (&gr, sz, cinfo->args+nParm);
1761 cinfo->args[nParm].size = sizeof(gpointer);
1766 ptype = mini_get_underlying_type (sig->params [i]);
1767 simpleType = ptype->type;
1768 cinfo->args[nParm].type = simpleType;
1769 switch (simpleType) {
1770 case MONO_TYPE_BOOLEAN:
1773 cinfo->args[nParm].size = sizeof(char);
1774 add_general (&gr, sz, cinfo->args+nParm);
1779 case MONO_TYPE_CHAR:
1780 cinfo->args[nParm].size = sizeof(short);
1781 add_general (&gr, sz, cinfo->args+nParm);
1786 cinfo->args[nParm].size = sizeof(int);
1787 add_general (&gr, sz, cinfo->args+nParm);
1793 case MONO_TYPE_FNPTR:
1794 case MONO_TYPE_CLASS:
1795 case MONO_TYPE_OBJECT:
1796 case MONO_TYPE_STRING:
1797 case MONO_TYPE_SZARRAY:
1798 case MONO_TYPE_ARRAY:
1799 cinfo->args[nParm].size = sizeof(gpointer);
1800 add_general (&gr, sz, cinfo->args+nParm);
1805 cinfo->args[nParm].size = sizeof(long long);
1806 add_general (&gr, sz, cinfo->args+nParm);
1810 cinfo->args[nParm].size = sizeof(float);
1811 add_float (&fr, sz, cinfo->args+nParm);
1815 cinfo->args[nParm].size = sizeof(double);
1816 add_float (&fr, sz, cinfo->args+nParm);
1819 case MONO_TYPE_GENERICINST:
1820 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1821 cinfo->args[nParm].size = sizeof(gpointer);
1822 add_general (&gr, sz, cinfo->args+nParm);
1827 case MONO_TYPE_VALUETYPE: {
1828 MonoMarshalType *info;
1829 MonoClass *klass = mono_class_from_mono_type (ptype);
1832 size = mono_class_native_size(klass, NULL);
1834 size = mono_class_value_size(klass, NULL);
1836 if (simpleType != MONO_TYPE_GENERICINST) {
1837 info = mono_marshal_load_type_info(klass);
1839 if ((info->native_size == sizeof(float)) &&
1840 (info->num_fields == 1) &&
1841 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1842 cinfo->args[nParm].size = sizeof(float);
1843 add_float(&fr, sz, cinfo->args+nParm);
1848 if ((info->native_size == sizeof(double)) &&
1849 (info->num_fields == 1) &&
1850 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1851 cinfo->args[nParm].size = sizeof(double);
1852 add_float(&fr, sz, cinfo->args+nParm);
1858 cinfo->args[nParm].vtsize = 0;
1859 cinfo->args[nParm].size = 0;
1862 /*----------------------------------*/
1863 /* On S/390, structures of size 1, */
1864 /* 2, 4, and 8 bytes are passed in */
1865 /* (a) register(s). */
1866 /*----------------------------------*/
1872 add_general(&gr, sz, cinfo->args+nParm);
1873 cinfo->args[nParm].size = size;
1874 cinfo->args[nParm].regtype = RegTypeStructByVal;
1876 sz->local_size += sizeof(long);
1879 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1884 case MONO_TYPE_TYPEDBYREF: {
1885 int size = sizeof (MonoTypedRef);
1887 cinfo->args[nParm].vtsize = 0;
1888 cinfo->args[nParm].size = 0;
1891 /*----------------------------------*/
1892 /* On S/390, structures of size 1, */
1893 /* 2, 4, and 8 bytes are passed in */
1894 /* (a) register(s). */
1895 /*----------------------------------*/
1901 add_general(&gr, sz, cinfo->args+nParm);
1902 cinfo->args[nParm].size = size;
1903 cinfo->args[nParm].regtype = RegTypeStructByVal;
1905 sz->local_size += sizeof(long);
1908 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1914 g_error ("Can't trampoline 0x%x", ptype);
1918 /*----------------------------------------------------------*/
1919 /* Handle the case where there are no implicit arguments */
1920 /*----------------------------------------------------------*/
1921 if ((sig->call_convention == MONO_CALL_VARARG) &&
1924 (sig->param_count == sig->sentinelpos)) {
1925 gr = S390_LAST_ARG_REG + 1;
1926 fr = S390_LAST_FPARG_REG + 1;
1927 add_general (&gr, sz, &cinfo->sigCookie);
1930 /*----------------------------------------------------------*/
1931 /* If we are passing a structure back then if it won't be */
1932 /* in a register(s) then we make room at the end of the */
1933 /* parameters that may have been placed on the stack */
1934 /*----------------------------------------------------------*/
1935 if (cinfo->struct_ret) {
1936 cinfo->ret.offset = sz->stack_size;
1937 switch (cinfo->ret.size) {
1945 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1950 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1952 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1957 /*========================= End of Function ========================*/
1959 /*------------------------------------------------------------------*/
1961 /* Name - mono_arch_allocate_vars */
1963 /* Function - Set var information according to the calling */
1964 /* convention for S/390. The local var stuff should */
1965 /* most likely be split in another method. */
1967 /* Parameter - @m - Compile unit. */
1969 /*------------------------------------------------------------------*/
1972 mono_arch_allocate_vars (MonoCompile *cfg)
1974 MonoMethodSignature *sig;
1975 MonoMethodHeader *header;
1978 int iParm, iVar, offset, align, size, curinst;
1979 int frame_reg = STK_BASE;
1982 header = cfg->header;
1984 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1986 /*---------------------------------------------------------*/
1987 /* We use the frame register also for any method that has */
1988 /* filter clauses. This way, when the handlers are called, */
1989 /* the code will reference local variables using the frame */
1990 /* reg instead of the stack pointer: if we had to restore */
1991 /* the stack pointer, we'd corrupt the method frames that */
1992 /* are already on the stack (since filters get called */
1993 /* before stack unwinding happens) when the filter code */
1994 /* would call any method. */
1995 /*---------------------------------------------------------*/
1996 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1997 frame_reg = s390_r11;
1999 cfg->frame_reg = frame_reg;
2001 cfg->arch.bkchain_reg = -1;
2003 if (frame_reg != STK_BASE)
2004 cfg->used_int_regs |= (1 << frame_reg);
2006 if (cfg->uses_rgctx_reg)
2007 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2009 sig = mono_method_signature (cfg->method);
2011 cinfo = get_call_info (cfg, cfg->mempool, sig);
2013 if (!cinfo->struct_ret) {
2014 switch (mini_get_underlying_type (sig->ret)->type) {
2015 case MONO_TYPE_VOID:
2018 cfg->ret->opcode = OP_REGVAR;
2019 cfg->ret->dreg = s390_r2;
2024 /*--------------------------------------------------------------*/
2025 /* local vars are at a positive offset from the stack pointer */
2026 /* also note that if the function uses alloca, we use s390_r11 */
2027 /* to point at the local variables. */
2028 /* add parameter area size for called functions */
2029 /*--------------------------------------------------------------*/
2030 if (cfg->param_area == 0)
2031 offset = S390_MINIMAL_STACK_SIZE;
2033 offset = cfg->param_area;
2035 cfg->sig_cookie = 0;
2037 if (cinfo->struct_ret) {
2038 inst = cfg->vret_addr;
2039 offset = S390_ALIGN(offset, sizeof(gpointer));
2040 inst->inst_offset = offset;
2041 inst->opcode = OP_REGOFFSET;
2042 inst->inst_basereg = frame_reg;
2043 offset += sizeof(gpointer);
2044 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2045 printf ("vret_addr =");
2046 mono_print_ins (cfg->vret_addr);
2051 inst = cfg->args [0];
2052 if (inst->opcode != OP_REGVAR) {
2053 inst->opcode = OP_REGOFFSET;
2054 inst->inst_basereg = frame_reg;
2055 offset = S390_ALIGN(offset, sizeof(gpointer));
2056 inst->inst_offset = offset;
2057 offset += sizeof (gpointer);
2064 eArg = sig->param_count + sArg;
2066 if (sig->call_convention == MONO_CALL_VARARG)
2067 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2069 for (iParm = sArg; iParm < eArg; ++iParm) {
2070 inst = cfg->args [curinst];
2071 if (inst->opcode != OP_REGVAR) {
2072 switch (cinfo->args[iParm].regtype) {
2073 case RegTypeStructByAddr : {
2076 size = sizeof (gpointer);
2078 inst->opcode = OP_REGOFFSET;
2079 inst->inst_basereg = frame_reg;
2080 offset = S390_ALIGN (offset, sizeof (gpointer));
2081 inst->inst_offset = offset;
2083 /* Add a level of indirection */
2084 MONO_INST_NEW (cfg, indir, 0);
2086 inst->opcode = OP_VTARG_ADDR;
2087 inst->inst_left = indir;
2090 case RegTypeStructByAddrOnStack : {
2093 size = sizeof (gpointer);
2095 /* Similar to the == STK_BASE case below */
2096 cfg->arch.bkchain_reg = s390_r12;
2097 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2099 inst->opcode = OP_REGOFFSET;
2100 inst->dreg = mono_alloc_preg (cfg);
2101 inst->inst_basereg = cfg->arch.bkchain_reg;
2102 inst->inst_offset = cinfo->args [iParm].offset;
2104 /* Add a level of indirection */
2105 MONO_INST_NEW (cfg, indir, 0);
2107 inst->opcode = OP_VTARG_ADDR;
2108 inst->inst_left = indir;
2111 case RegTypeStructByVal :
2112 size = cinfo->args[iParm].size;
2113 offset = S390_ALIGN(offset, size);
2114 inst->opcode = OP_REGOFFSET;
2115 inst->inst_basereg = frame_reg;
2116 inst->inst_offset = offset;
2119 if (cinfo->args [iParm].reg == STK_BASE) {
2121 * These arguments are in the previous frame, so we can't
2122 * compute their offset from the current frame pointer right
2123 * now, since cfg->stack_offset is not yet known, so dedicate a
2124 * register holding the previous frame pointer.
2126 cfg->arch.bkchain_reg = s390_r12;
2127 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2129 inst->opcode = OP_REGOFFSET;
2130 inst->inst_basereg = cfg->arch.bkchain_reg;
2131 size = (cinfo->args[iParm].size < 8
2132 ? 8 - cinfo->args[iParm].size
2134 inst->inst_offset = cinfo->args [iParm].offset + size;
2135 size = sizeof (long);
2137 inst->opcode = OP_REGOFFSET;
2138 inst->inst_basereg = frame_reg;
2139 size = (cinfo->args[iParm].size < 8
2142 offset = S390_ALIGN(offset, size);
2143 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2144 inst->inst_offset = offset;
2146 inst->inst_offset = offset + (8 - size);
2151 if ((sig->call_convention == MONO_CALL_VARARG) &&
2152 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2153 (iParm < sig->sentinelpos))
2154 cfg->sig_cookie += size;
2155 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2158 offset += MAX(size, 8);
2163 cfg->locals_min_stack_offset = offset;
2165 curinst = cfg->locals_start;
2166 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2167 inst = cfg->varinfo [iVar];
2168 if ((inst->flags & MONO_INST_IS_DEAD) ||
2169 (inst->opcode == OP_REGVAR))
2172 /*--------------------------------------------------*/
2173 /* inst->backend.is_pinvoke indicates native sized */
2174 /* value typs this is used by the pinvoke wrappers */
2175 /* when they call functions returning structure */
2176 /*--------------------------------------------------*/
2177 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2178 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2179 (guint32 *) &align);
2181 size = mono_type_size (inst->inst_vtype, &align);
2183 offset = S390_ALIGN(offset, align);
2184 inst->inst_offset = offset;
2185 inst->opcode = OP_REGOFFSET;
2186 inst->inst_basereg = frame_reg;
2188 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2189 iVar, inst->inst_offset, size));
2192 cfg->locals_max_stack_offset = offset;
2194 /*------------------------------------------------------*/
2195 /* Allow space for the trace method stack area if needed*/
2196 /*------------------------------------------------------*/
2197 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2198 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2199 offset += S390_TRACE_STACK_SIZE;
2201 /*------------------------------------------------------*/
2202 /* Reserve space to save LMF and caller saved registers */
2203 /*------------------------------------------------------*/
2204 if (cfg->method->save_lmf)
2205 offset += sizeof (MonoLMF);
2207 /*------------------------------------------------------*/
2208 /* align the offset */
2209 /*------------------------------------------------------*/
2210 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2212 /*------------------------------------------------------*/
2213 /* Fix offsets for args whose value is in parent frame */
2214 /*------------------------------------------------------*/
2215 for (iParm = sArg; iParm < eArg; ++iParm) {
2216 inst = cfg->args [iParm];
2218 if (inst->opcode == OP_S390_STKARG) {
2219 inst->opcode = OP_REGOFFSET;
2220 inst->inst_offset += cfg->stack_offset;
2225 /*========================= End of Function ========================*/
2227 /*------------------------------------------------------------------*/
2229 /* Name - mono_arch_create_vars */
2231 /*------------------------------------------------------------------*/
2234 mono_arch_create_vars (MonoCompile *cfg)
2236 MonoMethodSignature *sig;
2239 sig = mono_method_signature (cfg->method);
2241 cinfo = get_call_info (cfg, cfg->mempool, sig);
2243 if (cinfo->struct_ret) {
2244 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2245 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2246 printf ("vret_addr = ");
2247 mono_print_ins (cfg->vret_addr);
2252 /*========================= End of Function ========================*/
2254 /*------------------------------------------------------------------*/
2256 /* Name - add_outarg_reg2. */
2258 /*------------------------------------------------------------------*/
2261 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2266 case RegTypeGeneral:
2267 MONO_INST_NEW (cfg, ins, OP_MOVE);
2268 ins->dreg = mono_alloc_ireg (cfg);
2269 ins->sreg1 = tree->dreg;
2270 MONO_ADD_INS (cfg->cbb, ins);
2271 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2274 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2275 ins->dreg = mono_alloc_freg (cfg);
2276 ins->sreg1 = tree->dreg;
2277 MONO_ADD_INS (cfg->cbb, ins);
2278 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2281 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2282 ins->dreg = mono_alloc_freg (cfg);
2283 ins->sreg1 = tree->dreg;
2284 MONO_ADD_INS (cfg->cbb, ins);
2285 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2288 g_assert_not_reached ();
2292 /*========================= End of Function ========================*/
2294 /*------------------------------------------------------------------*/
2296 /* Name - emit_sig_cookie. */
2298 /*------------------------------------------------------------------*/
2301 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2303 MonoMethodSignature *tmpSig;
2306 cfg->disable_aot = TRUE;
2308 /*----------------------------------------------------------*/
2309 /* mono_ArgIterator_Setup assumes the signature cookie is */
2310 /* passed first and all the arguments which were before it */
2311 /* passed on the stack after the signature. So compensate */
2312 /* by passing a different signature. */
2313 /*----------------------------------------------------------*/
2314 tmpSig = mono_metadata_signature_dup (call->signature);
2315 tmpSig->param_count -= call->signature->sentinelpos;
2316 tmpSig->sentinelpos = 0;
2317 if (tmpSig->param_count > 0)
2318 memcpy (tmpSig->params,
2319 call->signature->params + call->signature->sentinelpos,
2320 tmpSig->param_count * sizeof(MonoType *));
2322 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2323 sig_arg->dreg = mono_alloc_ireg (cfg);
2324 sig_arg->inst_p0 = tmpSig;
2325 MONO_ADD_INS (cfg->cbb, sig_arg);
2327 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2328 cinfo->sigCookie.offset, sig_arg->dreg);
2331 /*========================= End of Function ========================*/
2333 /*------------------------------------------------------------------*/
2335 /* Name - mono_arch_emit_call */
2337 /*------------------------------------------------------------------*/
2340 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2343 MonoMethodSignature *sig;
2345 int i, n, lParamArea;
2347 ArgInfo *ainfo = NULL;
2349 MonoMethodHeader *header;
2352 sig = call->signature;
2353 n = sig->param_count + sig->hasthis;
2354 DEBUG (g_print ("Call requires: %d parameters\n",n));
2356 cinfo = get_call_info (cfg, cfg->mempool, sig);
2358 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2359 cinfo->sz.parm_size + cinfo->sz.offset;
2360 call->stack_usage = MAX(stackSize, call->stack_usage);
2361 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2362 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2363 cfg->flags |= MONO_CFG_HAS_CALLS;
2365 if (cinfo->struct_ret) {
2366 MONO_INST_NEW (cfg, ins, OP_MOVE);
2367 ins->sreg1 = call->vret_var->dreg;
2368 ins->dreg = mono_alloc_preg (cfg);
2369 MONO_ADD_INS (cfg->cbb, ins);
2370 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2373 header = cfg->header;
2374 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2379 for (i = 0; i < n; ++i) {
2382 ainfo = cinfo->args + i;
2383 if (i >= sig->hasthis)
2384 t = sig->params [i - sig->hasthis];
2386 t = &mono_defaults.int_class->byval_arg;
2387 t = mini_get_underlying_type (t);
2389 in = call->args [i];
2391 if ((sig->call_convention == MONO_CALL_VARARG) &&
2393 (i == sig->sentinelpos)) {
2394 emit_sig_cookie (cfg, call, cinfo);
2397 switch (ainfo->regtype) {
2398 case RegTypeGeneral:
2399 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2402 if (MONO_TYPE_ISSTRUCT (t)) {
2403 /* Valuetype passed in one fp register */
2404 ainfo->regtype = RegTypeStructByValInFP;
2407 if (ainfo->size == 4)
2408 ainfo->regtype = RegTypeFPR4;
2409 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2412 case RegTypeStructByVal:
2413 case RegTypeStructByAddr:
2414 case RegTypeStructByAddrOnStack: {
2418 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2419 size = sizeof (MonoTypedRef);
2420 align = sizeof (gpointer);
2424 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2427 * Other backends use mono_type_stack_size (), but that
2428 * aligns the size to 8, which is larger than the size of
2429 * the source, leading to reads of invalid memory if the
2430 * source is at the end of address space.
2432 size = mono_class_value_size (in->klass, &align);
2435 g_assert (in->klass);
2437 ainfo->offparm += cinfo->sz.offStruct;
2439 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2440 ins->sreg1 = in->dreg;
2441 ins->klass = in->klass;
2442 ins->backend.size = ainfo->size;
2443 ins->inst_p0 = call;
2444 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2445 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2447 MONO_ADD_INS (cfg->cbb, ins);
2449 if (ainfo->regtype == RegTypeStructByAddr) {
2451 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2452 * use the normal OUTARG opcodes to pass the address of the location to
2455 int treg = mono_alloc_preg (cfg);
2456 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2457 frmReg, ainfo->offparm);
2458 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2459 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2460 /* The address of the valuetype is passed on the stack */
2461 int treg = mono_alloc_preg (cfg);
2462 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2463 frmReg, ainfo->offparm);
2464 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2465 ainfo->reg, ainfo->offset, treg);
2467 if (cfg->compute_gc_maps) {
2470 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2476 if (!t->byref && t->type == MONO_TYPE_R4) {
2477 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2478 STK_BASE, ainfo->offset + 4,
2480 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2481 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2482 STK_BASE, ainfo->offset,
2485 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2486 ins->inst_destbasereg = STK_BASE;
2487 ins->inst_offset = ainfo->offset;
2488 ins->sreg1 = in->dreg;
2491 /* This is needed by MonoTypedRef->value to point to the correct data */
2492 if ((sig->call_convention == MONO_CALL_VARARG) &&
2493 (i >= sig->sentinelpos)) {
2494 switch (ainfo->size) {
2496 ins->opcode = OP_STOREI1_MEMBASE_REG;
2499 ins->opcode = OP_STOREI2_MEMBASE_REG;
2502 ins->opcode = OP_STOREI4_MEMBASE_REG;
2510 MONO_ADD_INS (cfg->cbb, ins);
2514 g_assert_not_reached ();
2520 * Handle the case where there are no implicit arguments
2522 if ((sig->call_convention == MONO_CALL_VARARG) &&
2524 (i == sig->sentinelpos)) {
2525 emit_sig_cookie (cfg, call, cinfo);
2529 /*========================= End of Function ========================*/
2531 /*------------------------------------------------------------------*/
2533 /* Name - mono_arch_emit_outarg_vt */
2535 /*------------------------------------------------------------------*/
2538 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2540 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2541 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2542 int size = ins->backend.size;
2544 if (ainfo->regtype == RegTypeStructByVal) {
2546 arg->ins.sreg1 = ainfo->reg;
2547 arg->ins.opcode = OP_OUTARG_VT;
2548 arg->size = ainfo->size;
2549 arg->offset = ainfo->offset;
2550 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2552 if (ainfo->reg != STK_BASE) {
2553 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2555 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2558 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2559 int dreg = mono_alloc_freg (cfg);
2561 if (ainfo->size == 4) {
2562 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2563 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2565 g_assert (ainfo->size == 8);
2567 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2570 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2573 MonoMethodHeader *header;
2576 header = mono_method_get_header_checked (cfg->method, &error);
2577 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2578 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2583 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2584 src->dreg, 0, size);
2586 if (cfg->compute_gc_maps) {
2589 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2594 /*========================= End of Function ========================*/
2596 /*------------------------------------------------------------------*/
2598 /* Name - mono_arch_emit_setret */
2600 /*------------------------------------------------------------------*/
2603 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2605 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2608 if (ret->type == MONO_TYPE_R4) {
2609 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2611 } else if (ret->type == MONO_TYPE_R8) {
2612 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2617 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2620 /*========================= End of Function ========================*/
2622 /*------------------------------------------------------------------*/
2624 /* Name - mono_arch_instrument_mem_needs */
2626 /* Function - Allow tracing to work with this interface (with */
2627 /* an optional argument). */
2629 /*------------------------------------------------------------------*/
2632 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2634 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2636 /* split prolog-epilog requirements? */
2637 *code = 50; /* max bytes needed: check this number */
2640 /*========================= End of Function ========================*/
2642 /*------------------------------------------------------------------*/
2644 /* Name - mono_arch_instrument_prolog */
2646 /* Function - Create an "instrumented" prolog. */
2648 /*------------------------------------------------------------------*/
2651 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2652 gboolean enable_arguments)
2659 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2660 if (cfg->method->save_lmf)
2661 parmOffset -= sizeof(MonoLMF);
2662 fpOffset = parmOffset + (5*sizeof(gpointer));
2665 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2666 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2667 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2668 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2669 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2670 S390_SET (code, s390_r1, func);
2671 S390_SET (code, s390_r2, cfg->method);
2672 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2673 s390_lgr (code, s390_r4, STK_BASE);
2674 s390_aghi (code, s390_r4, cfg->stack_usage);
2675 s390_basr (code, s390_r14, s390_r1);
2676 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2677 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2678 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2679 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2680 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2685 /*========================= End of Function ========================*/
2687 /*------------------------------------------------------------------*/
2689 /* Name - mono_arch_instrument_epilog */
2691 /* Function - Create an epilog that will handle the returned */
2692 /* values used in instrumentation. */
2694 /*------------------------------------------------------------------*/
2697 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2700 int save_mode = SAVE_NONE,
2703 MonoMethod *method = cfg->method;
2704 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2706 offset = code - cfg->native_code;
2707 /*-----------------------------------------*/
2708 /* We need about 128 bytes of instructions */
2709 /*-----------------------------------------*/
2710 if (offset > (cfg->code_size - 128)) {
2711 cfg->code_size *= 2;
2712 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2713 code = cfg->native_code + offset;
2716 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2717 if (method->save_lmf)
2718 saveOffset -= sizeof(MonoLMF);
2722 case MONO_TYPE_VOID:
2723 /* special case string .ctor icall */
2724 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2725 save_mode = SAVE_ONE;
2727 save_mode = SAVE_NONE;
2731 save_mode = SAVE_ONE;
2734 save_mode = SAVE_R4;
2737 save_mode = SAVE_R8;
2739 case MONO_TYPE_VALUETYPE:
2740 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2741 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2744 save_mode = SAVE_STRUCT;
2747 save_mode = SAVE_ONE;
2751 switch (save_mode) {
2753 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2754 if (enable_arguments) {
2755 s390_lgr (code, s390_r3, s390_r2);
2759 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2760 if (enable_arguments) {
2761 s390_ldebr (code, s390_f0, s390_f0);
2765 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2768 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2769 if (enable_arguments) {
2770 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2771 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2779 S390_SET (code, s390_r1, func);
2780 S390_SET (code, s390_r2, cfg->method);
2781 s390_basr (code, s390_r14, s390_r1);
2783 switch (save_mode) {
2785 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2789 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2792 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2802 /*========================= End of Function ========================*/
2804 /*------------------------------------------------------------------*/
2806 /* Name - mono_arch_peephole_pass_1 */
2808 /* Function - Form a peephole pass at the code looking for */
2809 /* simple optimizations. */
2811 /*------------------------------------------------------------------*/
2814 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2818 /*========================= End of Function ========================*/
2820 /*------------------------------------------------------------------*/
2822 /* Name - mono_arch_peephole_pass_2 */
2824 /* Function - Form a peephole pass at the code looking for */
2825 /* simple optimizations. */
2827 /*------------------------------------------------------------------*/
2830 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2834 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2835 mono_peephole_ins (bb, ins);
2839 /*========================= End of Function ========================*/
2841 /*------------------------------------------------------------------*/
2843 /* Name - mono_arch_lowering_pass. */
2845 /*------------------------------------------------------------------*/
2848 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2850 MonoInst *ins, *next;
2852 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2853 switch (ins->opcode) {
2858 case OP_IDIV_UN_IMM:
2859 case OP_IREM_UN_IMM:
2864 case OP_LOCALLOC_IMM:
2865 mono_decompose_op_imm (cfg, bb, ins);
2868 if (!s390_is_imm16 (ins->inst_imm))
2869 /* This is created by the memcpy code which ignores is_inst_imm */
2870 mono_decompose_op_imm (cfg, bb, ins);
2877 bb->max_vreg = cfg->next_vreg;
2880 /*========================= End of Function ========================*/
2882 /*------------------------------------------------------------------*/
2884 /* Name - emit_float_to_int */
2886 /* Function - Create instructions which will convert a floating */
2887 /* point value to integer. */
2889 /*------------------------------------------------------------------*/
2892 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2894 /* sreg is a float, dreg is an integer reg. */
2896 s390_cgdbr (code, dreg, 5, sreg);
2899 s390_ltgr (code, dreg, dreg);
2901 s390_oill (code, dreg, 0x80);
2902 s390_lghi (code, s390_r0, 0xff);
2903 s390_ngr (code, dreg, s390_r0);
2906 s390_ltgr (code, dreg, dreg);
2908 s390_oill (code, dreg, 0x8000);
2909 s390_llill(code, s390_r0, 0xffff);
2910 s390_ngr (code, dreg, s390_r0);
2915 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2916 s390_ldgr (code, s390_f14, s390_r13);
2917 s390_ldr (code, s390_f15, sreg);
2918 s390_cdbr (code, s390_f15, s390_f14);
2919 s390_jl (code, 0); CODEPTR (code, o[0]);
2920 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2921 s390_ldgr (code, s390_f14, s390_r13);
2922 s390_sdbr (code, s390_f15, s390_f14);
2923 s390_cfdbr (code, dreg, 7, s390_f15);
2925 PTRSLOT (code, o[0]);
2926 s390_cfdbr (code, dreg, 5, sreg);
2929 s390_lghi (code, s390_r0, 0xff);
2930 s390_ngr (code, dreg, s390_r0);
2933 s390_llill(code, s390_r0, 0xffff);
2934 s390_ngr (code, dreg, s390_r0);
2941 /*========================= End of Function ========================*/
2943 /*------------------------------------------------------------------*/
2945 /* Name - gboolean_is_unsigned. */
2947 /* Function - Return TRUE if next opcode is checking for un- */
2950 /*------------------------------------------------------------------*/
2953 gboolean is_unsigned (MonoInst *next)
2956 (((next->opcode >= OP_IBNE_UN) &&
2957 (next->opcode <= OP_IBLT_UN)) ||
2958 ((next->opcode >= OP_LBNE_UN) &&
2959 (next->opcode <= OP_LBLT_UN)) ||
2960 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2961 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2962 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2963 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2964 ((next->opcode == OP_CLT_UN) ||
2965 (next->opcode == OP_CGT_UN)) ||
2966 ((next->opcode == OP_ICLT_UN) ||
2967 (next->opcode == OP_ICGT_UN) ||
2968 (next->opcode == OP_LCLT_UN) ||
2969 (next->opcode == OP_LCGT_UN))))
2975 /*========================= End of Function ========================*/
2977 /*------------------------------------------------------------------*/
2979 /* Name - mono_arch_output_basic_block */
2981 /* Function - Perform the "real" work of emitting instructions */
2982 /* that will do the work of in the basic block. */
2984 /*------------------------------------------------------------------*/
2987 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2992 guint8 *code = cfg->native_code + cfg->code_len;
2993 guint last_offset = 0;
2996 /* we don't align basic blocks of loops on s390 */
2998 if (cfg->verbose_level > 2)
2999 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3001 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
3002 MonoProfileCoverageInfo *cov = cfg->coverage_info;
3003 g_assert (!mono_compile_aot);
3004 cov->data [bb->dfn].cil_code = bb->cil_code;
3005 /* This is not thread save, but good enough */
3006 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
3007 s390_alsi (code, 0, s390_r1, 1);
3010 MONO_BB_FOR_EACH_INS (bb, ins) {
3011 offset = code - cfg->native_code;
3013 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3015 if (offset > (cfg->code_size - max_len - 16)) {
3016 cfg->code_size *= 2;
3017 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3018 code = cfg->native_code + offset;
3021 mono_debug_record_line_number (cfg, ins, offset);
3023 switch (ins->opcode) {
3024 case OP_STOREI1_MEMBASE_IMM: {
3025 s390_lghi (code, s390_r0, ins->inst_imm);
3026 S390_LONG (code, stcy, stc, s390_r0, 0,
3027 ins->inst_destbasereg, ins->inst_offset);
3030 case OP_STOREI2_MEMBASE_IMM: {
3031 s390_lghi (code, s390_r0, ins->inst_imm);
3032 S390_LONG (code, sthy, sth, s390_r0, 0,
3033 ins->inst_destbasereg, ins->inst_offset);
3036 case OP_STOREI4_MEMBASE_IMM: {
3037 s390_lgfi (code, s390_r0, ins->inst_imm);
3038 S390_LONG (code, sty, st, s390_r0, 0,
3039 ins->inst_destbasereg, ins->inst_offset);
3042 case OP_STORE_MEMBASE_IMM:
3043 case OP_STOREI8_MEMBASE_IMM: {
3044 S390_SET (code, s390_r0, ins->inst_imm);
3045 S390_LONG (code, stg, stg, s390_r0, 0,
3046 ins->inst_destbasereg, ins->inst_offset);
3049 case OP_STOREI1_MEMBASE_REG: {
3050 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3051 ins->inst_destbasereg, ins->inst_offset);
3054 case OP_STOREI2_MEMBASE_REG: {
3055 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3056 ins->inst_destbasereg, ins->inst_offset);
3059 case OP_STOREI4_MEMBASE_REG: {
3060 S390_LONG (code, sty, st, ins->sreg1, 0,
3061 ins->inst_destbasereg, ins->inst_offset);
3064 case OP_STORE_MEMBASE_REG:
3065 case OP_STOREI8_MEMBASE_REG: {
3066 S390_LONG (code, stg, stg, ins->sreg1, 0,
3067 ins->inst_destbasereg, ins->inst_offset);
3071 g_assert_not_reached ();
3073 case OP_LOAD_MEMBASE:
3074 case OP_LOADI8_MEMBASE: {
3075 S390_LONG (code, lg, lg, ins->dreg, 0,
3076 ins->inst_basereg, ins->inst_offset);
3079 case OP_LOADI4_MEMBASE: {
3080 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3081 ins->inst_basereg, ins->inst_offset);
3084 case OP_LOADU4_MEMBASE: {
3085 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3086 ins->inst_basereg, ins->inst_offset);
3089 case OP_LOADU1_MEMBASE: {
3090 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3091 ins->inst_basereg, ins->inst_offset);
3094 case OP_LOADI1_MEMBASE: {
3095 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3096 ins->inst_basereg, ins->inst_offset);
3099 case OP_LOADU2_MEMBASE: {
3100 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3101 ins->inst_basereg, ins->inst_offset);
3104 case OP_LOADI2_MEMBASE: {
3105 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3106 ins->inst_basereg, ins->inst_offset);
3109 case OP_LCONV_TO_I1: {
3110 s390_lgbr (code, ins->dreg, ins->sreg1);
3113 case OP_LCONV_TO_I2: {
3114 s390_lghr (code, ins->dreg, ins->sreg1);
3117 case OP_LCONV_TO_U1: {
3118 s390_llgcr (code, ins->dreg, ins->sreg1);
3121 case OP_LCONV_TO_U2: {
3122 s390_llghr (code, ins->dreg, ins->sreg1);
3125 case OP_ICONV_TO_I1: {
3126 s390_lgbr (code, ins->dreg, ins->sreg1);
3129 case OP_ICONV_TO_I2: {
3130 s390_lghr (code, ins->dreg, ins->sreg1);
3133 case OP_ICONV_TO_U1: {
3134 s390_llgcr (code, ins->dreg, ins->sreg1);
3137 case OP_ICONV_TO_U2: {
3138 s390_llghr (code, ins->dreg, ins->sreg1);
3143 if (is_unsigned (ins->next))
3144 s390_clgr (code, ins->sreg1, ins->sreg2);
3146 s390_cgr (code, ins->sreg1, ins->sreg2);
3150 if (is_unsigned (ins->next))
3151 s390_clr (code, ins->sreg1, ins->sreg2);
3153 s390_cr (code, ins->sreg1, ins->sreg2);
3156 case OP_COMPARE_IMM:
3157 case OP_LCOMPARE_IMM: {
3158 S390_SET (code, s390_r0, ins->inst_imm);
3159 if (is_unsigned (ins->next))
3160 s390_clgr (code, ins->sreg1, s390_r0);
3162 s390_cgr (code, ins->sreg1, s390_r0);
3165 case OP_ICOMPARE_IMM: {
3166 S390_SET (code, s390_r0, ins->inst_imm);
3167 if (is_unsigned (ins->next))
3168 s390_clr (code, ins->sreg1, s390_r0);
3170 s390_cr (code, ins->sreg1, s390_r0);
3174 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3176 S390_CALL_TEMPLATE (code, s390_r14);
3181 s390_agr (code, ins->dreg, src2);
3186 s390_agr (code, ins->dreg, src2);
3191 s390_alcgr (code, ins->dreg, src2);
3195 if (ins->dreg != ins->sreg1) {
3196 s390_lgr (code, ins->dreg, ins->sreg1);
3198 if (s390_is_imm16 (ins->inst_imm)) {
3199 s390_aghi (code, ins->dreg, ins->inst_imm);
3200 } else if (s390_is_imm32 (ins->inst_imm)) {
3201 s390_agfi (code, ins->dreg, ins->inst_imm);
3203 S390_SET (code, s390_r0, ins->inst_imm);
3204 s390_agr (code, ins->dreg, s390_r0);
3209 if (ins->dreg != ins->sreg1) {
3210 s390_lgr (code, ins->dreg, ins->sreg1);
3212 g_assert (s390_is_imm16 (ins->inst_imm));
3213 s390_aghi (code, ins->dreg, ins->inst_imm);
3217 if (ins->dreg != ins->sreg1) {
3218 s390_lgr (code, ins->dreg, ins->sreg1);
3220 if (s390_is_imm16 (ins->inst_imm)) {
3221 s390_lghi (code, s390_r0, ins->inst_imm);
3222 s390_alcgr (code, ins->dreg, s390_r0);
3224 S390_SET (code, s390_r0, ins->inst_imm);
3225 s390_alcgr (code, ins->dreg, s390_r0);
3230 case OP_S390_IADD_OVF: {
3232 s390_ar (code, ins->dreg, src2);
3233 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3234 s390_lgfr (code, ins->dreg, ins->dreg);
3237 case OP_IADD_OVF_UN:
3238 case OP_S390_IADD_OVF_UN: {
3240 s390_algr (code, ins->dreg, src2);
3241 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3242 s390_llgfr (code, ins->dreg, ins->dreg);
3245 case OP_ADD_OVF_CARRY: {
3247 s390_lghi (code, s390_r0, 0);
3248 s390_lgr (code, s390_r1, s390_r0);
3249 s390_alcgr (code, s390_r0, s390_r1);
3250 s390_agr (code, ins->dreg, src2);
3251 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3252 s390_agr (code, ins->dreg, s390_r0);
3253 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3256 case OP_ADD_OVF_UN_CARRY: {
3258 s390_alcgr (code, ins->dreg, src2);
3259 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3264 s390_sgr (code, ins->dreg, src2);
3269 s390_sgr (code, ins->dreg, src2);
3274 s390_slbgr(code, ins->dreg, src2);
3278 if (ins->dreg != ins->sreg1) {
3279 s390_lgr (code, ins->dreg, ins->sreg1);
3281 if (s390_is_imm16 (-ins->inst_imm)) {
3282 s390_aghi (code, ins->dreg, -ins->inst_imm);
3283 } else if (s390_is_imm32 (-ins->inst_imm)) {
3284 s390_slgfi (code, ins->dreg, ins->inst_imm);
3286 S390_SET (code, s390_r0, ins->inst_imm);
3287 s390_slgr (code, ins->dreg, s390_r0);
3292 if (ins->dreg != ins->sreg1) {
3293 s390_lgr (code, ins->dreg, ins->sreg1);
3295 if (s390_is_imm16 (-ins->inst_imm)) {
3296 s390_aghi (code, ins->dreg, -ins->inst_imm);
3297 } else if (s390_is_imm32 (-ins->inst_imm)) {
3298 s390_slgfi (code, ins->dreg, ins->inst_imm);
3300 S390_SET (code, s390_r0, ins->inst_imm);
3301 s390_slgr (code, ins->dreg, s390_r0);
3306 if (ins->dreg != ins->sreg1) {
3307 s390_lgr (code, ins->dreg, ins->sreg1);
3309 if (s390_is_imm16 (-ins->inst_imm)) {
3310 s390_lghi (code, s390_r0, ins->inst_imm);
3311 s390_slbgr (code, ins->dreg, s390_r0);
3313 S390_SET (code, s390_r0, ins->inst_imm);
3314 s390_slbgr(code, ins->dreg, s390_r0);
3318 case OP_SUB_OVF_CARRY: {
3320 s390_lghi (code, s390_r0, 0);
3321 s390_lgr (code, s390_r1, s390_r0);
3322 s390_slbgr (code, s390_r0, s390_r1);
3323 s390_sgr (code, ins->dreg, src2);
3324 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3325 s390_agr (code, ins->dreg, s390_r0);
3326 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3329 case OP_SUB_OVF_UN_CARRY: {
3331 s390_slbgr (code, ins->dreg, src2);
3332 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3336 if (ins->sreg1 == ins->dreg) {
3337 s390_ngr (code, ins->dreg, ins->sreg2);
3340 if (ins->sreg2 == ins->dreg) {
3341 s390_ngr (code, ins->dreg, ins->sreg1);
3344 s390_lgr (code, ins->dreg, ins->sreg1);
3345 s390_ngr (code, ins->dreg, ins->sreg2);
3351 if (ins->dreg != ins->sreg1) {
3352 s390_lgr (code, ins->dreg, ins->sreg1);
3354 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3355 s390_ngr (code, ins->dreg, s390_r0);
3359 s390_lgr (code, s390_r1, ins->sreg1);
3360 s390_dsgr (code, s390_r0, ins->sreg2);
3361 s390_lgr (code, ins->dreg, s390_r1);
3365 s390_lgr (code, s390_r1, ins->sreg1);
3366 s390_lghi (code, s390_r0, 0);
3367 s390_dlgr (code, s390_r0, ins->sreg2);
3368 s390_lgr (code, ins->dreg, s390_r1);
3372 s390_lgr (code, s390_r1, ins->sreg1);
3373 s390_dsgr (code, s390_r0, ins->sreg2);
3374 s390_lgr (code, ins->dreg, s390_r0);
3378 if (s390_is_imm16 (ins->inst_imm)) {
3379 s390_lghi (code, s390_r13, ins->inst_imm);
3381 s390_lgfi (code, s390_r13, ins->inst_imm);
3383 s390_lgr (code, s390_r0, ins->sreg1);
3384 s390_dsgr (code, s390_r0, s390_r13);
3385 s390_lgfr (code, ins->dreg, s390_r0);
3389 s390_lgr (code, s390_r1, ins->sreg1);
3390 s390_lghi (code, s390_r0, 0);
3391 s390_dlgr (code, s390_r0, ins->sreg2);
3392 s390_lgr (code, ins->dreg, s390_r0);
3396 if (ins->sreg1 == ins->dreg) {
3397 s390_ogr (code, ins->dreg, ins->sreg2);
3400 if (ins->sreg2 == ins->dreg) {
3401 s390_ogr (code, ins->dreg, ins->sreg1);
3404 s390_lgr (code, ins->dreg, ins->sreg1);
3405 s390_ogr (code, ins->dreg, ins->sreg2);
3411 if (ins->dreg != ins->sreg1) {
3412 s390_lgr (code, ins->dreg, ins->sreg1);
3414 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3415 s390_ogr (code, ins->dreg, s390_r0);
3419 if (ins->sreg1 == ins->dreg) {
3420 s390_xgr (code, ins->dreg, ins->sreg2);
3423 if (ins->sreg2 == ins->dreg) {
3424 s390_xgr (code, ins->dreg, ins->sreg1);
3427 s390_lgr (code, ins->dreg, ins->sreg1);
3428 s390_xgr (code, ins->dreg, ins->sreg2);
3434 if (ins->dreg != ins->sreg1) {
3435 s390_lgr (code, ins->dreg, ins->sreg1);
3437 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3438 s390_xgr (code, ins->dreg, s390_r0);
3443 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3448 if (ins->sreg1 != ins->dreg) {
3449 s390_lgr (code, ins->dreg, ins->sreg1);
3451 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3456 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3461 if (ins->sreg1 != ins->dreg) {
3462 s390_lgr (code, ins->dreg, ins->sreg1);
3464 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3468 case OP_LSHR_UN_IMM: {
3469 if (ins->sreg1 != ins->dreg) {
3470 s390_lgr (code, ins->dreg, ins->sreg1);
3472 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3477 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3481 if (ins->sreg1 != ins->dreg) {
3482 s390_lgr (code, ins->dreg, ins->sreg1);
3484 s390_lghi (code, s390_r0, -1);
3485 s390_xgr (code, ins->dreg, s390_r0);
3489 s390_lcgr (code, ins->dreg, ins->sreg1);
3494 s390_msgr (code, ins->dreg, src2);
3499 if (ins->dreg != ins->sreg1) {
3500 s390_lgr (code, ins->dreg, ins->sreg1);
3502 if (s390_is_imm16 (ins->inst_imm)) {
3503 s390_lghi (code, s390_r13, ins->inst_imm);
3504 } else if (s390_is_imm32 (ins->inst_imm)) {
3505 s390_lgfi (code, s390_r13, ins->inst_imm);
3507 S390_SET (code, s390_r13, ins->inst_imm);
3509 s390_msgr (code, ins->dreg, s390_r13);
3514 s390_ltgr (code, s390_r1, ins->sreg1);
3515 s390_jz (code, 0); CODEPTR(code, o[0]);
3516 s390_ltgr (code, s390_r0, ins->sreg2);
3518 s390_lghi (code, s390_r1, 0);
3519 s390_j (code, 0); CODEPTR(code, o[1]);
3520 s390_xgr (code, s390_r0, s390_r1);
3521 s390_msgr (code, s390_r1, ins->sreg2);
3522 s390_xgr (code, s390_r0, s390_r1);
3523 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3524 s390_ltgr (code, s390_r0, s390_r0);
3525 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3526 PTRSLOT (code, o[0]);
3527 PTRSLOT (code, o[1]);
3528 s390_lgr (code, ins->dreg, s390_r1);
3531 case OP_LMUL_OVF_UN: {
3532 s390_lghi (code, s390_r0, 0);
3533 s390_lgr (code, s390_r1, ins->sreg1);
3534 s390_mlgr (code, s390_r0, ins->sreg2);
3535 s390_ltgr (code, s390_r0, s390_r0);
3536 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3537 s390_lgr (code, ins->dreg, s390_r1);
3541 g_assert_not_reached ();
3543 s390_algr (code, ins->dreg, src2);
3548 s390_agr (code, ins->dreg, src2);
3552 g_assert_not_reached ();
3554 s390_alcgr (code, ins->dreg, src2);
3558 if (ins->dreg != ins->sreg1) {
3559 s390_lgfr (code, ins->dreg, ins->sreg1);
3561 if (s390_is_imm16 (ins->inst_imm)) {
3562 s390_aghi (code, ins->dreg, ins->inst_imm);
3564 s390_afi (code, ins->dreg, ins->inst_imm);
3569 if (ins->dreg != ins->sreg1) {
3570 s390_lgfr (code, ins->dreg, ins->sreg1);
3572 if (s390_is_imm16 (ins->inst_imm)) {
3573 s390_lghi (code, s390_r0, ins->inst_imm);
3574 s390_alcgr (code, ins->dreg, s390_r0);
3576 S390_SET (code, s390_r0, ins->inst_imm);
3577 s390_alcgr (code, ins->dreg, s390_r0);
3582 case OP_S390_LADD_OVF: {
3584 s390_agr (code, ins->dreg, src2);
3585 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3588 case OP_LADD_OVF_UN:
3589 case OP_S390_LADD_OVF_UN: {
3591 s390_algr (code, ins->dreg, src2);
3592 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3596 CHECK_SRCDST_NCOM_I;
3597 s390_slgr (code, ins->dreg, src2);
3601 CHECK_SRCDST_NCOM_I;
3602 s390_sgr (code, ins->dreg, src2);
3606 CHECK_SRCDST_NCOM_I;
3607 s390_slbgr (code, ins->dreg, src2);
3611 if (ins->dreg != ins->sreg1) {
3612 s390_lgfr (code, ins->dreg, ins->sreg1);
3614 if (s390_is_imm16 (-ins->inst_imm)) {
3615 s390_aghi (code, ins->dreg, -ins->inst_imm);
3617 s390_agfi (code, ins->dreg, -ins->inst_imm);
3622 S390_SET (code, s390_r0, ins->inst_imm);
3623 s390_slgfr (code, ins->dreg, s390_r0);
3627 case OP_S390_ISUB_OVF: {
3629 s390_sr (code, ins->dreg, src2);
3630 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3631 s390_lgfr (code, ins->dreg, ins->dreg);
3634 case OP_ISUB_OVF_UN:
3635 case OP_S390_ISUB_OVF_UN: {
3637 s390_slr (code, ins->dreg, src2);
3638 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3639 s390_llgfr(code, ins->dreg, ins->dreg);
3643 case OP_S390_LSUB_OVF: {
3645 s390_sgr (code, ins->dreg, src2);
3646 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3649 case OP_LSUB_OVF_UN:
3650 case OP_S390_LSUB_OVF_UN: {
3652 s390_slgr (code, ins->dreg, src2);
3653 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3657 CHECK_SRCDST_NCOM_I;
3658 s390_ngr (code, ins->dreg, src2);
3662 if (ins->dreg != ins->sreg1) {
3663 s390_lgfr (code, ins->dreg, ins->sreg1);
3665 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3666 s390_ngr (code, ins->dreg, s390_r0);
3670 s390_lgfr (code, s390_r0, ins->sreg1);
3671 s390_srda (code, s390_r0, 0, 32);
3672 s390_dr (code, s390_r0, ins->sreg2);
3673 s390_lgfr (code, ins->dreg, s390_r1);
3677 s390_lgfr (code, s390_r0, ins->sreg1);
3678 s390_srdl (code, s390_r0, 0, 32);
3679 s390_dlr (code, s390_r0, ins->sreg2);
3680 s390_lgfr (code, ins->dreg, s390_r1);
3684 if (s390_is_imm16 (ins->inst_imm)) {
3685 s390_lghi (code, s390_r13, ins->inst_imm);
3687 s390_lgfi (code, s390_r13, ins->inst_imm);
3689 s390_lgfr (code, s390_r0, ins->sreg1);
3690 s390_srda (code, s390_r0, 0, 32);
3691 s390_dr (code, s390_r0, ins->sreg2);
3692 s390_lgfr (code, ins->dreg, s390_r1);
3696 s390_lgfr (code, s390_r0, ins->sreg1);
3697 s390_srda (code, s390_r0, 0, 32);
3698 s390_dr (code, s390_r0, ins->sreg2);
3699 s390_lgfr (code, ins->dreg, s390_r0);
3702 s390_lgfr (code, s390_r0, ins->sreg1);
3703 s390_srdl (code, s390_r0, 0, 32);
3704 s390_dlr (code, s390_r0, ins->sreg2);
3705 s390_lgfr (code, ins->dreg, s390_r0);
3709 if (s390_is_imm16 (ins->inst_imm)) {
3710 s390_lghi (code, s390_r13, ins->inst_imm);
3712 s390_lgfi (code, s390_r13, ins->inst_imm);
3714 s390_lgfr (code, s390_r0, ins->sreg1);
3715 s390_srda (code, s390_r0, 0, 32);
3716 s390_dr (code, s390_r0, ins->sreg2);
3717 s390_lgfr (code, ins->dreg, s390_r0);
3722 s390_ogr (code, ins->dreg, src2);
3726 if (ins->dreg != ins->sreg1) {
3727 s390_lgfr (code, ins->dreg, ins->sreg1);
3729 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3730 s390_ogr (code, ins->dreg, s390_r0);
3735 s390_xgr (code, ins->dreg, src2);
3739 if (ins->dreg != ins->sreg1) {
3740 s390_lgfr (code, ins->dreg, ins->sreg1);
3742 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3743 s390_xgr (code, ins->dreg, s390_r0);
3748 s390_sll (code, ins->dreg, src2, 0);
3752 if (ins->sreg1 != ins->dreg) {
3753 s390_lgfr (code, ins->dreg, ins->sreg1);
3755 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3760 s390_sra (code, ins->dreg, src2, 0);
3764 if (ins->sreg1 != ins->dreg) {
3765 s390_lgfr (code, ins->dreg, ins->sreg1);
3767 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3770 case OP_ISHR_UN_IMM: {
3771 if (ins->sreg1 != ins->dreg) {
3772 s390_lgfr (code, ins->dreg, ins->sreg1);
3774 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3779 s390_srl (code, ins->dreg, src2, 0);
3783 if (ins->sreg1 != ins->dreg) {
3784 s390_lgfr (code, ins->dreg, ins->sreg1);
3786 s390_lghi (code, s390_r0, -1);
3787 s390_xgr (code, ins->dreg, s390_r0);
3791 s390_lcgr (code, ins->dreg, ins->sreg1);
3796 s390_msr (code, ins->dreg, src2);
3800 if (ins->dreg != ins->sreg1) {
3801 s390_lgfr (code, ins->dreg, ins->sreg1);
3803 if (s390_is_imm16 (ins->inst_imm)) {
3804 s390_lghi (code, s390_r0, ins->inst_imm);
3806 s390_lgfi (code, s390_r0, ins->inst_imm);
3808 s390_msr (code, ins->dreg, s390_r0);
3813 s390_ltr (code, s390_r1, ins->sreg1);
3814 s390_jz (code, 0); CODEPTR(code, o[0]);
3815 s390_ltr (code, s390_r0, ins->sreg2);
3817 s390_lhi (code, s390_r1, 0);
3818 s390_j (code, 0); CODEPTR(code, o[1]);
3819 s390_xr (code, s390_r0, s390_r1);
3820 s390_msr (code, s390_r1, ins->sreg2);
3821 s390_xr (code, s390_r0, s390_r1);
3822 s390_srl (code, s390_r0, 0, 31);
3823 s390_ltr (code, s390_r0, s390_r0);
3824 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3825 PTRSLOT (code, o[0]);
3826 PTRSLOT (code, o[1]);
3827 s390_lgfr (code, ins->dreg, s390_r1);
3830 case OP_IMUL_OVF_UN: {
3831 s390_lhi (code, s390_r0, 0);
3832 s390_lr (code, s390_r1, ins->sreg1);
3833 s390_mlr (code, s390_r0, ins->sreg2);
3834 s390_ltr (code, s390_r0, s390_r0);
3835 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3836 s390_lgfr (code, ins->dreg, s390_r1);
3841 S390_SET (code, ins->dreg, ins->inst_c0);
3845 mono_add_patch_info (cfg, code - cfg->native_code,
3846 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3847 S390_LOAD_TEMPLATE (code, ins->dreg);
3850 case OP_JUMP_TABLE: {
3851 mono_add_patch_info (cfg, code - cfg->native_code,
3852 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3853 S390_LOAD_TEMPLATE (code, ins->dreg);
3857 if (ins->dreg != ins->sreg1) {
3858 s390_lgr (code, ins->dreg, ins->sreg1);
3862 case OP_LCONV_TO_I8:
3864 s390_lgfr (code, ins->dreg, ins->sreg1);
3866 case OP_LCONV_TO_I4:
3867 s390_lgfr (code, ins->dreg, ins->sreg1);
3870 case OP_LCONV_TO_U8:
3871 case OP_LCONV_TO_U4:
3873 s390_llgfr (code, ins->dreg, ins->sreg1);
3875 case OP_LCONV_TO_OVF_U4:
3876 S390_SET (code, s390_r0, 4294967295);
3877 s390_clgr (code, ins->sreg1, s390_r0);
3878 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3879 s390_ltgr (code, ins->sreg1, ins->sreg1);
3880 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3881 s390_llgfr(code, ins->dreg, ins->sreg1);
3883 case OP_LCONV_TO_OVF_I4_UN:
3884 S390_SET (code, s390_r0, 2147483647);
3885 s390_cgr (code, ins->sreg1, s390_r0);
3886 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3887 s390_ltgr (code, ins->sreg1, ins->sreg1);
3888 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3889 s390_lgfr (code, ins->dreg, ins->sreg1);
3892 if (ins->dreg != ins->sreg1) {
3893 s390_ldr (code, ins->dreg, ins->sreg1);
3896 case OP_MOVE_F_TO_I8:
3897 s390_lgdr (code, ins->dreg, ins->sreg1);
3899 case OP_MOVE_I8_TO_F:
3900 s390_ldgr (code, ins->dreg, ins->sreg1);
3902 case OP_MOVE_F_TO_I4:
3903 s390_ledbr (code, s390_f0, ins->sreg1);
3904 s390_lgdr (code, ins->dreg, s390_f0);
3905 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3907 case OP_MOVE_I4_TO_F:
3908 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3909 s390_ldgr (code, ins->dreg, s390_r0);
3910 s390_ldebr (code, ins->dreg, ins->dreg);
3912 case OP_FCONV_TO_R4:
3913 s390_ledbr (code, ins->dreg, ins->sreg1);
3914 s390_ldebr (code, ins->dreg, ins->dreg);
3916 case OP_S390_SETF4RET:
3917 s390_ledbr (code, ins->dreg, ins->sreg1);
3920 if (s390_is_imm16 (ins->inst_offset)) {
3921 s390_lghi (code, s390_r13, ins->inst_offset);
3922 } else if (s390_is_imm32 (ins->inst_offset)) {
3923 s390_lgfi (code, s390_r13, ins->inst_offset);
3925 S390_SET (code, s390_r13, ins->inst_offset);
3927 s390_ear (code, s390_r1, 0);
3928 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3929 s390_ear (code, s390_r1, 1);
3930 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3934 if (s390_is_imm16 (ins->inst_offset)) {
3935 s390_lghi (code, s390_r13, ins->inst_offset);
3936 } else if (s390_is_imm32 (ins->inst_offset)) {
3937 s390_lgfi (code, s390_r13, ins->inst_offset);
3939 S390_SET (code, s390_r13, ins->inst_offset);
3941 s390_ear (code, s390_r1, 0);
3942 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3943 s390_ear (code, s390_r1, 1);
3944 s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
3948 if (cfg->method->save_lmf)
3949 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3951 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3952 code = emit_load_volatile_arguments (code, cfg);
3955 code = backUpStackPtr(cfg, code);
3956 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3957 mono_add_patch_info (cfg, code - cfg->native_code,
3958 MONO_PATCH_INFO_METHOD_JUMP,
3960 s390_jcl (code, S390_CC_UN, 0);
3963 case OP_CHECK_THIS: {
3964 /* ensure ins->sreg1 is not NULL */
3965 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3966 s390_ltgr (code, s390_r0, s390_r0);
3967 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3971 int offset = cfg->sig_cookie + cfg->stack_usage;
3973 if (s390_is_imm16 (offset)) {
3974 s390_lghi (code, s390_r0, offset);
3975 } else if (s390_is_imm32 (offset)) {
3976 s390_lgfi (code, s390_r0, offset);
3978 S390_SET (code, s390_r0, offset);
3980 s390_agr (code, s390_r0, cfg->frame_reg);
3981 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3985 call = (MonoCallInst*)ins;
3986 if (ins->flags & MONO_INST_HAS_METHOD)
3987 mono_add_patch_info (cfg, code-cfg->native_code,
3988 MONO_PATCH_INFO_METHOD,
3991 mono_add_patch_info (cfg, code-cfg->native_code,
3992 MONO_PATCH_INFO_ABS,
3994 S390_CALL_TEMPLATE (code, s390_r14);
3995 if (call->signature->ret->type == MONO_TYPE_R4)
3996 s390_ldebr (code, s390_f0, s390_f0);
4004 call = (MonoCallInst*)ins;
4005 if (ins->flags & MONO_INST_HAS_METHOD)
4006 mono_add_patch_info (cfg, code-cfg->native_code,
4007 MONO_PATCH_INFO_METHOD,
4010 mono_add_patch_info (cfg, code-cfg->native_code,
4011 MONO_PATCH_INFO_ABS,
4013 S390_CALL_TEMPLATE (code, s390_r14);
4016 case OP_FCALL_REG: {
4017 call = (MonoCallInst*)ins;
4018 s390_lgr (code, s390_r1, ins->sreg1);
4019 s390_basr (code, s390_r14, s390_r1);
4020 if (call->signature->ret->type == MONO_TYPE_R4)
4021 s390_ldebr (code, s390_f0, s390_f0);
4027 case OP_VOIDCALL_REG:
4029 s390_lgr (code, s390_r1, ins->sreg1);
4030 s390_basr (code, s390_r14, s390_r1);
4033 case OP_FCALL_MEMBASE: {
4034 call = (MonoCallInst*)ins;
4035 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4036 s390_basr (code, s390_r14, s390_r1);
4037 if (call->signature->ret->type == MONO_TYPE_R4)
4038 s390_ldebr (code, s390_f0, s390_f0);
4041 case OP_LCALL_MEMBASE:
4042 case OP_VCALL_MEMBASE:
4043 case OP_VCALL2_MEMBASE:
4044 case OP_VOIDCALL_MEMBASE:
4045 case OP_CALL_MEMBASE: {
4046 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4047 s390_basr (code, s390_r14, s390_r1);
4054 if (cfg->param_area == 0)
4055 alloca_skip = S390_MINIMAL_STACK_SIZE;
4057 alloca_skip = cfg->param_area;
4059 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4060 s390_lgr (code, s390_r1, ins->sreg1);
4061 if (ins->flags & MONO_INST_INIT)
4062 s390_lgr (code, s390_r0, ins->sreg1);
4063 s390_aghi (code, s390_r1, 14);
4064 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4065 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4066 if (cfg->method->save_lmf) {
4067 /*----------------------------------*/
4068 /* we have to adjust lmf ebp value */
4069 /*----------------------------------*/
4070 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4072 s390_lgr (code, s390_r13, cfg->frame_reg);
4073 if (s390_is_imm16(lmfOffset)) {
4074 s390_aghi (code, s390_r13, lmfOffset);
4075 } else if (s390_is_imm32(lmfOffset)) {
4076 s390_agfi (code, s390_r13, lmfOffset);
4078 S390_SET (code, s390_r13, lmfOffset);
4080 s390_lgr (code, s390_r14, STK_BASE);
4081 s390_sgr (code, s390_r14, s390_r1);
4082 s390_stg (code, s390_r14, 0, s390_r13,
4083 G_STRUCT_OFFSET(MonoLMF, ebp));
4085 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4086 s390_sgr (code, STK_BASE, s390_r1);
4087 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4088 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4089 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4090 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4091 if (ins->flags & MONO_INST_INIT) {
4092 s390_lgr (code, s390_r1, s390_r0);
4093 s390_lgr (code, s390_r0, ins->dreg);
4094 s390_lgr (code, s390_r14, s390_r12);
4095 s390_lghi (code, s390_r13, 0);
4096 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4098 s390_lgr (code, s390_r12, s390_r14);
4103 s390_lgr (code, s390_r2, ins->sreg1);
4104 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4105 (gpointer) "mono_arch_throw_exception");
4106 S390_CALL_TEMPLATE(code, s390_r14);
4110 s390_lgr (code, s390_r2, ins->sreg1);
4111 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4112 (gpointer) "mono_arch_rethrow_exception");
4113 S390_CALL_TEMPLATE(code, s390_r14);
4116 case OP_START_HANDLER: {
4117 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4119 S390_LONG (code, stg, stg, s390_r14, 0,
4120 spvar->inst_basereg,
4121 spvar->inst_offset);
4124 case OP_ENDFILTER: {
4125 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4127 if (ins->sreg1 != s390_r2)
4128 s390_lgr(code, s390_r2, ins->sreg1);
4129 S390_LONG (code, lg, lg, s390_r14, 0,
4130 spvar->inst_basereg,
4131 spvar->inst_offset);
4132 s390_br (code, s390_r14);
4135 case OP_ENDFINALLY: {
4136 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4138 S390_LONG (code, lg, lg, s390_r14, 0,
4139 spvar->inst_basereg,
4140 spvar->inst_offset);
4141 s390_br (code, s390_r14);
4144 case OP_CALL_HANDLER: {
4145 mono_add_patch_info (cfg, code-cfg->native_code,
4146 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4147 s390_brasl (code, s390_r14, 0);
4148 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4152 ins->inst_c0 = code - cfg->native_code;
4155 case OP_RELAXED_NOP:
4158 case OP_DUMMY_STORE:
4159 case OP_NOT_REACHED:
4163 case OP_IL_SEQ_POINT:
4164 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4166 case OP_SEQ_POINT: {
4169 if (cfg->compile_aot)
4173 * Read from the single stepping trigger page. This will cause a
4174 * SIGSEGV when single stepping is enabled.
4175 * We do this _before_ the breakpoint, so single stepping after
4176 * a breakpoint is hit will step to the next IL offset.
4178 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4179 breakpointCode.pTrigger = ss_trigger_page;
4180 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4181 code += BREAKPOINT_SIZE;
4184 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4187 * A placeholder for a possible breakpoint inserted by
4188 * mono_arch_set_breakpoint ().
4190 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4194 * Add an additional nop so skipping the bp doesn't cause the ip to point
4195 * to another IL offset.
4201 case OP_GENERIC_CLASS_INIT: {
4202 static int byte_offset = -1;
4203 static guint8 bitmask;
4206 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4208 if (byte_offset < 0)
4209 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4211 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4212 s390_jo (code, 0); CODEPTR(code, jump);
4214 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4215 "mono_generic_class_init");
4216 S390_CALL_TEMPLATE(code, s390_r14);
4218 PTRSLOT (code, jump);
4220 ins->flags |= MONO_INST_GC_CALLSITE;
4221 ins->backend.pc_offset = code - cfg->native_code;
4225 EMIT_UNCOND_BRANCH(ins);
4228 s390_br (code, ins->sreg1);
4234 s390_lghi(code, ins->dreg, 1);
4236 s390_lghi(code, ins->dreg, 0);
4242 s390_lghi(code, ins->dreg, 1);
4244 s390_lghi(code, ins->dreg, 0);
4250 s390_lghi(code, ins->dreg, 1);
4252 s390_lghi(code, ins->dreg, 0);
4258 s390_lghi(code, ins->dreg, 1);
4260 s390_lghi(code, ins->dreg, 0);
4266 s390_lghi(code, ins->dreg, 1);
4268 s390_lghi(code, ins->dreg, 0);
4271 case OP_COND_EXC_EQ:
4272 case OP_COND_EXC_IEQ:
4273 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4275 case OP_COND_EXC_NE_UN:
4276 case OP_COND_EXC_INE_UN:
4277 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4279 case OP_COND_EXC_LT:
4280 case OP_COND_EXC_ILT:
4281 case OP_COND_EXC_LT_UN:
4282 case OP_COND_EXC_ILT_UN:
4283 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4285 case OP_COND_EXC_GT:
4286 case OP_COND_EXC_IGT:
4287 case OP_COND_EXC_GT_UN:
4288 case OP_COND_EXC_IGT_UN:
4289 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4291 case OP_COND_EXC_GE:
4292 case OP_COND_EXC_IGE:
4293 case OP_COND_EXC_GE_UN:
4294 case OP_COND_EXC_IGE_UN:
4295 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4297 case OP_COND_EXC_LE:
4298 case OP_COND_EXC_ILE:
4299 case OP_COND_EXC_LE_UN:
4300 case OP_COND_EXC_ILE_UN:
4301 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4303 case OP_COND_EXC_OV:
4304 case OP_COND_EXC_IOV:
4305 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4307 case OP_COND_EXC_NO:
4308 case OP_COND_EXC_INO:
4309 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4312 case OP_COND_EXC_IC:
4313 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4315 case OP_COND_EXC_NC:
4316 case OP_COND_EXC_INC:
4317 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4321 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4325 EMIT_COND_BRANCH (ins, S390_CC_NE);
4331 EMIT_COND_BRANCH (ins, S390_CC_LT);
4337 EMIT_COND_BRANCH (ins, S390_CC_GT);
4343 EMIT_COND_BRANCH (ins, S390_CC_GE);
4349 EMIT_COND_BRANCH (ins, S390_CC_LE);
4352 /* floating point opcodes */
4354 if (*((double *) ins->inst_p0) == 0) {
4355 s390_lzdr (code, ins->dreg);
4357 S390_SET (code, s390_r13, ins->inst_p0);
4358 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4363 if (*((float *) ins->inst_p0) == 0) {
4364 s390_lzdr (code, ins->dreg);
4366 S390_SET (code, s390_r13, ins->inst_p0);
4367 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4371 case OP_STORER8_MEMBASE_REG: {
4372 S390_LONG (code, stdy, std, ins->sreg1, 0,
4373 ins->inst_destbasereg, ins->inst_offset);
4376 case OP_LOADR8_MEMBASE: {
4377 S390_LONG (code, ldy, ld, ins->dreg, 0,
4378 ins->inst_basereg, ins->inst_offset);
4381 case OP_STORER4_MEMBASE_REG: {
4382 s390_ledbr (code, s390_f15, ins->sreg1);
4383 S390_LONG (code, stey, ste, s390_f15, 0,
4384 ins->inst_destbasereg, ins->inst_offset);
4387 case OP_LOADR4_MEMBASE: {
4388 S390_LONG (code, ley, le, s390_f15, 0,
4389 ins->inst_basereg, ins->inst_offset);
4390 s390_ldebr (code, ins->dreg, s390_f15);
4393 case OP_ICONV_TO_R_UN: {
4394 if (mono_hwcap_s390x_has_fpe) {
4395 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4397 s390_llgfr (code, s390_r0, ins->sreg1);
4398 s390_cdgbr (code, ins->dreg, s390_r0);
4402 case OP_LCONV_TO_R_UN: {
4403 if (mono_hwcap_s390x_has_fpe) {
4404 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4407 s390_cxgbr (code, s390_f12, ins->sreg1);
4408 s390_ltgr (code, ins->sreg1, ins->sreg1);
4409 s390_jnl (code, 0); CODEPTR(code, jump);
4410 S390_SET (code, s390_r13, 0x403f000000000000llu);
4411 s390_lgdr (code, s390_f13, s390_r13);
4412 s390_lzdr (code, s390_f15);
4413 s390_axbr (code, s390_f12, s390_f13);
4414 PTRSLOT(code, jump);
4415 s390_ldxbr (code, s390_f13, s390_f12);
4416 s390_ldr (code, ins->dreg, s390_f13);
4420 case OP_LCONV_TO_R4:
4421 case OP_ICONV_TO_R4: {
4422 s390_cegbr (code, ins->dreg, ins->sreg1);
4423 s390_ldebr (code, ins->dreg, ins->dreg);
4426 case OP_LCONV_TO_R8:
4427 case OP_ICONV_TO_R8: {
4428 s390_cdgbr (code, ins->dreg, ins->sreg1);
4431 case OP_FCONV_TO_I1:
4432 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4433 s390_ltgr (code, ins->dreg, ins->dreg);
4435 s390_oill (code, ins->dreg, 0x80);
4436 s390_lghi (code, s390_r0, 0xff);
4437 s390_ngr (code, ins->dreg, s390_r0);
4439 case OP_FCONV_TO_U1:
4440 if (mono_hwcap_s390x_has_fpe) {
4441 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4442 s390_lghi (code, s390_r0, 0xff);
4443 s390_ngr (code, ins->dreg, s390_r0);
4445 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4448 case OP_FCONV_TO_I2:
4449 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4450 s390_ltgr (code, ins->dreg, ins->dreg);
4452 s390_oill (code, ins->dreg, 0x8000);
4453 s390_llill (code, s390_r0, 0xffff);
4454 s390_ngr (code, ins->dreg, s390_r0);
4456 case OP_FCONV_TO_U2:
4457 if (mono_hwcap_s390x_has_fpe) {
4458 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4459 s390_llill (code, s390_r0, 0xffff);
4460 s390_ngr (code, ins->dreg, s390_r0);
4462 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4465 case OP_FCONV_TO_I4:
4467 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4469 case OP_FCONV_TO_U4:
4471 if (mono_hwcap_s390x_has_fpe) {
4472 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4474 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4477 case OP_FCONV_TO_I8:
4478 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4480 case OP_FCONV_TO_U8:
4481 if (mono_hwcap_s390x_has_fpe) {
4482 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4484 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4487 case OP_LCONV_TO_OVF_I: {
4488 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4490 s390_ltgr (code, ins->sreg2, ins->sreg2);
4491 s390_jnl (code, 0); CODEPTR(code, o[0]);
4492 s390_ltgr (code, ins->sreg1, ins->sreg1);
4493 s390_jnl (code, 0); CODEPTR(code, o[1]);
4494 s390_lhi (code, s390_r13, -1);
4495 s390_cgr (code, ins->sreg1, s390_r13);
4496 s390_jnz (code, 0); CODEPTR(code, o[2]);
4497 if (ins->dreg != ins->sreg2)
4498 s390_lgr (code, ins->dreg, ins->sreg2);
4499 s390_j (code, 0); CODEPTR(code, o[3]);
4500 PTRSLOT(code, o[0]);
4501 s390_jz (code, 0); CODEPTR(code, o[4]);
4502 PTRSLOT(code, o[1]);
4503 PTRSLOT(code, o[2]);
4504 mono_add_patch_info (cfg, code - cfg->native_code,
4505 MONO_PATCH_INFO_EXC, "OverflowException");
4506 s390_brasl (code, s390_r14, 0);
4507 PTRSLOT(code, o[3]);
4508 PTRSLOT(code, o[4]);
4512 s390_lpdbr (code, ins->dreg, ins->sreg1);
4516 s390_sqdbr (code, ins->dreg, ins->sreg1);
4521 s390_adbr (code, ins->dreg, src2);
4525 CHECK_SRCDST_NCOM_F;
4526 s390_sdbr (code, ins->dreg, src2);
4531 s390_mdbr (code, ins->dreg, src2);
4535 CHECK_SRCDST_NCOM_F;
4536 s390_ddbr (code, ins->dreg, src2);
4540 s390_lcdbr (code, ins->dreg, ins->sreg1);
4544 CHECK_SRCDST_NCOM_F;
4545 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4549 s390_cdbr (code, ins->sreg1, ins->sreg2);
4553 s390_cdbr (code, ins->sreg1, ins->sreg2);
4554 s390_lghi (code, ins->dreg, 1);
4556 s390_lghi (code, ins->dreg, 0);
4560 s390_cdbr (code, ins->sreg1, ins->sreg2);
4561 s390_lghi (code, ins->dreg, 1);
4563 s390_lghi (code, ins->dreg, 0);
4567 s390_cdbr (code, ins->sreg1, ins->sreg2);
4568 s390_lghi (code, ins->dreg, 1);
4570 s390_lghi (code, ins->dreg, 0);
4574 s390_cdbr (code, ins->sreg1, ins->sreg2);
4575 s390_lghi (code, ins->dreg, 1);
4577 s390_lghi (code, ins->dreg, 0);
4581 s390_cdbr (code, ins->sreg1, ins->sreg2);
4582 s390_lghi (code, ins->dreg, 1);
4584 s390_lghi (code, ins->dreg, 0);
4589 s390_jo (code, 0); CODEPTR(code, o);
4590 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4595 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4599 s390_jo (code, 0); CODEPTR(code, o);
4600 EMIT_COND_BRANCH (ins, S390_CC_LT);
4605 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4609 s390_jo (code, 0); CODEPTR(code, o);
4610 EMIT_COND_BRANCH (ins, S390_CC_GT);
4615 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4619 s390_jo (code, 0); CODEPTR(code, o);
4620 EMIT_COND_BRANCH (ins, S390_CC_GE);
4625 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4629 s390_jo (code, 0); CODEPTR(code, o);
4630 EMIT_COND_BRANCH (ins, S390_CC_LE);
4635 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4639 s390_lhi (code, s390_r13, 0x7f);
4640 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4641 s390_jz (code, 0); CODEPTR(code, o);
4642 mono_add_patch_info (cfg, code - cfg->native_code,
4643 MONO_PATCH_INFO_EXC, "OverflowException");
4644 s390_brasl (code, s390_r14,0);
4648 case OP_S390_MOVE: {
4649 if (ins->backend.size > 0) {
4650 if (ins->backend.size <= 256) {
4651 s390_mvc (code, ins->backend.size, ins->dreg,
4652 ins->inst_offset, ins->sreg1, ins->inst_imm);
4654 s390_lgr (code, s390_r0, ins->dreg);
4655 if (ins->inst_offset > 0) {
4656 if (s390_is_imm16 (ins->inst_offset)) {
4657 s390_aghi (code, s390_r0, ins->inst_offset);
4658 } else if (s390_is_imm32 (ins->inst_offset)) {
4659 s390_agfi (code, s390_r0, ins->inst_offset);
4661 S390_SET (code, s390_r13, ins->inst_offset);
4662 s390_agr (code, s390_r0, s390_r13);
4665 s390_lgr (code, s390_r12, ins->sreg1);
4666 if (ins->inst_imm > 0) {
4667 if (s390_is_imm16 (ins->inst_imm)) {
4668 s390_aghi (code, s390_r12, ins->inst_imm);
4669 } else if (s390_is_imm32 (ins->inst_imm)) {
4670 s390_agfi (code, s390_r12, ins->inst_imm);
4672 S390_SET (code, s390_r13, ins->inst_imm);
4673 s390_agr (code, s390_r12, s390_r13);
4676 if (s390_is_imm16 (ins->backend.size)) {
4677 s390_lghi (code, s390_r1, ins->backend.size);
4678 } else if (s390_is_imm32 (ins->inst_offset)) {
4679 s390_agfi (code, s390_r1, ins->backend.size);
4681 S390_SET (code, s390_r13, ins->backend.size);
4682 s390_agr (code, s390_r1, s390_r13);
4684 s390_lgr (code, s390_r13, s390_r1);
4685 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4691 case OP_ATOMIC_ADD_I8: {
4692 s390_lgr (code, s390_r1, ins->sreg2);
4693 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4694 s390_agr (code, s390_r1, s390_r0);
4695 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4696 s390_jnz (code, -10);
4697 s390_lgr (code, ins->dreg, s390_r1);
4700 case OP_ATOMIC_EXCHANGE_I8: {
4701 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4702 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4703 s390_jnz (code, -6);
4704 s390_lgr (code, ins->dreg, s390_r0);
4707 case OP_ATOMIC_ADD_I4: {
4708 s390_lgfr(code, s390_r1, ins->sreg2);
4709 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4710 s390_agr (code, s390_r1, s390_r0);
4711 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4712 s390_jnz (code, -9);
4713 s390_lgfr(code, ins->dreg, s390_r1);
4716 case OP_ATOMIC_EXCHANGE_I4: {
4717 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4718 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4719 s390_jnz (code, -4);
4720 s390_lgfr(code, ins->dreg, s390_r0);
4723 case OP_S390_BKCHAIN: {
4724 s390_lgr (code, ins->dreg, ins->sreg1);
4725 if (s390_is_imm16 (cfg->stack_offset)) {
4726 s390_aghi (code, ins->dreg, cfg->stack_offset);
4727 } else if (s390_is_imm32 (cfg->stack_offset)) {
4728 s390_agfi (code, ins->dreg, cfg->stack_offset);
4730 S390_SET (code, s390_r13, cfg->stack_offset);
4731 s390_agr (code, ins->dreg, s390_r13);
4735 case OP_MEMORY_BARRIER:
4738 case OP_GC_SAFE_POINT: {
4741 g_assert (mono_threads_is_coop_enabled ());
4743 s390_chi (code, ins->sreg1, 1);
4744 s390_je (code, 0); CODEPTR(code, br);
4745 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4746 mono_threads_state_poll);
4747 S390_CALL_TEMPLATE (code, s390_r14);
4751 case OP_GC_LIVENESS_DEF:
4752 case OP_GC_LIVENESS_USE:
4753 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4754 ins->backend.pc_offset = code - cfg->native_code;
4756 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4757 ins->backend.pc_offset = code - cfg->native_code;
4758 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4760 #ifdef MONO_ARCH_SIMD_INTRINSICS
4762 s390x_addps (code, ins->sreg1, ins->sreg2);
4765 s390x_divps (code, ins->sreg1, ins->sreg2);
4768 s390x_mulps (code, ins->sreg1, ins->sreg2);
4771 s390x_subps (code, ins->sreg1, ins->sreg2);
4774 s390x_maxps (code, ins->sreg1, ins->sreg2);
4777 s390x_minps (code, ins->sreg1, ins->sreg2);
4780 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4781 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4784 s390x_andps (code, ins->sreg1, ins->sreg2);
4787 s390x_andnps (code, ins->sreg1, ins->sreg2);
4790 s390x_orps (code, ins->sreg1, ins->sreg2);
4793 s390x_xorps (code, ins->sreg1, ins->sreg2);
4796 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4799 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4802 s390x_rcpps (code, ins->dreg, ins->sreg1);
4805 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4808 s390x_haddps (code, ins->sreg1, ins->sreg2);
4811 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4814 s390x_movshdup (code, ins->dreg, ins->sreg1);
4817 s390x_movsldup (code, ins->dreg, ins->sreg1);
4820 case OP_PSHUFLEW_HIGH:
4821 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4822 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4824 case OP_PSHUFLEW_LOW:
4825 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4826 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4829 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4830 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4833 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4834 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4837 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4838 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4842 s390x_addpd (code, ins->sreg1, ins->sreg2);
4845 s390x_divpd (code, ins->sreg1, ins->sreg2);
4848 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4851 s390x_subpd (code, ins->sreg1, ins->sreg2);
4854 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4857 s390x_minpd (code, ins->sreg1, ins->sreg2);
4860 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4861 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4864 s390x_andpd (code, ins->sreg1, ins->sreg2);
4867 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4870 s390x_orpd (code, ins->sreg1, ins->sreg2);
4873 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4876 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4879 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4882 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4885 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4888 s390x_movddup (code, ins->dreg, ins->sreg1);
4891 case OP_EXTRACT_MASK:
4892 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4896 s390x_pand (code, ins->sreg1, ins->sreg2);
4899 s390x_por (code, ins->sreg1, ins->sreg2);
4902 s390x_pxor (code, ins->sreg1, ins->sreg2);
4906 s390x_paddb (code, ins->sreg1, ins->sreg2);
4909 s390x_paddw (code, ins->sreg1, ins->sreg2);
4912 s390x_paddd (code, ins->sreg1, ins->sreg2);
4915 s390x_paddq (code, ins->sreg1, ins->sreg2);
4919 s390x_psubb (code, ins->sreg1, ins->sreg2);
4922 s390x_psubw (code, ins->sreg1, ins->sreg2);
4925 s390x_psubd (code, ins->sreg1, ins->sreg2);
4928 s390x_psubq (code, ins->sreg1, ins->sreg2);
4932 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4935 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4938 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4942 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4945 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4948 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4952 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4955 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4959 s390x_pminub (code, ins->sreg1, ins->sreg2);
4962 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4965 s390x_pminud (code, ins->sreg1, ins->sreg2);
4969 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4972 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4975 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4979 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4982 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4985 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4988 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4992 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4995 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4998 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5001 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5004 case OP_PSUM_ABS_DIFF:
5005 s390x_psadbw (code, ins->sreg1, ins->sreg2);
5008 case OP_UNPACK_LOWB:
5009 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5011 case OP_UNPACK_LOWW:
5012 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5014 case OP_UNPACK_LOWD:
5015 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5017 case OP_UNPACK_LOWQ:
5018 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5020 case OP_UNPACK_LOWPS:
5021 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5023 case OP_UNPACK_LOWPD:
5024 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5027 case OP_UNPACK_HIGHB:
5028 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5030 case OP_UNPACK_HIGHW:
5031 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5033 case OP_UNPACK_HIGHD:
5034 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5036 case OP_UNPACK_HIGHQ:
5037 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5039 case OP_UNPACK_HIGHPS:
5040 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5042 case OP_UNPACK_HIGHPD:
5043 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5047 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5050 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5053 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5056 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5059 case OP_PADDB_SAT_UN:
5060 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5062 case OP_PSUBB_SAT_UN:
5063 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5065 case OP_PADDW_SAT_UN:
5066 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5068 case OP_PSUBW_SAT_UN:
5069 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5073 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5076 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5079 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5082 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5086 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5089 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5092 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5094 case OP_PMULW_HIGH_UN:
5095 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5098 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5102 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5105 s390x_psrlw (code, ins->dreg, ins->sreg2);
5109 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5112 s390x_psraw (code, ins->dreg, ins->sreg2);
5116 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5119 s390x_psllw (code, ins->dreg, ins->sreg2);
5123 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5126 s390x_psrld (code, ins->dreg, ins->sreg2);
5130 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5133 s390x_psrad (code, ins->dreg, ins->sreg2);
5137 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5140 s390x_pslld (code, ins->dreg, ins->sreg2);
5144 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5147 s390x_psrlq (code, ins->dreg, ins->sreg2);
5150 /*TODO: This is appart of the sse spec but not added
5152 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5155 s390x_psraq (code, ins->dreg, ins->sreg2);
5160 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5163 s390x_psllq (code, ins->dreg, ins->sreg2);
5166 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5169 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5172 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5175 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5178 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5181 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5184 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5187 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5191 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5194 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5198 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5199 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5201 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5206 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5208 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5209 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5213 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5215 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5216 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5217 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5221 amd64_movhlps (code, ins->dreg, ins->sreg1);
5223 s390x_movsd (code, ins->dreg, ins->sreg1);
5226 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5228 case OP_EXTRACTX_U2:
5229 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5231 case OP_INSERTX_U1_SLOW:
5232 /*sreg1 is the extracted ireg (scratch)
5233 /sreg2 is the to be inserted ireg (scratch)
5234 /dreg is the xreg to receive the value*/
5236 /*clear the bits from the extracted word*/
5237 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5238 /*shift the value to insert if needed*/
5239 if (ins->inst_c0 & 1)
5240 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5241 /*join them together*/
5242 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5243 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5245 case OP_INSERTX_I4_SLOW:
5246 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5247 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5248 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5250 case OP_INSERTX_I8_SLOW:
5251 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5253 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5255 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5258 case OP_INSERTX_R4_SLOW:
5259 switch (ins->inst_c0) {
5262 s390x_movss (code, ins->dreg, ins->sreg2);
5264 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5267 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5269 s390x_movss (code, ins->dreg, ins->sreg2);
5271 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5272 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5275 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5277 s390x_movss (code, ins->dreg, ins->sreg2);
5279 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5280 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5283 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5285 s390x_movss (code, ins->dreg, ins->sreg2);
5287 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5288 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5292 case OP_INSERTX_R8_SLOW:
5294 amd64_movlhps (code, ins->dreg, ins->sreg2);
5296 s390x_movsd (code, ins->dreg, ins->sreg2);
5298 case OP_STOREX_MEMBASE_REG:
5299 case OP_STOREX_MEMBASE:
5300 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5302 case OP_LOADX_MEMBASE:
5303 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5305 case OP_LOADX_ALIGNED_MEMBASE:
5306 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5308 case OP_STOREX_ALIGNED_MEMBASE_REG:
5309 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5311 case OP_STOREX_NTA_MEMBASE_REG:
5312 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5314 case OP_PREFETCH_MEMBASE:
5315 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5319 /*FIXME the peephole pass should have killed this*/
5320 if (ins->dreg != ins->sreg1)
5321 s390x_movaps (code, ins->dreg, ins->sreg1);
5324 s390x_pxor (code, ins->dreg, ins->dreg);
5326 case OP_ICONV_TO_R4_RAW:
5327 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5330 case OP_FCONV_TO_R8_X:
5331 s390x_movsd (code, ins->dreg, ins->sreg1);
5334 case OP_XCONV_R8_TO_I4:
5335 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5336 switch (ins->backend.source_opcode) {
5337 case OP_FCONV_TO_I1:
5338 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5340 case OP_FCONV_TO_U1:
5341 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5343 case OP_FCONV_TO_I2:
5344 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5346 case OP_FCONV_TO_U2:
5347 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5353 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5354 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5355 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5358 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5359 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5362 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5363 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5367 s390x_movsd (code, ins->dreg, ins->sreg1);
5369 s390x_movsd (code, ins->dreg, ins->sreg1);
5370 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5372 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5375 s390x_movsd (code, ins->dreg, ins->sreg1);
5376 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5380 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5381 g_assert_not_reached ();
5384 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5385 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5386 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5387 g_assert_not_reached ();
5390 last_offset = offset;
5393 cfg->code_len = code - cfg->native_code;
5396 /*========================= End of Function ========================*/
5398 /*------------------------------------------------------------------*/
5400 /* Name - mono_arch_register_lowlevel_calls */
5402 /* Function - Register routines to help with --trace operation. */
5404 /*------------------------------------------------------------------*/
5407 mono_arch_register_lowlevel_calls (void)
5411 /*========================= End of Function ========================*/
5413 /*------------------------------------------------------------------*/
5415 /* Name - mono_arch_patch_code */
5417 /* Function - Process the patch data created during the */
5418 /* instruction build process. This resolves jumps, */
5419 /* calls, variables etc. */
5421 /*------------------------------------------------------------------*/
5424 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5425 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5428 MonoJumpInfo *patch_info;
5432 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5433 unsigned char *ip = patch_info->ip.i + code;
5434 gconstpointer target = NULL;
5436 target = mono_resolve_patch_target (method, domain, code,
5437 patch_info, run_cctors, error);
5438 return_if_nok (error);
5440 switch (patch_info->type) {
5441 case MONO_PATCH_INFO_IP:
5442 case MONO_PATCH_INFO_LDSTR:
5443 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5444 case MONO_PATCH_INFO_LDTOKEN:
5445 case MONO_PATCH_INFO_EXC:
5446 s390_patch_addr (ip, (guint64) target);
5448 case MONO_PATCH_INFO_METHOD:
5449 case MONO_PATCH_INFO_INTERNAL_METHOD:
5450 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5451 case MONO_PATCH_INFO_RGCTX_FETCH:
5452 case MONO_PATCH_INFO_ABS: {
5453 S390_EMIT_CALL (ip, target);
5456 case MONO_PATCH_INFO_SWITCH:
5457 /*----------------------------------*/
5458 /* ip points at the basr r13,0/j +4 */
5459 /* instruction the vtable value */
5460 /* follows this (i.e. ip+6) */
5461 /*----------------------------------*/
5462 S390_EMIT_LOAD (ip, target);
5464 case MONO_PATCH_INFO_METHODCONST:
5465 case MONO_PATCH_INFO_CLASS:
5466 case MONO_PATCH_INFO_IMAGE:
5467 case MONO_PATCH_INFO_FIELD:
5468 case MONO_PATCH_INFO_IID:
5469 case MONO_PATCH_INFO_EXC_NAME:
5470 target = S390_RELATIVE(target, ip);
5471 s390_patch_rel (ip, (guint64) target);
5473 case MONO_PATCH_INFO_R4:
5474 case MONO_PATCH_INFO_R8:
5475 case MONO_PATCH_INFO_METHOD_REL:
5476 g_assert_not_reached ();
5479 target = S390_RELATIVE(target, ip);
5481 s390_patch_rel (ip, (guint64) target);
5486 /*========================= End of Function ========================*/
5488 /*------------------------------------------------------------------*/
5490 /* Name - emit_load_volatile_arguments */
5492 /* Function - Emit the instructions to reload parameter regist- */
5493 /* registers for use with "tail" operations. */
5495 /* The register loading operations performed here */
5496 /* are the mirror of the store operations performed */
5497 /* in mono_arch_emit_prolog and need to be kept in */
5498 /* synchronization with it. */
5500 /*------------------------------------------------------------------*/
5503 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5506 MonoMethod *method = cfg->method;
5507 MonoMethodSignature *sig = mono_method_signature(method);
5511 cinfo = get_call_info (NULL, NULL, sig);
5513 if (cinfo->struct_ret) {
5514 ArgInfo *ainfo = &cinfo->ret;
5515 inst = cfg->vret_addr;
5516 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5519 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5520 ArgInfo *ainfo = cinfo->args + i;
5521 inst = cfg->args [pos];
5523 if (inst->opcode == OP_REGVAR) {
5524 if (ainfo->regtype == RegTypeGeneral)
5525 s390_lgr (code, ainfo->reg, inst->dreg);
5526 else if (ainfo->regtype == RegTypeFP) {
5527 if (inst->dreg != ainfo->reg) {
5528 if (ainfo->size == 4) {
5529 s390_ldebr (code, ainfo->reg, inst->dreg);
5531 s390_ldr (code, ainfo->reg, inst->dreg);
5535 else if (ainfo->regtype == RegTypeBase) {
5537 g_assert_not_reached ();
5539 if (ainfo->regtype == RegTypeGeneral) {
5540 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5541 g_assert_not_reached();
5542 switch (ainfo->size) {
5544 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5547 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5553 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5556 } else if (ainfo->regtype == RegTypeBase) {
5557 } else if (ainfo->regtype == RegTypeFP) {
5558 if (ainfo->size == 8)
5559 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5560 else if (ainfo->size == 4)
5561 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5563 g_assert_not_reached ();
5564 } else if (ainfo->regtype == RegTypeStructByVal) {
5565 if (ainfo->reg != STK_BASE) {
5566 switch (ainfo->size) {
5568 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5571 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5574 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5577 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5581 } else if (ainfo->regtype == RegTypeStructByAddr) {
5582 if (ainfo->reg != STK_BASE) {
5583 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5586 g_assert_not_reached ();
5594 /*========================= End of Function ========================*/
5596 /*------------------------------------------------------------------*/
5598 /* Name - mono_arch_emit_prolog */
5600 /* Function - Create the instruction sequence for a function */
5603 /*------------------------------------------------------------------*/
5606 mono_arch_emit_prolog (MonoCompile *cfg)
5608 MonoMethod *method = cfg->method;
5610 MonoMethodSignature *sig;
5612 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5621 cfg->code_size = 512;
5623 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5625 cfg->code_size += 256;
5626 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5627 cfg->code_size += 256;
5629 if (method->save_lmf)
5630 cfg->code_size += 200;
5632 cfg->native_code = code = g_malloc (cfg->code_size);
5634 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5635 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5636 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5637 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5638 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5640 if (cfg->arch.bkchain_reg != -1)
5641 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5643 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5644 cfg->used_int_regs |= 1 << 11;
5647 alloc_size = cfg->stack_offset;
5649 cfg->stack_usage = cfa_offset = alloc_size;
5650 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5651 s390_lgr (code, s390_r11, STK_BASE);
5652 if (s390_is_imm16 (alloc_size)) {
5653 s390_aghi (code, STK_BASE, -alloc_size);
5654 } else if (s390_is_imm32 (alloc_size)) {
5655 s390_agfi (code, STK_BASE, -alloc_size);
5657 int stackSize = alloc_size;
5658 while (stackSize > INT_MAX) {
5659 s390_agfi (code, STK_BASE, -INT_MAX);
5660 stackSize -= INT_MAX;
5662 s390_agfi (code, STK_BASE, -stackSize);
5664 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5666 if (cfg->frame_reg != STK_BASE)
5667 s390_lgr (code, s390_r11, STK_BASE);
5669 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5671 /* store runtime generic context */
5672 if (cfg->rgctx_var) {
5673 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5675 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5676 cfg->rgctx_var->inst_basereg,
5677 cfg->rgctx_var->inst_offset);
5680 /* compute max_offset in order to use short forward jumps
5681 * we always do it on s390 because the immediate displacement
5682 * for jumps is too small
5685 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5687 bb->max_offset = max_offset;
5689 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5692 MONO_BB_FOR_EACH_INS (bb, ins)
5693 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5696 /* load arguments allocated to register from the stack */
5697 sig = mono_method_signature (method);
5700 cinfo = get_call_info (cfg, cfg->mempool, sig);
5702 if (cinfo->struct_ret) {
5703 ArgInfo *ainfo = &cinfo->ret;
5704 inst = cfg->vret_addr;
5705 inst->backend.size = ainfo->vtsize;
5706 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5709 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5710 ArgInfo *ainfo = cinfo->args + i;
5711 inst = cfg->args [pos];
5713 if (inst->opcode == OP_VTARG_ADDR)
5714 inst = inst->inst_left;
5716 if (inst->opcode == OP_REGVAR) {
5717 if (ainfo->regtype == RegTypeGeneral)
5718 s390_lgr (code, inst->dreg, ainfo->reg);
5719 else if (ainfo->regtype == RegTypeFP) {
5720 if (inst->dreg != ainfo->reg) {
5721 if (ainfo->size == 4) {
5722 s390_ledbr (code, inst->dreg, ainfo->reg);
5724 s390_ldr (code, inst->dreg, ainfo->reg);
5728 else if (ainfo->regtype == RegTypeBase) {
5729 s390_lgr (code, s390_r13, STK_BASE);
5730 s390_aghi (code, s390_r13, alloc_size);
5731 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5733 g_assert_not_reached ();
5735 if (cfg->verbose_level > 2)
5736 g_print ("Argument %d assigned to register %s\n",
5737 pos, mono_arch_regname (inst->dreg));
5739 if (ainfo->regtype == RegTypeGeneral) {
5740 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5741 g_assert_not_reached();
5742 switch (ainfo->size) {
5744 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5747 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5750 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5753 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5756 } else if (ainfo->regtype == RegTypeBase) {
5757 } else if (ainfo->regtype == RegTypeFP) {
5758 if (ainfo->size == 8)
5759 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5760 else if (ainfo->size == 4)
5761 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5763 g_assert_not_reached ();
5764 } else if (ainfo->regtype == RegTypeStructByVal) {
5765 int doffset = inst->inst_offset;
5767 if (ainfo->reg != STK_BASE)
5771 s390_lgr (code, s390_r13, STK_BASE);
5772 s390_aghi (code, s390_r13, alloc_size);
5775 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5776 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5781 if (ainfo->reg == STK_BASE)
5782 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5783 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5786 if (ainfo->reg == STK_BASE)
5787 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5788 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5791 if (ainfo->reg == STK_BASE)
5792 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5793 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5796 if (ainfo->reg == STK_BASE)
5797 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5798 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5801 } else if (ainfo->regtype == RegTypeStructByAddr) {
5802 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5803 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5805 g_assert_not_reached ();
5810 if (method->save_lmf) {
5811 /*---------------------------------------------------------------*/
5812 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5813 /*---------------------------------------------------------------*/
5814 lmfOffset = alloc_size - sizeof(MonoLMF);
5816 s390_lgr (code, s390_r13, cfg->frame_reg);
5817 s390_aghi (code, s390_r13, lmfOffset);
5819 /*---------------------------------------------------------------*/
5820 /* Preserve the parameter registers while we fix up the lmf */
5821 /*---------------------------------------------------------------*/
5822 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5823 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5825 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5826 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5827 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5828 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5829 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5831 /*---------------------------------------------------------------*/
5832 /* On return from this call r2 have the address of the &lmf */
5833 /*---------------------------------------------------------------*/
5834 mono_add_patch_info (cfg, code - cfg->native_code,
5835 MONO_PATCH_INFO_INTERNAL_METHOD,
5836 (gpointer)"mono_tls_get_lmf_addr");
5837 S390_CALL_TEMPLATE(code, s390_r1);
5839 /*---------------------------------------------------------------*/
5840 /* Set lmf.lmf_addr = jit_tls->lmf */
5841 /*---------------------------------------------------------------*/
5842 s390_stg (code, s390_r2, 0, s390_r13,
5843 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5844 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5846 /*---------------------------------------------------------------*/
5847 /* Get current lmf */
5848 /*---------------------------------------------------------------*/
5849 s390_lg (code, s390_r0, 0, s390_r2, 0);
5851 /*---------------------------------------------------------------*/
5852 /* Set our lmf as the current lmf */
5853 /*---------------------------------------------------------------*/
5854 s390_stg (code, s390_r13, 0, s390_r2, 0);
5856 /*---------------------------------------------------------------*/
5857 /* Have our lmf.previous_lmf point to the last lmf */
5858 /*---------------------------------------------------------------*/
5859 s390_stg (code, s390_r0, 0, s390_r13,
5860 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5861 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5863 /*---------------------------------------------------------------*/
5864 /* save method info */
5865 /*---------------------------------------------------------------*/
5866 S390_SET (code, s390_r1, method);
5867 s390_stg (code, s390_r1, 0, s390_r13,
5868 G_STRUCT_OFFSET(MonoLMF, method));
5869 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5871 /*---------------------------------------------------------------*/
5872 /* save the current IP */
5873 /*---------------------------------------------------------------*/
5874 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5875 s390_basr (code, s390_r1, 0);
5876 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5880 /*---------------------------------------------------------------*/
5881 /* Save general and floating point registers */
5882 /*---------------------------------------------------------------*/
5883 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5884 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5885 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5886 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5887 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5888 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5889 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5890 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5891 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5892 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5893 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5894 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5895 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5897 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5898 for (i = 0; i < 16; i++) {
5899 s390_std (code, i, 0, s390_r13,
5900 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5901 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5902 fpOffset += sizeof(double);
5905 /*---------------------------------------------------------------*/
5906 /* Restore the parameter registers now that we've set up the lmf */
5907 /*---------------------------------------------------------------*/
5908 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5909 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5912 if (cfg->method->save_lmf)
5913 argsClobbered = TRUE;
5916 argsClobbered = TRUE;
5917 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5920 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5921 argsClobbered = TRUE;
5924 * Optimize the common case of the first bblock making a call with the same
5925 * arguments as the method. This works because the arguments are still in their
5926 * original argument registers.
5928 if (!argsClobbered) {
5929 MonoBasicBlock *first_bb = cfg->bb_entry;
5931 int filter = FILTER_IL_SEQ_POINT;
5933 next = mono_bb_first_inst (first_bb, filter);
5934 if (!next && first_bb->next_bb) {
5935 first_bb = first_bb->next_bb;
5936 next = mono_bb_first_inst (first_bb, filter);
5939 if (first_bb->in_count > 1)
5942 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5943 ArgInfo *ainfo = cinfo->args + i;
5944 gboolean match = FALSE;
5946 inst = cfg->args [i];
5947 if (inst->opcode != OP_REGVAR) {
5948 switch (ainfo->regtype) {
5949 case RegTypeGeneral: {
5950 if (((next->opcode == OP_LOAD_MEMBASE) ||
5951 (next->opcode == OP_LOADI4_MEMBASE)) &&
5952 next->inst_basereg == inst->inst_basereg &&
5953 next->inst_offset == inst->inst_offset) {
5954 if (next->dreg == ainfo->reg) {
5958 next->opcode = OP_MOVE;
5959 next->sreg1 = ainfo->reg;
5960 /* Only continue if the instruction doesn't change argument regs */
5961 if (next->dreg == ainfo->reg)
5971 /* Argument allocated to (non-volatile) register */
5972 switch (ainfo->regtype) {
5973 case RegTypeGeneral:
5974 if (next->opcode == OP_MOVE &&
5975 next->sreg1 == inst->dreg &&
5976 next->dreg == ainfo->reg) {
5987 next = mono_inst_next (next, filter);
5994 cfg->code_len = code - cfg->native_code;
5995 g_assert (cfg->code_len < cfg->code_size);
6000 /*========================= End of Function ========================*/
6002 /*------------------------------------------------------------------*/
6004 /* Name - mono_arch_emit_epilog */
6006 /* Function - Emit the instructions for a function epilog. */
6008 /*------------------------------------------------------------------*/
6011 mono_arch_emit_epilog (MonoCompile *cfg)
6013 MonoMethod *method = cfg->method;
6016 int max_epilog_size = 96;
6018 if (cfg->method->save_lmf)
6019 max_epilog_size += 128;
6021 if (mono_jit_trace_calls != NULL)
6022 max_epilog_size += 128;
6023 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6024 max_epilog_size += 128;
6026 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6027 cfg->code_size *= 2;
6028 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6029 cfg->stat_code_reallocs++;
6032 code = cfg->native_code + cfg->code_len;
6034 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6035 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6039 if (method->save_lmf)
6040 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6042 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6043 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6045 code = backUpStackPtr(cfg, code);
6047 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6048 s390_br (code, s390_r14);
6050 cfg->code_len = code - cfg->native_code;
6052 g_assert (cfg->code_len < cfg->code_size);
6056 /*========================= End of Function ========================*/
6058 /*------------------------------------------------------------------*/
6060 /* Name - mono_arch_emit_exceptions */
6062 /* Function - Emit the blocks to handle exception conditions. */
6064 /*------------------------------------------------------------------*/
6067 mono_arch_emit_exceptions (MonoCompile *cfg)
6069 MonoJumpInfo *patch_info;
6075 MonoClass *exc_classes [MAX_EXC];
6076 guint8 *exc_throw_start [MAX_EXC];
6078 for (patch_info = cfg->patch_info;
6080 patch_info = patch_info->next) {
6081 if (patch_info->type == MONO_PATCH_INFO_EXC)
6085 code_size = exc_count * 48;
6087 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6088 cfg->code_size *= 2;
6089 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6090 cfg->stat_code_reallocs++;
6093 code = cfg->native_code + cfg->code_len;
6095 /*---------------------------------------------------------------------*/
6096 /* Add code to raise exceptions */
6097 /*---------------------------------------------------------------------*/
6098 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6099 switch (patch_info->type) {
6100 case MONO_PATCH_INFO_EXC: {
6101 guint8 *ip = patch_info->ip.i + cfg->native_code;
6102 MonoClass *exc_class;
6105 /*-----------------------------------------------------*/
6106 /* Patch the branch in epilog to come here */
6107 /*-----------------------------------------------------*/
6108 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6110 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6112 patch_info->data.name);
6113 throw_ip = patch_info->ip.i;
6115 for (iExc = 0; iExc < nThrows; ++iExc)
6116 if (exc_classes [iExc] == exc_class)
6119 if (iExc < nThrows) {
6120 s390_jcl (code, S390_CC_UN,
6121 (guint64) exc_throw_start [iExc]);
6122 patch_info->type = MONO_PATCH_INFO_NONE;
6125 if (nThrows < MAX_EXC) {
6126 exc_classes [nThrows] = exc_class;
6127 exc_throw_start [nThrows] = code;
6130 /*---------------------------------------------*/
6131 /* Patch the parameter passed to the handler */
6132 /*---------------------------------------------*/
6133 S390_SET (code, s390_r2, exc_class->type_token);
6134 /*---------------------------------------------*/
6135 /* Load return address & parameter register */
6136 /*---------------------------------------------*/
6137 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6138 cfg->native_code + 8), code));
6139 /*---------------------------------------------*/
6140 /* Reuse the current patch to set the jump */
6141 /*---------------------------------------------*/
6142 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6143 patch_info->data.name = "mono_arch_throw_corlib_exception";
6144 patch_info->ip.i = code - cfg->native_code;
6145 S390_BR_TEMPLATE (code, s390_r1);
6155 cfg->code_len = code - cfg->native_code;
6157 g_assert (cfg->code_len < cfg->code_size);
6161 /*========================= End of Function ========================*/
6163 /*------------------------------------------------------------------*/
6165 /* Name - mono_arch_finish_init */
6167 /* Function - Setup the JIT's Thread Level Specific Data. */
6169 /*------------------------------------------------------------------*/
6172 mono_arch_finish_init (void)
6176 /*========================= End of Function ========================*/
6178 /*------------------------------------------------------------------*/
6180 /* Name - mono_arch_free_jit_tls_data */
6182 /* Function - Free tls data. */
6184 /*------------------------------------------------------------------*/
6187 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6191 /*========================= End of Function ========================*/
6193 /*------------------------------------------------------------------*/
6195 /* Name - mono_arch_emit_inst_for_method */
6197 /*------------------------------------------------------------------*/
6200 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6205 /*========================= End of Function ========================*/
6207 /*------------------------------------------------------------------*/
6209 /* Name - mono_arch_decompose_opts */
6211 /* Function - Decompose opcode into a System z opcode. */
6213 /*------------------------------------------------------------------*/
6216 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6219 * Have to rename these to avoid being decomposed normally, since the normal
6220 * decomposition does not work on S390.
6222 switch (ins->opcode) {
6224 ins->opcode = OP_S390_ISUB_OVF;
6226 case OP_ISUB_OVF_UN:
6227 ins->opcode = OP_S390_ISUB_OVF_UN;
6230 ins->opcode = OP_S390_IADD_OVF;
6232 case OP_IADD_OVF_UN:
6233 ins->opcode = OP_S390_IADD_OVF_UN;
6236 ins->opcode = OP_S390_LADD_OVF;
6238 case OP_LADD_OVF_UN:
6239 ins->opcode = OP_S390_LADD_OVF_UN;
6242 ins->opcode = OP_S390_LSUB_OVF;
6244 case OP_LSUB_OVF_UN:
6245 ins->opcode = OP_S390_LSUB_OVF_UN;
6252 /*========================= End of Function ========================*/
6254 /*------------------------------------------------------------------*/
6256 /* Name - mono_arch_print_tree */
6258 /* Function - Print platform-specific opcode details. */
6260 /* Returns - 1 - opcode details have been printed */
6261 /* 0 - opcode details have not been printed */
6263 /*------------------------------------------------------------------*/
6266 mono_arch_print_tree (MonoInst *tree, int arity)
6270 switch (tree->opcode) {
6271 case OP_S390_LOADARG:
6272 case OP_S390_ARGREG:
6273 case OP_S390_ARGPTR:
6274 printf ("[0x%lx(%s)]", tree->inst_offset,
6275 mono_arch_regname (tree->inst_basereg));
6278 case OP_S390_STKARG:
6279 printf ("[0x%lx(previous_frame)]",
6284 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6285 tree->inst_offset, tree->backend.size,
6286 mono_arch_regname(tree->dreg),
6288 mono_arch_regname(tree->sreg1));
6291 case OP_S390_SETF4RET:
6292 printf ("[f%s,f%s]",
6293 mono_arch_regname (tree->dreg),
6294 mono_arch_regname (tree->sreg1));
6298 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6300 mono_arch_regname (tree->sreg1));
6304 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6306 mono_arch_regname (tree->sreg1));
6309 case OP_S390_BKCHAIN:
6310 printf ("[previous_frame(%s)]",
6311 mono_arch_regname (tree->sreg1));
6319 /*========================= End of Function ========================*/
6321 /*------------------------------------------------------------------*/
6323 /* Name - mono_arch_regalloc_cost */
6325 /* Function - Determine the cost, in the number of memory */
6326 /* references, of the action of allocating the var- */
6327 /* iable VMV into a register during global register */
6330 /* Returns - Cost */
6332 /*------------------------------------------------------------------*/
6335 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6341 /*========================= End of Function ========================*/
6343 /*------------------------------------------------------------------*/
6345 /* Name - mono_arch_flush_register_windows */
6351 /*------------------------------------------------------------------*/
6354 mono_arch_flush_register_windows (void)
6358 /*========================= End of Function ========================*/
6360 /*------------------------------------------------------------------*/
6362 /* Name - mono_arch_is_inst_imm */
6364 /* Function - Determine if operand qualifies as an immediate */
6365 /* value. For s390 this is a value -32768-32768 */
6367 /* Returns - True|False - is [not] immediate value. */
6369 /*------------------------------------------------------------------*/
6372 mono_arch_is_inst_imm (gint64 imm)
6374 return s390_is_imm32 (imm);
6377 /*========================= End of Function ========================*/
6379 /*------------------------------------------------------------------*/
6381 /* Name - mono_arch_get_patch_offset */
6383 /* Function - Dummy entry point until s390x supports aot. */
6385 /* Returns - Offset for patch. */
6387 /*------------------------------------------------------------------*/
6390 mono_arch_get_patch_offset (guint8 *code)
6395 /*========================= End of Function ========================*/
6397 /*------------------------------------------------------------------*/
6399 /* Name - mono_arch_context_get_int_reg. */
6403 /* Returns - Return a register from the context. */
6405 /*------------------------------------------------------------------*/
6408 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6410 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6413 /*========================= End of Function ========================*/
6415 /*------------------------------------------------------------------*/
6417 /* Name - mono_arch_context_set_int_reg. */
6419 /* Function - Set a value in a specified register. */
6421 /*------------------------------------------------------------------*/
6424 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6426 ctx->uc_mcontext.gregs[reg] = val;
6429 /*========================= End of Function ========================*/
6431 /*------------------------------------------------------------------*/
6433 /* Name - mono_arch_get_this_arg_from_call. */
6437 /*------------------------------------------------------------------*/
6440 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6442 return (gpointer) regs [s390_r2];
6445 /*========================= End of Function ========================*/
6447 /*------------------------------------------------------------------*/
6449 /* Name - mono_arch_install_handler_block_guard */
6453 /*------------------------------------------------------------------*/
6456 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6457 MonoContext *ctx, gpointer new_value)
6460 gpointer *sp, old_value;
6463 offset = clause->exvar_offset;
6466 bp = MONO_CONTEXT_GET_BP (ctx);
6467 sp = *(gpointer*)(bp + offset);
6470 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6478 /*========================= End of Function ========================*/
6480 /*------------------------------------------------------------------*/
6482 /* Name - get_delegate_invoke_impl. */
6486 /*------------------------------------------------------------------*/
6489 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6491 guint8 *code, *start;
6496 start = code = mono_global_codeman_reserve (size);
6498 /* Replace the this argument with the target */
6499 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6500 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6501 s390_br (code, s390_r1);
6502 g_assert ((code - start) <= size);
6504 mono_arch_flush_icache (start, size);
6508 size = 32 + param_count * 8;
6509 start = code = mono_global_codeman_reserve (size);
6511 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6512 /* slide down the arguments */
6513 for (i = 0; i < param_count; ++i) {
6514 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6516 s390_br (code, s390_r1);
6518 g_assert ((code - start) <= size);
6520 mono_arch_flush_icache (start, size);
6523 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6526 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6528 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6529 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6536 /*========================= End of Function ========================*/
6538 /*------------------------------------------------------------------*/
6540 /* Name - mono_arch_get_delegate_invoke_impls. */
6544 /*------------------------------------------------------------------*/
6547 mono_arch_get_delegate_invoke_impls (void)
6550 MonoTrampInfo *info;
6553 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6554 res = g_slist_prepend (res, info);
6556 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6557 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6558 res = g_slist_prepend (res, info);
6564 /*========================= End of Function ========================*/
6566 /*------------------------------------------------------------------*/
6568 /* Name - mono_arch_get_delegate_invoke_impl. */
6572 /*------------------------------------------------------------------*/
6575 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6577 guint8 *code, *start;
6579 /* FIXME: Support more cases */
6580 if (MONO_TYPE_ISSTRUCT (sig->ret))
6584 static guint8* cached = NULL;
6589 if (mono_aot_only) {
6590 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6592 MonoTrampInfo *info;
6593 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6594 mono_tramp_info_register (info, NULL);
6597 mono_memory_barrier ();
6601 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6604 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6606 for (i = 0; i < sig->param_count; ++i)
6607 if (!mono_is_regsize_var (sig->params [i]))
6611 code = cache [sig->param_count];
6615 if (mono_aot_only) {
6616 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6617 start = mono_aot_get_trampoline (name);
6620 MonoTrampInfo *info;
6621 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6622 mono_tramp_info_register (info, NULL);
6625 mono_memory_barrier ();
6627 cache [sig->param_count] = start;
6632 /*========================= End of Function ========================*/
6634 /*------------------------------------------------------------------*/
6636 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6640 /*------------------------------------------------------------------*/
6643 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6644 int offset, gboolean load_imt_reg)
6646 guint8 *code, *start;
6649 start = code = mono_global_codeman_reserve (size);
6652 * Replace the "this" argument with the target
6654 s390_lgr (code, s390_r1, s390_r2);
6655 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6658 * Load the IMT register, if needed
6661 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6667 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6669 s390_agfi(code, s390_r1, offset);
6671 s390_lg (code, s390_r1, 0, s390_r1, 0);
6672 s390_br (code, s390_r1);
6677 /*========================= End of Function ========================*/
6679 /*------------------------------------------------------------------*/
6681 /* Name - mono_arch_build_imt_trampoline. */
6685 /*------------------------------------------------------------------*/
6688 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6689 MonoIMTCheckItem **imt_entries, int count,
6690 gpointer fail_tramp)
6694 guchar *code, *start;
6697 for (i = 0; i < count; ++i) {
6698 MonoIMTCheckItem *item = imt_entries [i];
6699 if (item->is_equals) {
6700 if (item->check_target_idx) {
6701 if (!item->compare_done)
6702 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6703 if (item->has_target_code)
6704 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6706 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6710 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6712 if (!item->has_target_code)
6713 item->chunk_size += LOAD_SIZE;
6715 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6716 #if ENABLE_WRONG_METHOD_CHECK
6717 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6722 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6723 imt_entries [item->check_target_idx]->compare_done = TRUE;
6725 size += item->chunk_size;
6729 code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6731 code = mono_domain_code_reserve (domain, size);
6735 for (i = 0; i < count; ++i) {
6736 MonoIMTCheckItem *item = imt_entries [i];
6737 item->code_target = (guint8 *) code;
6738 if (item->is_equals) {
6739 if (item->check_target_idx) {
6740 if (!item->compare_done) {
6741 S390_SET (code, s390_r0, item->key);
6742 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6744 item->jmp_code = (guint8*) code;
6745 s390_jcl (code, S390_CC_NE, 0);
6747 if (item->has_target_code) {
6748 S390_SET (code, s390_r1, item->value.target_code);
6750 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6751 s390_lg (code, s390_r1, 0, s390_r1, 0);
6753 s390_br (code, s390_r1);
6758 S390_SET (code, s390_r0, item->key);
6759 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6760 item->jmp_code = (guint8*) code;
6761 s390_jcl (code, S390_CC_NE, 0);
6762 if (item->has_target_code) {
6763 S390_SET (code, s390_r1, item->value.target_code);
6766 S390_SET (code, s390_r1,
6767 (&(vtable->vtable [item->value.vtable_slot])));
6768 s390_lg (code, s390_r1, 0, s390_r1, 0);
6770 s390_br (code, s390_r1);
6771 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6772 s390_patch_rel(item->jmp_code+2, target);
6773 S390_SET (code, s390_r1, fail_tramp);
6774 s390_br (code, s390_r1);
6775 item->jmp_code = NULL;
6777 /* enable the commented code to assert on wrong method */
6778 #if ENABLE_WRONG_METHOD_CHECK
6779 g_assert_not_reached ();
6781 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6782 s390_lg (code, s390_r1, 0, s390_r1, 0);
6783 s390_br (code, s390_r1);
6787 S390_SET (code, s390_r0, item->key);
6788 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6789 item->jmp_code = (guint8 *) code;
6790 s390_jcl (code, S390_CC_GE, 0);
6794 * patch the branches to get to the target items
6796 for (i = 0; i < count; ++i) {
6797 MonoIMTCheckItem *item = imt_entries [i];
6798 if (item->jmp_code) {
6799 if (item->check_target_idx) {
6801 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6803 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6808 mono_arch_flush_icache ((guint8*)start, (code - start));
6809 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6812 mono_stats.imt_trampolines_size += (code - start);
6814 g_assert (code - start <= size);
6816 snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
6817 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6822 /*========================= End of Function ========================*/
6824 /*------------------------------------------------------------------*/
6826 /* Name - mono_arch_find_imt_method. */
6828 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6829 /* found in the save area. */
6831 /*------------------------------------------------------------------*/
6834 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6836 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6839 /*========================= End of Function ========================*/
6841 /*------------------------------------------------------------------*/
6843 /* Name - mono_arch_find_static_call_vtable */
6845 /* Function - Find the static call vtable. */
6847 /*------------------------------------------------------------------*/
6850 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6852 mgreg_t *r = (mgreg_t*)regs;
6854 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6857 /*========================= End of Function ========================*/
6859 /*------------------------------------------------------------------*/
6861 /* Name - mono_arch_get_cie_program */
6863 /* Function - Find the static call vtable. */
6865 /*------------------------------------------------------------------*/
6868 mono_arch_get_cie_program (void)
6872 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6877 /*========================= End of Function ========================*/
6879 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6881 /*------------------------------------------------------------------*/
6883 /* Name - mono_arch_set_breakpoint. */
6885 /* Function - Set a breakpoint at the native code corresponding */
6886 /* to JI at NATIVE_OFFSET. The location should */
6887 /* contain code emitted by OP_SEQ_POINT. */
6889 /*------------------------------------------------------------------*/
6892 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6896 breakpointCode.pTrigger = bp_trigger_page;
6897 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6898 code += BREAKPOINT_SIZE;
6901 /*========================= End of Function ========================*/
6903 /*------------------------------------------------------------------*/
6905 /* Name - mono_arch_clear_breakpoint. */
6907 /* Function - Clear the breakpoint at IP. */
6909 /*------------------------------------------------------------------*/
6912 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6917 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6921 /*========================= End of Function ========================*/
6923 /*------------------------------------------------------------------*/
6925 /* Name - mono_arch_is_breakpoint_event. */
6929 /*------------------------------------------------------------------*/
6932 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6934 siginfo_t* sinfo = (siginfo_t*) info;
6937 * Sometimes the address is off by 4
6939 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6945 /*========================= End of Function ========================*/
6947 /*------------------------------------------------------------------*/
6949 /* Name - mono_arch_skip_breakpoint. */
6951 /* Function - Modify the CTX so the IP is placed after the */
6952 /* breakpoint instruction, so when we resume, the */
6953 /* instruction is not executed again. */
6955 /*------------------------------------------------------------------*/
6958 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6960 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6963 /*========================= End of Function ========================*/
6965 /*------------------------------------------------------------------*/
6967 /* Name - mono_arch_start_single_stepping. */
6969 /* Function - Start single stepping. */
6971 /*------------------------------------------------------------------*/
6974 mono_arch_start_single_stepping (void)
6976 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6979 /*========================= End of Function ========================*/
6981 /*------------------------------------------------------------------*/
6983 /* Name - mono_arch_stop_single_stepping. */
6985 /* Function - Stop single stepping. */
6987 /*------------------------------------------------------------------*/
6990 mono_arch_stop_single_stepping (void)
6992 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6995 /*========================= End of Function ========================*/
6997 /*------------------------------------------------------------------*/
6999 /* Name - mono_arch_is_single_step_event. */
7001 /* Function - Return whether the machine state in sigctx cor- */
7002 /* responds to a single step event. */
7004 /*------------------------------------------------------------------*/
7007 mono_arch_is_single_step_event (void *info, void *sigctx)
7009 siginfo_t* sinfo = (siginfo_t*) info;
7012 * Sometimes the address is off by 4
7014 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7020 /*========================= End of Function ========================*/
7022 /*------------------------------------------------------------------*/
7024 /* Name - mono_arch_skip_single_step. */
7026 /* Function - Modify the ctx so the IP is placed after the */
7027 /* single step trigger instruction, so that the */
7028 /* instruction is not executed again. */
7030 /*------------------------------------------------------------------*/
7033 mono_arch_skip_single_step (MonoContext *ctx)
7035 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7038 /*========================= End of Function ========================*/
7040 /*------------------------------------------------------------------*/
7042 /* Name - mono_arch_create_seq_point_info. */
7044 /* Function - Return a pointer to a data struction which is */
7045 /* used by the sequence point implementation in */
7048 /*------------------------------------------------------------------*/
7051 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7057 /*========================= End of Function ========================*/
7059 /*------------------------------------------------------------------*/
7061 /* Name - mono_arch_init_lmf_ext. */
7065 /*------------------------------------------------------------------*/
7068 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7070 ext->lmf.previous_lmf = prev_lmf;
7071 /* Mark that this is a MonoLMFExt */
7072 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7073 ext->lmf.ebp = (gssize)ext;
7076 /*========================= End of Function ========================*/
7080 /*------------------------------------------------------------------*/
7082 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7084 /* Function - If this CPU supports vector operations then it */
7085 /* supports the equivalent of SSE1-4. */
7087 /*------------------------------------------------------------------*/
7090 mono_arch_cpu_enumerate_simd_versions (void)
7092 guint32 sseOpts = 0;
7094 if (mono_hwcap_s390x_has_vec)
7095 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7096 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7097 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7098 SIMD_VERSION_SSE4a);
7103 /*========================= End of Function ========================*/
7105 /*------------------------------------------------------------------*/
7107 /* Name - mono_arch_opcode_supported. */
7109 /* Function - Check if a given return code is supported. */
7111 /*------------------------------------------------------------------*/
7114 mono_arch_opcode_supported (int opcode)
7117 case OP_ATOMIC_ADD_I4:
7118 case OP_ATOMIC_ADD_I8:
7119 case OP_ATOMIC_EXCHANGE_I4:
7120 case OP_ATOMIC_EXCHANGE_I8:
7127 /*========================= End of Function ========================*/