1 /*------------------------------------------------------------------*/
3 /* Name - mini-s390.c */
5 /* Function - S/390 backend for the Mono code generator. */
7 /* Name - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) */
9 /* Date - January, 2004 */
11 /* Derivation - From mini-x86 & mini-ppc by - */
12 /* Paolo Molaro (lupus@ximian.com) */
13 /* Dietmar Maurer (dietmar@ximian.com) */
15 /*------------------------------------------------------------------*/
17 /*------------------------------------------------------------------*/
19 /*------------------------------------------------------------------*/
21 #define MAX_ARCH_DELEGATE_PARAMS 7
23 #define EMIT_COND_BRANCH(ins,cond) \
25 if (ins->inst_true_bb->native_offset) { \
27 displace = ((cfg->native_code + \
28 ins->inst_true_bb->native_offset) - code) / 2; \
29 if (s390_is_imm16(displace)) { \
30 s390_brc (code, cond, displace); \
32 s390_jcl (code, cond, displace); \
35 mono_add_patch_info (cfg, code - cfg->native_code, \
36 MONO_PATCH_INFO_BB, ins->inst_true_bb); \
37 s390_jcl (code, cond, 0); \
41 #define EMIT_UNCOND_BRANCH(ins) \
43 if (ins->inst_target_bb->native_offset) { \
45 displace = ((cfg->native_code + \
46 ins->inst_target_bb->native_offset) - code) / 2; \
47 if (s390_is_imm16(displace)) { \
48 s390_brc (code, S390_CC_UN, displace); \
50 s390_jcl (code, S390_CC_UN, displace); \
53 mono_add_patch_info (cfg, code - cfg->native_code, \
54 MONO_PATCH_INFO_BB, ins->inst_target_bb); \
55 s390_jcl (code, S390_CC_UN, 0); \
59 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name) \
61 mono_add_patch_info (cfg, code - cfg->native_code, \
62 MONO_PATCH_INFO_EXC, exc_name); \
63 s390_jcl (code, cond, 0); \
66 #define CHECK_SRCDST_COM \
67 if (ins->dreg == ins->sreg2) { \
71 if (ins->dreg != ins->sreg1) { \
72 s390_lgr (code, ins->dreg, ins->sreg1); \
76 #define CHECK_SRCDST_NCOM \
77 if (ins->dreg == ins->sreg2) { \
79 s390_lgr (code, s390_r13, ins->sreg2); \
83 if (ins->dreg != ins->sreg1) { \
84 s390_lgr (code, ins->dreg, ins->sreg1); \
87 #define CHECK_SRCDST_COM_I \
88 if (ins->dreg == ins->sreg2) { \
92 if (ins->dreg != ins->sreg1) { \
93 s390_lgfr (code, ins->dreg, ins->sreg1); \
97 #define CHECK_SRCDST_NCOM_I \
98 if (ins->dreg == ins->sreg2) { \
100 s390_lgfr (code, s390_r13, ins->sreg2); \
104 if (ins->dreg != ins->sreg1) { \
105 s390_lgfr (code, ins->dreg, ins->sreg1); \
108 #define CHECK_SRCDST_COM_F \
109 if (ins->dreg == ins->sreg2) { \
113 if (ins->dreg != ins->sreg1) { \
114 s390_ldr (code, ins->dreg, ins->sreg1); \
118 #define CHECK_SRCDST_NCOM_F \
119 if (ins->dreg == ins->sreg2) { \
121 s390_ldr (code, s390_r13, ins->sreg2); \
125 if (ins->dreg != ins->sreg1) { \
126 s390_ldr (code, ins->dreg, ins->sreg1); \
129 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \
132 MONO_INST_NEW (cfg, inst, OP_NOP); \
135 inst->inst_offset = offset; \
137 inst->inst_imm = imm; \
139 if (s390_is_uimm12(offset)) { \
141 inst->inst_offset = offset; \
143 dReg = mono_alloc_preg (cfg); \
144 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
145 dReg, dest, offset); \
147 inst->inst_offset = 0; \
149 if (s390_is_uimm12(imm)) { \
151 inst->inst_imm = imm; \
153 sReg = mono_alloc_preg (cfg); \
154 MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM, \
156 inst->sreg1 = sReg; \
157 inst->inst_imm = 0; \
160 inst->opcode = OP_S390_MOVE; \
161 inst->backend.size = size; \
162 MONO_ADD_INS (cfg->cbb, inst); \
165 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \
166 int reg = mono_alloc_preg (cfg); \
169 MONO_EMIT_NEW_ICONST(cfg, reg, 0); \
172 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
176 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
180 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
184 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE, \
188 mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE); \
191 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do { \
195 tmpr = mono_alloc_preg (cfg); \
196 MONO_EMIT_NEW_ICONST(cfg, tmpr, 0); \
197 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
201 tmpr = mono_alloc_preg (cfg); \
202 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \
204 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
208 tmpr = mono_alloc_preg (cfg); \
209 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \
211 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
215 tmpr = mono_alloc_preg (cfg); \
216 MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE, \
218 MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG, \
222 MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size); \
228 #define DEBUG(a) if (cfg->verbose_level > 1) a
232 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
234 #define BREAKPOINT_SIZE sizeof(breakpoint_t)
235 #define S390X_NOP_SIZE sizeof(RR_Format)
237 #define MAX(a, b) ((a) > (b) ? (a) : (b))
240 * imt thunking size values
243 #define LOADCON_SIZE 20
247 #define ENABLE_WRONG_METHOD_CHECK 0
249 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
250 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
252 /*========================= End of Defines =========================*/
254 /*------------------------------------------------------------------*/
255 /* I n c l u d e s */
256 /*------------------------------------------------------------------*/
260 #include <sys/types.h>
263 #include <mono/metadata/abi-details.h>
264 #include <mono/metadata/appdomain.h>
265 #include <mono/metadata/debug-helpers.h>
266 #include <mono/metadata/profiler-private.h>
267 #include <mono/utils/mono-math.h>
268 #include <mono/utils/mono-mmap.h>
269 #include <mono/utils/mono-hwcap-s390x.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;
392 static gint appdomain_tls_offset = -1,
394 lmf_addr_tls_offset = -1;
396 pthread_key_t lmf_addr_key;
398 gboolean lmf_addr_key_inited = FALSE;
403 * The code generated for sequence points reads from this location,
404 * which is made read-only when single stepping is enabled.
406 static gpointer ss_trigger_page;
409 * Enabled breakpoints read from this trigger page
411 static gpointer bp_trigger_page;
413 breakpoint_t breakpointCode;
415 static mono_mutex_t mini_arch_mutex;
417 static const char * grNames[] = {
418 "s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
419 "s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
420 "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
424 static const char * fpNames[] = {
425 "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
426 "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
427 "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
431 static const char * vrNames[] = {
432 "vr0", "vr1", "vr2", "vr3", "vr4", "vr5", "vr6", "vr7",
433 "vr8", "vr9", "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
434 "vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
435 "vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
438 /*====================== End of Global Variables ===================*/
440 /*------------------------------------------------------------------*/
442 /* Name - mono_arch_regname */
444 /* Function - Returns the name of the register specified by */
445 /* the input parameter. */
447 /*------------------------------------------------------------------*/
450 mono_arch_regname (int reg)
452 if (reg >= 0 && reg < 16)
453 return grNames [reg];
458 /*========================= End of Function ========================*/
460 /*------------------------------------------------------------------*/
462 /* Name - mono_arch_fregname */
464 /* Function - Returns the name of the register specified by */
465 /* the input parameter. */
467 /*------------------------------------------------------------------*/
470 mono_arch_fregname (int reg)
472 if (reg >= 0 && reg < 16)
473 return fpNames [reg];
478 /*========================= End of Function ========================*/
480 /*------------------------------------------------------------------*/
482 /* Name - mono_arch_xregname */
484 /* Function - Returns the name of the register specified by */
485 /* the input parameter. */
487 /*------------------------------------------------------------------*/
490 mono_arch_xregname (int reg)
492 if (reg < s390_VR_NREG)
493 return vrNames [reg];
498 /*========================= End of Function ========================*/
500 /*------------------------------------------------------------------*/
502 /* Name - arch_get_argument_info */
504 /* Function - Gathers information on parameters such as size, */
505 /* alignment, and padding. arg_info should be large */
506 /* enough to hold param_count + 1 entries. */
508 /* Parameters - @csig - Method signature */
509 /* @param_count - No. of parameters to consider */
510 /* @arg_info - An array to store the result info */
512 /* Returns - Size of the activation frame */
514 /*------------------------------------------------------------------*/
517 mono_arch_get_argument_info (MonoMethodSignature *csig,
519 MonoJitArgumentInfo *arg_info)
521 int k, frame_size = 0;
522 int size, align, pad;
525 if (MONO_TYPE_ISSTRUCT (csig->ret)) {
526 frame_size += sizeof (gpointer);
530 arg_info [0].offset = offset;
533 frame_size += sizeof (gpointer);
537 arg_info [0].size = frame_size;
539 for (k = 0; k < param_count; k++) {
542 size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
544 size = mini_type_stack_size (csig->params [k], &align);
546 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
547 arg_info [k].pad = pad;
549 arg_info [k + 1].pad = 0;
550 arg_info [k + 1].size = size;
552 arg_info [k + 1].offset = offset;
556 align = MONO_ARCH_FRAME_ALIGNMENT;
557 frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
558 arg_info [k].pad = pad;
563 /*========================= End of Function ========================*/
565 /*------------------------------------------------------------------*/
567 /* Name - emit_unwind_regs. */
569 /* Function - Determines if a value can be returned in one or */
572 /*------------------------------------------------------------------*/
574 static void __inline__
575 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
579 for (i = start; i < end; i++) {
580 mono_emit_unwind_op_offset (cfg, code, i, offset);
581 mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
582 offset += sizeof(gulong);
586 /*========================= End of Function ========================*/
588 /*------------------------------------------------------------------*/
590 /* Name - retFitsInReg. */
592 /* Function - Determines if a value can be returned in one or */
595 /*------------------------------------------------------------------*/
597 static inline gboolean
598 retFitsInReg(guint32 size)
613 /*========================= End of Function ========================*/
615 /*------------------------------------------------------------------*/
617 /* Name - backStackPtr. */
619 /* Function - Restore Stack Pointer to previous frame. */
621 /*------------------------------------------------------------------*/
623 static inline guint8 *
624 backUpStackPtr(MonoCompile *cfg, guint8 *code)
626 int stackSize = cfg->stack_usage;
628 if (cfg->frame_reg != STK_BASE)
629 s390_lgr (code, STK_BASE, cfg->frame_reg);
631 if (s390_is_imm16 (stackSize)) {
632 s390_aghi (code, STK_BASE, stackSize);
634 while (stackSize > 32767) {
635 s390_aghi (code, STK_BASE, 32767);
638 s390_aghi (code, STK_BASE, stackSize);
643 /*========================= End of Function ========================*/
645 /*------------------------------------------------------------------*/
649 /* Function - Perform nice indenting to current level */
651 /*------------------------------------------------------------------*/
657 indent_level += diff;
659 printf("%p [%3d] ",(void *)pthread_self(),v);
664 indent_level += diff;
667 /*========================= End of Function ========================*/
669 /*------------------------------------------------------------------*/
671 /* Name - cvtMonoType */
673 /* Function - Convert a mono-type to a string. */
675 /*------------------------------------------------------------------*/
678 cvtMonoType(MonoTypeEnum t)
683 return "MONO_TYPE_END";
685 return "MONO_TYPE_VOID";
686 case MONO_TYPE_BOOLEAN:
687 return "MONO_TYPE_BOOLEAN";
689 return "MONO_TYPE_CHAR";
691 return "MONO_TYPE_I1";
693 return "MONO_TYPE_U1";
695 return "MONO_TYPE_I2";
697 return "MONO_TYPE_U2";
699 return "MONO_TYPE_I4";
701 return "MONO_TYPE_U4";
703 return "MONO_TYPE_I8";
705 return "MONO_TYPE_U8";
707 return "MONO_TYPE_R4";
709 return "MONO_TYPE_R8";
710 case MONO_TYPE_STRING:
711 return "MONO_TYPE_STRING";
713 return "MONO_TYPE_PTR";
714 case MONO_TYPE_BYREF:
715 return "MONO_TYPE_BYREF";
716 case MONO_TYPE_VALUETYPE:
717 return "MONO_TYPE_VALUETYPE";
718 case MONO_TYPE_CLASS:
719 return "MONO_TYPE_CLASS";
721 return "MONO_TYPE_VAR";
722 case MONO_TYPE_ARRAY:
723 return "MONO_TYPE_ARRAY";
724 case MONO_TYPE_GENERICINST:
725 return "MONO_TYPE_GENERICINST";
726 case MONO_TYPE_TYPEDBYREF:
727 return "MONO_TYPE_TYPEDBYREF";
729 return "MONO_TYPE_I";
731 return "MONO_TYPE_U";
732 case MONO_TYPE_FNPTR:
733 return "MONO_TYPE_FNPTR";
734 case MONO_TYPE_OBJECT:
735 return "MONO_TYPE_OBJECT";
736 case MONO_TYPE_SZARRAY:
737 return "MONO_TYPE_SZARRAY";
739 return "MONO_TYPE_MVAR";
740 case MONO_TYPE_CMOD_REQD:
741 return "MONO_TYPE_CMOD_REQD";
742 case MONO_TYPE_CMOD_OPT:
743 return "MONO_TYPE_CMOD_OPT";
744 case MONO_TYPE_INTERNAL:
745 return "MONO_TYPE_INTERNAL";
746 case MONO_TYPE_MODIFIER:
747 return "MONO_TYPE_MODIFIER";
748 case MONO_TYPE_SENTINEL:
749 return "MONO_TYPE_SENTINEL";
750 case MONO_TYPE_PINNED:
751 return "MONO_TYPE_PINNED";
758 /*========================= End of Function ========================*/
760 /*------------------------------------------------------------------*/
762 /* Name - decodeParm */
764 /* Function - Decode a parameter for the trace. */
766 /*------------------------------------------------------------------*/
769 decodeParm(MonoType *type, void *curParm, int size)
774 printf("[BYREF:%p], ", *((char **) curParm));
776 simpleType = mini_get_underlying_type(type)->type;
778 switch (simpleType) {
780 printf ("[INTPTR:%p], ", *((int **) curParm));
783 printf ("[UINTPTR:%p], ", *((int **) curParm));
785 case MONO_TYPE_BOOLEAN :
786 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
788 case MONO_TYPE_CHAR :
789 printf ("[CHAR:%c], ", *((int *) curParm));
792 printf ("[INT1:%ld], ", *((gint64 *) curParm));
795 printf ("[INT2:%ld], ", *((gint64 *) curParm));
798 printf ("[INT4:%ld], ", *((gint64 *) curParm));
801 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
804 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
807 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
810 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
812 case MONO_TYPE_STRING : {
813 MonoString *s = *((MonoString **) curParm);
815 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
816 printf("[STRING:%p:%s], ", s, mono_string_to_utf8(s));
818 printf("[STRING:null], ");
822 case MONO_TYPE_CLASS :
823 case MONO_TYPE_OBJECT : {
824 MonoObject *obj = *((MonoObject **) curParm);
826 if ((obj) && (obj->vtable)) {
827 printf("[CLASS/OBJ:");
828 klass = obj->vtable->klass;
829 printf("%p [%p] ",obj,curParm);
830 if (klass == mono_defaults.string_class) {
831 printf("[STRING:%p:%s]",
832 obj, mono_string_to_utf8 ((MonoString *) obj));
833 } else if (klass == mono_defaults.int32_class) {
834 printf("[INT32:%p:%d]",
835 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
838 klass->name_space, klass->name, obj);
841 printf("[OBJECT:null], ");
846 printf("[PTR:%p], ", *((gpointer **) (curParm)));
848 case MONO_TYPE_FNPTR :
849 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
851 case MONO_TYPE_ARRAY :
852 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
854 case MONO_TYPE_SZARRAY :
855 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
858 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
861 printf("[FLOAT4:%g], ", *((float *) (curParm)));
864 printf("[FLOAT8:%g], ", *((double *) (curParm)));
866 case MONO_TYPE_VALUETYPE : {
868 MonoMarshalType *info;
870 if (type->data.klass->enumtype) {
871 simpleType = mono_class_enum_basetype (type->data.klass)->type;
872 printf("{VALUETYPE} - ");
876 info = mono_marshal_load_type_info (type->data.klass);
878 if ((info->native_size == sizeof(float)) &&
879 (info->num_fields == 1) &&
880 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
881 printf("[FLOAT4:%f], ", *((float *) (curParm)));
885 if ((info->native_size == sizeof(double)) &&
886 (info->num_fields == 1) &&
887 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
888 printf("[FLOAT8:%g], ", *((double *) (curParm)));
892 printf("[VALUETYPE:");
893 for (i = 0; i < size; i++)
894 printf("%02x,", *((guint8 *)curParm+i));
898 case MONO_TYPE_TYPEDBYREF: {
900 printf("[TYPEDBYREF:");
901 for (i = 0; i < size; i++)
902 printf("%02x,", *((guint8 *)curParm+i));
907 printf("[%s], ",cvtMonoType(simpleType));
912 /*========================= End of Function ========================*/
914 /*------------------------------------------------------------------*/
916 /* Name - enter_method */
918 /* Function - Perform tracing of the entry to the current */
921 /*------------------------------------------------------------------*/
924 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
926 int i, oParm = 0, iParm = 0;
929 MonoMethodSignature *sig;
936 fname = mono_method_full_name (method, TRUE);
938 printf ("ENTER: %s ", fname);
941 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
942 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
947 sig = mono_method_signature (method);
949 cinfo = get_call_info (NULL, NULL, sig);
951 if (cinfo->struct_ret) {
952 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
957 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
958 obj = (MonoObject *) this_arg;
959 switch(method->klass->this_arg.type) {
960 case MONO_TYPE_VALUETYPE:
962 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
963 printf("this:[value:%p:%016lx], ", this_arg, *value);
965 printf ("this:[NULL], ");
967 case MONO_TYPE_STRING:
970 klass = obj->vtable->klass;
971 if (klass == mono_defaults.string_class) {
972 printf ("this:[STRING:%p:%s], ",
973 obj, mono_string_to_utf8 ((MonoString *)obj));
975 printf ("this:%p[%s.%s], ",
976 obj, klass->name_space, klass->name);
979 printf("vtable:[NULL], ");
981 printf ("this:[NULL], ");
984 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
989 for (i = 0; i < sig->param_count; ++i) {
990 ainfo = &cinfo->args[i + oParm];
991 switch (ainfo->regtype) {
992 case RegTypeGeneral :
993 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
996 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
999 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1001 case RegTypeStructByVal :
1002 if (ainfo->reg != STK_BASE) {
1003 int offset = sizeof(glong) - ainfo->size;
1004 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1007 curParm = sp+ainfo->offset;
1009 if (retFitsInReg (ainfo->vtsize))
1010 decodeParm(sig->params[i],
1014 decodeParm(sig->params[i],
1015 *((char **) curParm),
1018 case RegTypeStructByAddr :
1019 if (ainfo->reg != STK_BASE)
1020 curParm = &(rParm->gr[ainfo->reg-2]);
1022 curParm = sp+ainfo->offset;
1024 decodeParm(sig->params[i],
1025 *((char **) curParm),
1037 /*========================= End of Function ========================*/
1039 /*------------------------------------------------------------------*/
1041 /* Name - leave_method */
1045 /*------------------------------------------------------------------*/
1048 leave_method (MonoMethod *method, ...)
1055 va_start(ap, method);
1057 fname = mono_method_full_name (method, TRUE);
1059 printf ("LEAVE: %s", fname);
1062 type = mono_method_signature (method)->ret;
1065 switch (type->type) {
1066 case MONO_TYPE_VOID:
1068 case MONO_TYPE_BOOLEAN: {
1069 int val = va_arg (ap, int);
1071 printf ("[TRUE:%d]", val);
1077 case MONO_TYPE_CHAR: {
1078 int val = va_arg (ap, int);
1079 printf ("[CHAR:%d]", val);
1082 case MONO_TYPE_I1: {
1083 int val = va_arg (ap, int);
1084 printf ("[INT1:%d]", val);
1087 case MONO_TYPE_U1: {
1088 int val = va_arg (ap, int);
1089 printf ("[UINT1:%d]", val);
1092 case MONO_TYPE_I2: {
1093 int val = va_arg (ap, int);
1094 printf ("[INT2:%d]", val);
1097 case MONO_TYPE_U2: {
1098 int val = va_arg (ap, int);
1099 printf ("[UINT2:%d]", val);
1102 case MONO_TYPE_I4: {
1103 int val = va_arg (ap, int);
1104 printf ("[INT4:%d]", val);
1107 case MONO_TYPE_U4: {
1108 int val = va_arg (ap, int);
1109 printf ("[UINT4:%d]", val);
1113 gint64 val = va_arg (ap, gint64);
1114 printf ("[INT:%ld]", val);
1119 gint64 val = va_arg (ap, gint64);
1120 printf ("[UINT:%lu]", val);
1124 case MONO_TYPE_STRING: {
1125 MonoString *s = va_arg (ap, MonoString *);
1128 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1129 printf ("[STRING:%p:%s]", s, mono_string_to_utf8 (s));
1131 printf ("[STRING:null], ");
1134 case MONO_TYPE_CLASS:
1135 case MONO_TYPE_OBJECT: {
1136 MonoObject *o = va_arg (ap, MonoObject *);
1138 if ((o) && (o->vtable)) {
1139 if (o->vtable->klass == mono_defaults.boolean_class) {
1140 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1141 } else if (o->vtable->klass == mono_defaults.int32_class) {
1142 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1143 } else if (o->vtable->klass == mono_defaults.int64_class) {
1144 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1146 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1148 printf ("[OBJECT:%p]", o);
1153 case MONO_TYPE_FNPTR:
1154 case MONO_TYPE_ARRAY:
1155 case MONO_TYPE_SZARRAY: {
1156 gpointer p = va_arg (ap, gpointer);
1157 printf ("[result=%p]", p);
1160 case MONO_TYPE_I8: {
1161 gint64 l = va_arg (ap, gint64);
1162 printf ("[LONG:%ld]", l);
1165 case MONO_TYPE_U8: {
1166 guint64 l = va_arg (ap, guint64);
1167 printf ("[ULONG:%lu]", l);
1170 case MONO_TYPE_R4: {
1171 double f = va_arg (ap, double);
1172 printf ("[FLOAT4:%g]\n", f);
1175 case MONO_TYPE_R8: {
1176 double f = va_arg (ap, double);
1177 printf ("[FLOAT8:%g]\n", f);
1180 case MONO_TYPE_VALUETYPE: {
1181 MonoMarshalType *info;
1182 if (type->data.klass->enumtype) {
1183 type = mono_class_enum_basetype (type->data.klass);
1188 info = mono_marshal_load_type_info (type->data.klass);
1190 if ((info->native_size == sizeof(float)) &&
1191 (info->num_fields == 1) &&
1192 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1193 double f = va_arg (ap, double);
1194 printf("[FLOAT4:%g]\n", (double) f);
1198 if ((info->native_size == sizeof(double)) &&
1199 (info->num_fields == 1) &&
1200 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1201 double f = va_arg (ap, double);
1202 printf("[FLOAT8:%g]\n", f);
1206 size = mono_type_size (type, &align);
1209 guint32 p = va_arg (ap, guint32);
1210 printf ("[%02x]\n",p);
1214 guint32 p = va_arg (ap, guint32);
1215 printf ("[%04x]\n",p);
1219 guint32 p = va_arg (ap, guint32);
1220 printf ("[%08x]\n",p);
1224 guint64 p = va_arg (ap, guint64);
1225 printf ("[%016lx]\n",p);
1229 gpointer p = va_arg (ap, gpointer);
1230 printf ("[VALUETYPE] %p\n",p);
1236 case MONO_TYPE_TYPEDBYREF: {
1237 guint8 *p = va_arg (ap, gpointer);
1239 size = mono_type_size (type, &align);
1246 for (j = 0; p && j < size; j++)
1247 printf ("%02x,", p [j]);
1251 printf ("[TYPEDBYREF]\n");
1255 case MONO_TYPE_GENERICINST: {
1256 printf("[GENERICINST]\n");
1259 case MONO_TYPE_MVAR: {
1263 case MONO_TYPE_CMOD_REQD: {
1264 printf("[CMOD_REQD]\n");
1267 case MONO_TYPE_CMOD_OPT: {
1268 printf("[CMOD_OPT]\n");
1271 case MONO_TYPE_INTERNAL: {
1272 printf("[INTERNAL]\n");
1276 printf ("(unknown return type %x)",
1277 mono_method_signature (method)->ret->type);
1280 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1281 printf (" ip: %p\n", (gpointer) ip);
1284 /*========================= End of Function ========================*/
1286 /*------------------------------------------------------------------*/
1288 /* Name - mono_arch_cpu_init */
1290 /* Function - Perform CPU specific initialization to execute */
1293 /*------------------------------------------------------------------*/
1296 mono_arch_cpu_init (void)
1300 /*========================= End of Function ========================*/
1302 /*------------------------------------------------------------------*/
1304 /* Name - mono_arch_init. */
1306 /* Function - Initialize architecture specific code. */
1308 /*------------------------------------------------------------------*/
1311 mono_arch_init (void)
1315 mono_set_partial_sharing_supported (FALSE);
1316 mono_os_mutex_init_recursive (&mini_arch_mutex);
1318 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1319 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1320 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1322 code = (guint8 *) &breakpointCode;
1323 s390_basr(code, s390_r13, 0);
1325 s390_llong(code, 0);
1326 s390_lg(code, s390_r13, 0, s390_r13, 4);
1327 s390_lg(code, s390_r0, 0, s390_r13, 0);
1330 /*========================= End of Function ========================*/
1332 /*------------------------------------------------------------------*/
1334 /* Name - mono_arch_cleanup. */
1336 /* Function - Cleanup architecture specific code . */
1338 /*------------------------------------------------------------------*/
1341 mono_arch_cleanup (void)
1343 if (ss_trigger_page)
1344 mono_vfree (ss_trigger_page, mono_pagesize ());
1345 if (bp_trigger_page)
1346 mono_vfree (bp_trigger_page, mono_pagesize ());
1347 mono_os_mutex_destroy (&mini_arch_mutex);
1350 /*========================= End of Function ========================*/
1352 /*------------------------------------------------------------------*/
1354 /* Name - mono_arch_cpu_optimizations */
1356 /* Function - Returns the optimizations supported on this CPU */
1358 /*------------------------------------------------------------------*/
1361 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1365 /*----------------------------------------------------------*/
1366 /* No s390-specific optimizations yet */
1367 /*----------------------------------------------------------*/
1368 *exclude_mask = MONO_OPT_LINEARS;
1372 /*========================= End of Function ========================*/
1374 /*------------------------------------------------------------------*/
1376 /* Name - mono_arch_get_allocatable_int_vars */
1380 /*------------------------------------------------------------------*/
1383 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1388 for (i = 0; i < cfg->num_varinfo; i++) {
1389 MonoInst *ins = cfg->varinfo [i];
1390 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1393 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1396 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1397 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1400 /* we can only allocate 32 bit values */
1401 if (mono_is_regsize_var(ins->inst_vtype)) {
1402 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1403 g_assert (i == vmv->idx);
1404 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1411 /*========================= End of Function ========================*/
1413 /*------------------------------------------------------------------*/
1415 /* Name - mono_arch_global_int_regs */
1417 /* Function - Return a list of usable integer registers. */
1419 /*------------------------------------------------------------------*/
1422 mono_arch_get_global_int_regs (MonoCompile *cfg)
1425 MonoMethodHeader *header;
1428 header = cfg->header;
1429 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1430 cfg->frame_reg = s390_r11;
1433 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1435 for (i = 8; i < top; ++i) {
1436 if (cfg->frame_reg != i)
1437 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1443 /*========================= End of Function ========================*/
1445 /*------------------------------------------------------------------*/
1447 /* Name - mono_arch_flush_icache */
1449 /* Function - Flush the CPU icache. */
1451 /*------------------------------------------------------------------*/
1454 mono_arch_flush_icache (guint8 *code, gint size)
1458 /*========================= End of Function ========================*/
1460 /*------------------------------------------------------------------*/
1462 /* Name - add_general */
1464 /* Function - Determine code and stack size incremements for a */
1467 /*------------------------------------------------------------------*/
1470 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1472 if (*gr > S390_LAST_ARG_REG) {
1473 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1474 ainfo->offset = sz->stack_size;
1475 ainfo->reg = STK_BASE;
1476 ainfo->regtype = RegTypeBase;
1477 sz->stack_size += sizeof(long);
1478 sz->local_size += sizeof(long);
1479 sz->offStruct += sizeof(long);
1480 sz->code_size += 12;
1488 /*========================= End of Function ========================*/
1490 /*------------------------------------------------------------------*/
1492 /* Name - add_stackParm */
1494 /* Function - Determine code and stack size incremements for a */
1497 /*------------------------------------------------------------------*/
1500 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1502 if (*gr > S390_LAST_ARG_REG) {
1503 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1504 ainfo->reg = STK_BASE;
1505 ainfo->offset = sz->stack_size;
1506 ainfo->regtype = RegTypeStructByAddrOnStack;
1507 sz->stack_size += sizeof (gpointer);
1508 sz->parm_size += sizeof(gpointer);
1509 sz->offStruct += sizeof(gpointer);
1512 ainfo->offset = sz->stack_size;
1513 ainfo->regtype = RegTypeStructByAddr;
1516 ainfo->offparm = sz->offset;
1517 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1519 ainfo->vtsize = size;
1520 sz->parm_size += size;
1523 /*========================= End of Function ========================*/
1525 /*------------------------------------------------------------------*/
1527 /* Name - add_float */
1529 /* Function - Determine code and stack size incremements for a */
1530 /* float parameter. */
1532 /*------------------------------------------------------------------*/
1535 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1537 if ((*fr) <= S390_LAST_FPARG_REG) {
1538 ainfo->regtype = RegTypeFP;
1544 ainfo->offset = sz->stack_size;
1545 ainfo->reg = STK_BASE;
1546 ainfo->regtype = RegTypeBase;
1548 sz->stack_size += sizeof(double);
1549 sz->local_size += sizeof(double);
1550 sz->offStruct += sizeof(double);
1554 /*========================= End of Function ========================*/
1556 /*------------------------------------------------------------------*/
1558 /* Name - get_call_info */
1560 /* Function - Determine the amount of space required for code */
1561 /* and stack. In addition determine starting points */
1562 /* for stack-based parameters, and area for struct- */
1563 /* ures being returned on the stack. */
1565 /*------------------------------------------------------------------*/
1568 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1570 guint i, fr, gr, size, pstart;
1571 int nParm = sig->hasthis + sig->param_count;
1573 guint32 simpleType, align;
1574 gboolean is_pinvoke = sig->pinvoke;
1579 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1581 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1586 cinfo->struct_ret = 0;
1590 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1591 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1598 /*----------------------------------------------------------*/
1599 /* We determine the size of the return code/stack in case we*/
1600 /* need to reserve a register to be used to address a stack */
1601 /* area that the callee will use. */
1602 /*----------------------------------------------------------*/
1604 ret_type = mini_get_underlying_type (sig->ret);
1605 simpleType = ret_type->type;
1607 switch (simpleType) {
1608 case MONO_TYPE_BOOLEAN:
1613 case MONO_TYPE_CHAR:
1618 case MONO_TYPE_CLASS:
1619 case MONO_TYPE_OBJECT:
1620 case MONO_TYPE_SZARRAY:
1621 case MONO_TYPE_ARRAY:
1623 case MONO_TYPE_FNPTR:
1624 case MONO_TYPE_STRING:
1625 cinfo->ret.reg = s390_r2;
1630 cinfo->ret.reg = s390_f0;
1635 cinfo->ret.reg = s390_r2;
1638 case MONO_TYPE_GENERICINST:
1639 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1640 cinfo->ret.reg = s390_r2;
1645 case MONO_TYPE_VALUETYPE: {
1646 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1647 if (klass->enumtype) {
1648 simpleType = mono_class_enum_basetype (klass)->type;
1651 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1653 cinfo->struct_ret = 1;
1654 cinfo->ret.size = size;
1655 cinfo->ret.vtsize = size;
1658 case MONO_TYPE_TYPEDBYREF:
1659 size = sizeof (MonoTypedRef);
1660 cinfo->struct_ret = 1;
1661 cinfo->ret.size = size;
1662 cinfo->ret.vtsize = size;
1664 case MONO_TYPE_VOID:
1667 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1673 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1674 * the first argument, allowing 'this' to be always passed in the first arg reg.
1675 * Also do this if the first argument is a reference type, since virtual calls
1676 * are sometimes made using calli without sig->hasthis set, like in the delegate
1679 if (cinfo->struct_ret && !is_pinvoke &&
1681 (sig->param_count > 0 &&
1682 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1684 cinfo->args[nParm].size = sizeof (gpointer);
1685 add_general (&gr, sz, cinfo->args + nParm);
1687 cinfo->args[nParm].size = sizeof (gpointer);
1688 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1692 cinfo->vret_arg_index = 1;
1693 cinfo->ret.reg = gr;
1698 cinfo->args[nParm].size = sizeof (gpointer);
1699 add_general (&gr, sz, cinfo->args + nParm);
1703 if (cinfo->struct_ret) {
1704 cinfo->ret.reg = gr;
1709 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1710 gr = S390_LAST_ARG_REG + 1;
1711 fr = S390_LAST_FPARG_REG + 1;
1713 /* Emit the signature cookie just before the implicit arguments */
1714 add_general (&gr, sz, &cinfo->sigCookie);
1717 /*----------------------------------------------------------*/
1718 /* We determine the size of the parameter code and stack */
1719 /* requirements by checking the types and sizes of the */
1721 /*----------------------------------------------------------*/
1723 for (i = pstart; i < sig->param_count; ++i) {
1726 /*--------------------------------------------------*/
1727 /* Handle vararg type calls. All args are put on */
1729 /*--------------------------------------------------*/
1730 if ((sig->call_convention == MONO_CALL_VARARG) &&
1731 (i == sig->sentinelpos)) {
1732 gr = S390_LAST_ARG_REG + 1;
1733 fr = S390_LAST_FPARG_REG + 1;
1734 add_general (&gr, sz, &cinfo->sigCookie);
1737 if (sig->params [i]->byref) {
1738 add_general (&gr, sz, cinfo->args+nParm);
1739 cinfo->args[nParm].size = sizeof(gpointer);
1744 ptype = mini_get_underlying_type (sig->params [i]);
1745 simpleType = ptype->type;
1746 cinfo->args[nParm].type = simpleType;
1747 switch (simpleType) {
1748 case MONO_TYPE_BOOLEAN:
1751 cinfo->args[nParm].size = sizeof(char);
1752 add_general (&gr, sz, cinfo->args+nParm);
1757 case MONO_TYPE_CHAR:
1758 cinfo->args[nParm].size = sizeof(short);
1759 add_general (&gr, sz, cinfo->args+nParm);
1764 cinfo->args[nParm].size = sizeof(int);
1765 add_general (&gr, sz, cinfo->args+nParm);
1771 case MONO_TYPE_FNPTR:
1772 case MONO_TYPE_CLASS:
1773 case MONO_TYPE_OBJECT:
1774 case MONO_TYPE_STRING:
1775 case MONO_TYPE_SZARRAY:
1776 case MONO_TYPE_ARRAY:
1777 cinfo->args[nParm].size = sizeof(gpointer);
1778 add_general (&gr, sz, cinfo->args+nParm);
1783 cinfo->args[nParm].size = sizeof(long long);
1784 add_general (&gr, sz, cinfo->args+nParm);
1788 cinfo->args[nParm].size = sizeof(float);
1789 add_float (&fr, sz, cinfo->args+nParm);
1793 cinfo->args[nParm].size = sizeof(double);
1794 add_float (&fr, sz, cinfo->args+nParm);
1797 case MONO_TYPE_GENERICINST:
1798 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1799 cinfo->args[nParm].size = sizeof(gpointer);
1800 add_general (&gr, sz, cinfo->args+nParm);
1805 case MONO_TYPE_VALUETYPE: {
1806 MonoMarshalType *info;
1807 MonoClass *klass = mono_class_from_mono_type (ptype);
1810 size = mono_class_native_size(klass, NULL);
1812 size = mono_class_value_size(klass, NULL);
1814 if (simpleType != MONO_TYPE_GENERICINST) {
1815 info = mono_marshal_load_type_info(klass);
1817 if ((info->native_size == sizeof(float)) &&
1818 (info->num_fields == 1) &&
1819 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1820 cinfo->args[nParm].size = sizeof(float);
1821 add_float(&fr, sz, cinfo->args+nParm);
1826 if ((info->native_size == sizeof(double)) &&
1827 (info->num_fields == 1) &&
1828 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1829 cinfo->args[nParm].size = sizeof(double);
1830 add_float(&fr, sz, cinfo->args+nParm);
1836 cinfo->args[nParm].vtsize = 0;
1837 cinfo->args[nParm].size = 0;
1840 /*----------------------------------*/
1841 /* On S/390, structures of size 1, */
1842 /* 2, 4, and 8 bytes are passed in */
1843 /* (a) register(s). */
1844 /*----------------------------------*/
1850 add_general(&gr, sz, cinfo->args+nParm);
1851 cinfo->args[nParm].size = size;
1852 cinfo->args[nParm].regtype = RegTypeStructByVal;
1854 sz->local_size += sizeof(long);
1857 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1862 case MONO_TYPE_TYPEDBYREF: {
1863 int size = sizeof (MonoTypedRef);
1865 cinfo->args[nParm].vtsize = 0;
1866 cinfo->args[nParm].size = 0;
1869 /*----------------------------------*/
1870 /* On S/390, structures of size 1, */
1871 /* 2, 4, and 8 bytes are passed in */
1872 /* (a) register(s). */
1873 /*----------------------------------*/
1879 add_general(&gr, sz, cinfo->args+nParm);
1880 cinfo->args[nParm].size = size;
1881 cinfo->args[nParm].regtype = RegTypeStructByVal;
1883 sz->local_size += sizeof(long);
1886 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1892 g_error ("Can't trampoline 0x%x", ptype);
1896 /*----------------------------------------------------------*/
1897 /* Handle the case where there are no implicit arguments */
1898 /*----------------------------------------------------------*/
1899 if ((sig->call_convention == MONO_CALL_VARARG) &&
1902 (sig->param_count == sig->sentinelpos)) {
1903 gr = S390_LAST_ARG_REG + 1;
1904 fr = S390_LAST_FPARG_REG + 1;
1905 add_general (&gr, sz, &cinfo->sigCookie);
1908 /*----------------------------------------------------------*/
1909 /* If we are passing a structure back then if it won't be */
1910 /* in a register(s) then we make room at the end of the */
1911 /* parameters that may have been placed on the stack */
1912 /*----------------------------------------------------------*/
1913 if (cinfo->struct_ret) {
1914 cinfo->ret.offset = sz->stack_size;
1915 switch (cinfo->ret.size) {
1923 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1928 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1930 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1935 /*========================= End of Function ========================*/
1937 /*------------------------------------------------------------------*/
1939 /* Name - mono_arch_allocate_vars */
1941 /* Function - Set var information according to the calling */
1942 /* convention for S/390. The local var stuff should */
1943 /* most likely be split in another method. */
1945 /* Parameter - @m - Compile unit. */
1947 /*------------------------------------------------------------------*/
1950 mono_arch_allocate_vars (MonoCompile *cfg)
1952 MonoMethodSignature *sig;
1953 MonoMethodHeader *header;
1956 int iParm, iVar, offset, align, size, curinst;
1957 int frame_reg = STK_BASE;
1960 header = cfg->header;
1962 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1964 /*---------------------------------------------------------*/
1965 /* We use the frame register also for any method that has */
1966 /* filter clauses. This way, when the handlers are called, */
1967 /* the code will reference local variables using the frame */
1968 /* reg instead of the stack pointer: if we had to restore */
1969 /* the stack pointer, we'd corrupt the method frames that */
1970 /* are already on the stack (since filters get called */
1971 /* before stack unwinding happens) when the filter code */
1972 /* would call any method. */
1973 /*---------------------------------------------------------*/
1974 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1975 frame_reg = s390_r11;
1977 cfg->frame_reg = frame_reg;
1979 cfg->arch.bkchain_reg = -1;
1981 if (frame_reg != STK_BASE)
1982 cfg->used_int_regs |= (1 << frame_reg);
1984 if (cfg->uses_rgctx_reg)
1985 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1987 sig = mono_method_signature (cfg->method);
1989 cinfo = get_call_info (cfg, cfg->mempool, sig);
1991 if (!cinfo->struct_ret) {
1992 switch (mini_get_underlying_type (sig->ret)->type) {
1993 case MONO_TYPE_VOID:
1996 cfg->ret->opcode = OP_REGVAR;
1997 cfg->ret->dreg = s390_r2;
2002 /*--------------------------------------------------------------*/
2003 /* local vars are at a positive offset from the stack pointer */
2004 /* also note that if the function uses alloca, we use s390_r11 */
2005 /* to point at the local variables. */
2006 /* add parameter area size for called functions */
2007 /*--------------------------------------------------------------*/
2008 if (cfg->param_area == 0)
2009 offset = S390_MINIMAL_STACK_SIZE;
2011 offset = cfg->param_area;
2013 cfg->sig_cookie = 0;
2015 if (cinfo->struct_ret) {
2016 inst = cfg->vret_addr;
2017 offset = S390_ALIGN(offset, sizeof(gpointer));
2018 inst->inst_offset = offset;
2019 inst->opcode = OP_REGOFFSET;
2020 inst->inst_basereg = frame_reg;
2021 offset += sizeof(gpointer);
2022 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2023 printf ("vret_addr =");
2024 mono_print_ins (cfg->vret_addr);
2029 inst = cfg->args [0];
2030 if (inst->opcode != OP_REGVAR) {
2031 inst->opcode = OP_REGOFFSET;
2032 inst->inst_basereg = frame_reg;
2033 offset = S390_ALIGN(offset, sizeof(gpointer));
2034 inst->inst_offset = offset;
2035 offset += sizeof (gpointer);
2042 eArg = sig->param_count + sArg;
2044 if (sig->call_convention == MONO_CALL_VARARG)
2045 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2047 for (iParm = sArg; iParm < eArg; ++iParm) {
2048 inst = cfg->args [curinst];
2049 if (inst->opcode != OP_REGVAR) {
2050 switch (cinfo->args[iParm].regtype) {
2051 case RegTypeStructByAddr : {
2054 size = sizeof (gpointer);
2056 inst->opcode = OP_REGOFFSET;
2057 inst->inst_basereg = frame_reg;
2058 offset = S390_ALIGN (offset, sizeof (gpointer));
2059 inst->inst_offset = offset;
2061 /* Add a level of indirection */
2062 MONO_INST_NEW (cfg, indir, 0);
2064 inst->opcode = OP_VTARG_ADDR;
2065 inst->inst_left = indir;
2068 case RegTypeStructByAddrOnStack : {
2071 size = sizeof (gpointer);
2073 /* Similar to the == STK_BASE case below */
2074 cfg->arch.bkchain_reg = s390_r12;
2075 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2077 inst->opcode = OP_REGOFFSET;
2078 inst->dreg = mono_alloc_preg (cfg);
2079 inst->inst_basereg = cfg->arch.bkchain_reg;
2080 inst->inst_offset = cinfo->args [iParm].offset;
2082 /* Add a level of indirection */
2083 MONO_INST_NEW (cfg, indir, 0);
2085 inst->opcode = OP_VTARG_ADDR;
2086 inst->inst_left = indir;
2089 case RegTypeStructByVal :
2090 size = cinfo->args[iParm].size;
2091 offset = S390_ALIGN(offset, size);
2092 inst->opcode = OP_REGOFFSET;
2093 inst->inst_basereg = frame_reg;
2094 inst->inst_offset = offset;
2097 if (cinfo->args [iParm].reg == STK_BASE) {
2099 * These arguments are in the previous frame, so we can't
2100 * compute their offset from the current frame pointer right
2101 * now, since cfg->stack_offset is not yet known, so dedicate a
2102 * register holding the previous frame pointer.
2104 cfg->arch.bkchain_reg = s390_r12;
2105 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2107 inst->opcode = OP_REGOFFSET;
2108 inst->inst_basereg = cfg->arch.bkchain_reg;
2109 size = (cinfo->args[iParm].size < 8
2110 ? 8 - cinfo->args[iParm].size
2112 inst->inst_offset = cinfo->args [iParm].offset + size;
2113 size = sizeof (long);
2115 inst->opcode = OP_REGOFFSET;
2116 inst->inst_basereg = frame_reg;
2117 size = (cinfo->args[iParm].size < 8
2120 offset = S390_ALIGN(offset, size);
2121 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2122 inst->inst_offset = offset;
2124 inst->inst_offset = offset + (8 - size);
2129 if ((sig->call_convention == MONO_CALL_VARARG) &&
2130 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2131 (iParm < sig->sentinelpos))
2132 cfg->sig_cookie += size;
2133 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2136 offset += MAX(size, 8);
2141 cfg->locals_min_stack_offset = offset;
2143 curinst = cfg->locals_start;
2144 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2145 inst = cfg->varinfo [iVar];
2146 if ((inst->flags & MONO_INST_IS_DEAD) ||
2147 (inst->opcode == OP_REGVAR))
2150 /*--------------------------------------------------*/
2151 /* inst->backend.is_pinvoke indicates native sized */
2152 /* value typs this is used by the pinvoke wrappers */
2153 /* when they call functions returning structure */
2154 /*--------------------------------------------------*/
2155 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2156 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2157 (guint32 *) &align);
2159 size = mono_type_size (inst->inst_vtype, &align);
2161 offset = S390_ALIGN(offset, align);
2162 inst->inst_offset = offset;
2163 inst->opcode = OP_REGOFFSET;
2164 inst->inst_basereg = frame_reg;
2166 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2167 iVar, inst->inst_offset, size));
2170 cfg->locals_max_stack_offset = offset;
2172 /*------------------------------------------------------*/
2173 /* Allow space for the trace method stack area if needed*/
2174 /*------------------------------------------------------*/
2175 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2176 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2177 offset += S390_TRACE_STACK_SIZE;
2179 /*------------------------------------------------------*/
2180 /* Reserve space to save LMF and caller saved registers */
2181 /*------------------------------------------------------*/
2182 if (cfg->method->save_lmf)
2183 offset += sizeof (MonoLMF);
2185 /*------------------------------------------------------*/
2186 /* align the offset */
2187 /*------------------------------------------------------*/
2188 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2190 /*------------------------------------------------------*/
2191 /* Fix offsets for args whose value is in parent frame */
2192 /*------------------------------------------------------*/
2193 for (iParm = sArg; iParm < eArg; ++iParm) {
2194 inst = cfg->args [iParm];
2196 if (inst->opcode == OP_S390_STKARG) {
2197 inst->opcode = OP_REGOFFSET;
2198 inst->inst_offset += cfg->stack_offset;
2203 /*========================= End of Function ========================*/
2205 /*------------------------------------------------------------------*/
2207 /* Name - mono_arch_create_vars */
2209 /*------------------------------------------------------------------*/
2212 mono_arch_create_vars (MonoCompile *cfg)
2214 MonoMethodSignature *sig;
2217 sig = mono_method_signature (cfg->method);
2219 cinfo = get_call_info (cfg, cfg->mempool, sig);
2221 if (cinfo->struct_ret) {
2222 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2223 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2224 printf ("vret_addr = ");
2225 mono_print_ins (cfg->vret_addr);
2230 /*========================= End of Function ========================*/
2232 /*------------------------------------------------------------------*/
2234 /* Name - add_outarg_reg2. */
2236 /*------------------------------------------------------------------*/
2239 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2244 case RegTypeGeneral:
2245 MONO_INST_NEW (cfg, ins, OP_MOVE);
2246 ins->dreg = mono_alloc_ireg (cfg);
2247 ins->sreg1 = tree->dreg;
2248 MONO_ADD_INS (cfg->cbb, ins);
2249 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2252 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2253 ins->dreg = mono_alloc_freg (cfg);
2254 ins->sreg1 = tree->dreg;
2255 MONO_ADD_INS (cfg->cbb, ins);
2256 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2259 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2260 ins->dreg = mono_alloc_freg (cfg);
2261 ins->sreg1 = tree->dreg;
2262 MONO_ADD_INS (cfg->cbb, ins);
2263 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2266 g_assert_not_reached ();
2270 /*========================= End of Function ========================*/
2272 /*------------------------------------------------------------------*/
2274 /* Name - emit_sig_cookie. */
2276 /*------------------------------------------------------------------*/
2279 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2281 MonoMethodSignature *tmpSig;
2284 cfg->disable_aot = TRUE;
2286 /*----------------------------------------------------------*/
2287 /* mono_ArgIterator_Setup assumes the signature cookie is */
2288 /* passed first and all the arguments which were before it */
2289 /* passed on the stack after the signature. So compensate */
2290 /* by passing a different signature. */
2291 /*----------------------------------------------------------*/
2292 tmpSig = mono_metadata_signature_dup (call->signature);
2293 tmpSig->param_count -= call->signature->sentinelpos;
2294 tmpSig->sentinelpos = 0;
2295 if (tmpSig->param_count > 0)
2296 memcpy (tmpSig->params,
2297 call->signature->params + call->signature->sentinelpos,
2298 tmpSig->param_count * sizeof(MonoType *));
2300 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2301 sig_arg->dreg = mono_alloc_ireg (cfg);
2302 sig_arg->inst_p0 = tmpSig;
2303 MONO_ADD_INS (cfg->cbb, sig_arg);
2305 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2306 cinfo->sigCookie.offset, sig_arg->dreg);
2309 /*========================= End of Function ========================*/
2311 /*------------------------------------------------------------------*/
2313 /* Name - mono_arch_emit_call */
2315 /*------------------------------------------------------------------*/
2318 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2321 MonoMethodSignature *sig;
2323 int i, n, lParamArea;
2325 ArgInfo *ainfo = NULL;
2327 MonoMethodHeader *header;
2330 sig = call->signature;
2331 n = sig->param_count + sig->hasthis;
2332 DEBUG (g_print ("Call requires: %d parameters\n",n));
2334 cinfo = get_call_info (cfg, cfg->mempool, sig);
2336 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2337 cinfo->sz.parm_size + cinfo->sz.offset;
2338 call->stack_usage = MAX(stackSize, call->stack_usage);
2339 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2340 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2341 cfg->flags |= MONO_CFG_HAS_CALLS;
2343 if (cinfo->struct_ret) {
2344 MONO_INST_NEW (cfg, ins, OP_MOVE);
2345 ins->sreg1 = call->vret_var->dreg;
2346 ins->dreg = mono_alloc_preg (cfg);
2347 MONO_ADD_INS (cfg->cbb, ins);
2348 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2351 header = cfg->header;
2352 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2357 for (i = 0; i < n; ++i) {
2360 ainfo = cinfo->args + i;
2361 if (i >= sig->hasthis)
2362 t = sig->params [i - sig->hasthis];
2364 t = &mono_defaults.int_class->byval_arg;
2365 t = mini_get_underlying_type (t);
2367 in = call->args [i];
2369 if ((sig->call_convention == MONO_CALL_VARARG) &&
2371 (i == sig->sentinelpos)) {
2372 emit_sig_cookie (cfg, call, cinfo);
2375 switch (ainfo->regtype) {
2376 case RegTypeGeneral:
2377 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2380 if (MONO_TYPE_ISSTRUCT (t)) {
2381 /* Valuetype passed in one fp register */
2382 ainfo->regtype = RegTypeStructByValInFP;
2385 if (ainfo->size == 4)
2386 ainfo->regtype = RegTypeFPR4;
2387 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2390 case RegTypeStructByVal:
2391 case RegTypeStructByAddr:
2392 case RegTypeStructByAddrOnStack: {
2396 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2397 size = sizeof (MonoTypedRef);
2398 align = sizeof (gpointer);
2402 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2405 * Other backends use mono_type_stack_size (), but that
2406 * aligns the size to 8, which is larger than the size of
2407 * the source, leading to reads of invalid memory if the
2408 * source is at the end of address space.
2410 size = mono_class_value_size (in->klass, &align);
2413 g_assert (in->klass);
2415 ainfo->offparm += cinfo->sz.offStruct;
2417 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2418 ins->sreg1 = in->dreg;
2419 ins->klass = in->klass;
2420 ins->backend.size = ainfo->size;
2421 ins->inst_p0 = call;
2422 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2423 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2425 MONO_ADD_INS (cfg->cbb, ins);
2427 if (ainfo->regtype == RegTypeStructByAddr) {
2429 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2430 * use the normal OUTARG opcodes to pass the address of the location to
2433 int treg = mono_alloc_preg (cfg);
2434 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2435 frmReg, ainfo->offparm);
2436 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2437 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2438 /* The address of the valuetype is passed on the stack */
2439 int treg = mono_alloc_preg (cfg);
2440 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2441 frmReg, ainfo->offparm);
2442 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2443 ainfo->reg, ainfo->offset, treg);
2445 if (cfg->compute_gc_maps) {
2448 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2454 if (!t->byref && t->type == MONO_TYPE_R4) {
2455 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2456 STK_BASE, ainfo->offset + 4,
2458 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2459 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2460 STK_BASE, ainfo->offset,
2463 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2464 ins->inst_destbasereg = STK_BASE;
2465 ins->inst_offset = ainfo->offset;
2466 ins->sreg1 = in->dreg;
2469 /* This is needed by MonoTypedRef->value to point to the correct data */
2470 if ((sig->call_convention == MONO_CALL_VARARG) &&
2471 (i >= sig->sentinelpos)) {
2472 switch (ainfo->size) {
2474 ins->opcode = OP_STOREI1_MEMBASE_REG;
2477 ins->opcode = OP_STOREI2_MEMBASE_REG;
2480 ins->opcode = OP_STOREI4_MEMBASE_REG;
2488 MONO_ADD_INS (cfg->cbb, ins);
2492 g_assert_not_reached ();
2498 * Handle the case where there are no implicit arguments
2500 if ((sig->call_convention == MONO_CALL_VARARG) &&
2502 (i == sig->sentinelpos)) {
2503 emit_sig_cookie (cfg, call, cinfo);
2507 /*========================= End of Function ========================*/
2509 /*------------------------------------------------------------------*/
2511 /* Name - mono_arch_emit_outarg_vt */
2513 /*------------------------------------------------------------------*/
2516 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2518 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2519 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2520 int size = ins->backend.size;
2522 if (ainfo->regtype == RegTypeStructByVal) {
2524 arg->ins.sreg1 = ainfo->reg;
2525 arg->ins.opcode = OP_OUTARG_VT;
2526 arg->size = ainfo->size;
2527 arg->offset = ainfo->offset;
2528 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2530 if (ainfo->reg != STK_BASE) {
2531 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2533 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2536 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2537 int dreg = mono_alloc_freg (cfg);
2539 if (ainfo->size == 4) {
2540 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2541 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2543 g_assert (ainfo->size == 8);
2545 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2548 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2551 MonoMethodHeader *header;
2554 header = mono_method_get_header_checked (cfg->method, &error);
2555 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2556 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2561 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2562 src->dreg, 0, size);
2564 if (cfg->compute_gc_maps) {
2567 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2572 /*========================= End of Function ========================*/
2574 /*------------------------------------------------------------------*/
2576 /* Name - mono_arch_emit_setret */
2578 /*------------------------------------------------------------------*/
2581 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2583 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2586 if (ret->type == MONO_TYPE_R4) {
2587 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2589 } else if (ret->type == MONO_TYPE_R8) {
2590 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2595 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2598 /*========================= End of Function ========================*/
2600 /*------------------------------------------------------------------*/
2602 /* Name - mono_arch_instrument_mem_needs */
2604 /* Function - Allow tracing to work with this interface (with */
2605 /* an optional argument). */
2607 /*------------------------------------------------------------------*/
2610 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2612 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2614 /* split prolog-epilog requirements? */
2615 *code = 50; /* max bytes needed: check this number */
2618 /*========================= End of Function ========================*/
2620 /*------------------------------------------------------------------*/
2622 /* Name - mono_arch_instrument_prolog */
2624 /* Function - Create an "instrumented" prolog. */
2626 /*------------------------------------------------------------------*/
2629 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2630 gboolean enable_arguments)
2637 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2638 if (cfg->method->save_lmf)
2639 parmOffset -= sizeof(MonoLMF);
2640 fpOffset = parmOffset + (5*sizeof(gpointer));
2643 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2644 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2645 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2646 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2647 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2648 S390_SET (code, s390_r1, func);
2649 S390_SET (code, s390_r2, cfg->method);
2650 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2651 s390_lgr (code, s390_r4, STK_BASE);
2652 s390_aghi (code, s390_r4, cfg->stack_usage);
2653 s390_basr (code, s390_r14, s390_r1);
2654 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2655 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2656 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2657 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2658 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2663 /*========================= End of Function ========================*/
2665 /*------------------------------------------------------------------*/
2667 /* Name - mono_arch_instrument_epilog */
2669 /* Function - Create an epilog that will handle the returned */
2670 /* values used in instrumentation. */
2672 /*------------------------------------------------------------------*/
2675 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2678 int save_mode = SAVE_NONE,
2681 MonoMethod *method = cfg->method;
2682 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2684 offset = code - cfg->native_code;
2685 /*-----------------------------------------*/
2686 /* We need about 128 bytes of instructions */
2687 /*-----------------------------------------*/
2688 if (offset > (cfg->code_size - 128)) {
2689 cfg->code_size *= 2;
2690 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2691 code = cfg->native_code + offset;
2694 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2695 if (method->save_lmf)
2696 saveOffset -= sizeof(MonoLMF);
2700 case MONO_TYPE_VOID:
2701 /* special case string .ctor icall */
2702 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2703 save_mode = SAVE_ONE;
2705 save_mode = SAVE_NONE;
2709 save_mode = SAVE_ONE;
2712 save_mode = SAVE_R4;
2715 save_mode = SAVE_R8;
2717 case MONO_TYPE_VALUETYPE:
2718 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2719 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2722 save_mode = SAVE_STRUCT;
2725 save_mode = SAVE_ONE;
2729 switch (save_mode) {
2731 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2732 if (enable_arguments) {
2733 s390_lgr (code, s390_r3, s390_r2);
2737 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2738 if (enable_arguments) {
2739 s390_ldebr (code, s390_f0, s390_f0);
2743 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2746 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2747 if (enable_arguments) {
2748 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2749 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2757 S390_SET (code, s390_r1, func);
2758 S390_SET (code, s390_r2, cfg->method);
2759 s390_basr (code, s390_r14, s390_r1);
2761 switch (save_mode) {
2763 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2767 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2770 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2780 /*========================= End of Function ========================*/
2782 /*------------------------------------------------------------------*/
2784 /* Name - mono_arch_peephole_pass_1 */
2786 /* Function - Form a peephole pass at the code looking for */
2787 /* simple optimizations. */
2789 /*------------------------------------------------------------------*/
2792 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2796 /*========================= End of Function ========================*/
2798 /*------------------------------------------------------------------*/
2800 /* Name - mono_arch_peephole_pass_2 */
2802 /* Function - Form a peephole pass at the code looking for */
2803 /* simple optimizations. */
2805 /*------------------------------------------------------------------*/
2808 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2812 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2813 mono_peephole_ins (bb, ins);
2817 /*========================= End of Function ========================*/
2819 /*------------------------------------------------------------------*/
2821 /* Name - mono_arch_lowering_pass. */
2823 /*------------------------------------------------------------------*/
2826 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2828 MonoInst *ins, *next;
2830 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2831 switch (ins->opcode) {
2836 case OP_IDIV_UN_IMM:
2837 case OP_IREM_UN_IMM:
2842 case OP_LOCALLOC_IMM:
2843 mono_decompose_op_imm (cfg, bb, ins);
2846 if (!s390_is_imm16 (ins->inst_imm))
2847 /* This is created by the memcpy code which ignores is_inst_imm */
2848 mono_decompose_op_imm (cfg, bb, ins);
2855 bb->max_vreg = cfg->next_vreg;
2858 /*========================= End of Function ========================*/
2860 /*------------------------------------------------------------------*/
2862 /* Name - emit_float_to_int */
2864 /* Function - Create instructions which will convert a floating */
2865 /* point value to integer. */
2867 /*------------------------------------------------------------------*/
2870 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2872 /* sreg is a float, dreg is an integer reg. */
2874 s390_cgdbr (code, dreg, 5, sreg);
2877 s390_ltgr (code, dreg, dreg);
2879 s390_oill (code, dreg, 0x80);
2880 s390_lghi (code, s390_r0, 0xff);
2881 s390_ngr (code, dreg, s390_r0);
2884 s390_ltgr (code, dreg, dreg);
2886 s390_oill (code, dreg, 0x8000);
2887 s390_llill(code, s390_r0, 0xffff);
2888 s390_ngr (code, dreg, s390_r0);
2893 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2894 s390_ldgr (code, s390_f14, s390_r13);
2895 s390_ldr (code, s390_f15, sreg);
2896 s390_cdbr (code, s390_f15, s390_f14);
2897 s390_jl (code, 0); CODEPTR (code, o[0]);
2898 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2899 s390_ldgr (code, s390_f14, s390_r13);
2900 s390_sdbr (code, s390_f15, s390_f14);
2901 s390_cfdbr (code, dreg, 7, s390_f15);
2903 PTRSLOT (code, o[0]);
2904 s390_cfdbr (code, dreg, 5, sreg);
2907 s390_lghi (code, s390_r0, 0xff);
2908 s390_ngr (code, dreg, s390_r0);
2911 s390_llill(code, s390_r0, 0xffff);
2912 s390_ngr (code, dreg, s390_r0);
2919 /*========================= End of Function ========================*/
2921 /*------------------------------------------------------------------*/
2923 /* Name - gboolean_is_unsigned. */
2925 /* Function - Return TRUE if next opcode is checking for un- */
2928 /*------------------------------------------------------------------*/
2931 gboolean is_unsigned (MonoInst *next)
2934 (((next->opcode >= OP_IBNE_UN) &&
2935 (next->opcode <= OP_IBLT_UN)) ||
2936 ((next->opcode >= OP_LBNE_UN) &&
2937 (next->opcode <= OP_LBLT_UN)) ||
2938 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2939 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2940 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2941 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2942 ((next->opcode == OP_CLT_UN) ||
2943 (next->opcode == OP_CGT_UN)) ||
2944 ((next->opcode == OP_ICLT_UN) ||
2945 (next->opcode == OP_ICGT_UN) ||
2946 (next->opcode == OP_LCLT_UN) ||
2947 (next->opcode == OP_LCGT_UN))))
2953 /*========================= End of Function ========================*/
2955 /*------------------------------------------------------------------*/
2957 /* Name - mono_arch_output_basic_block */
2959 /* Function - Perform the "real" work of emitting instructions */
2960 /* that will do the work of in the basic block. */
2962 /*------------------------------------------------------------------*/
2965 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2970 guint8 *code = cfg->native_code + cfg->code_len;
2971 guint last_offset = 0;
2974 /* we don't align basic blocks of loops on s390 */
2976 if (cfg->verbose_level > 2)
2977 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2979 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2980 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2981 g_assert (!mono_compile_aot);
2982 cov->data [bb->dfn].cil_code = bb->cil_code;
2983 /* This is not thread save, but good enough */
2984 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2985 s390_alsi (code, 0, s390_r1, 1);
2988 MONO_BB_FOR_EACH_INS (bb, ins) {
2989 offset = code - cfg->native_code;
2991 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
2993 if (offset > (cfg->code_size - max_len - 16)) {
2994 cfg->code_size *= 2;
2995 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2996 code = cfg->native_code + offset;
2999 mono_debug_record_line_number (cfg, ins, offset);
3001 switch (ins->opcode) {
3002 case OP_STOREI1_MEMBASE_IMM: {
3003 s390_lghi (code, s390_r0, ins->inst_imm);
3004 S390_LONG (code, stcy, stc, s390_r0, 0,
3005 ins->inst_destbasereg, ins->inst_offset);
3008 case OP_STOREI2_MEMBASE_IMM: {
3009 s390_lghi (code, s390_r0, ins->inst_imm);
3010 S390_LONG (code, sthy, sth, s390_r0, 0,
3011 ins->inst_destbasereg, ins->inst_offset);
3014 case OP_STOREI4_MEMBASE_IMM: {
3015 s390_lgfi (code, s390_r0, ins->inst_imm);
3016 S390_LONG (code, sty, st, s390_r0, 0,
3017 ins->inst_destbasereg, ins->inst_offset);
3020 case OP_STORE_MEMBASE_IMM:
3021 case OP_STOREI8_MEMBASE_IMM: {
3022 S390_SET (code, s390_r0, ins->inst_imm);
3023 S390_LONG (code, stg, stg, s390_r0, 0,
3024 ins->inst_destbasereg, ins->inst_offset);
3027 case OP_STOREI1_MEMBASE_REG: {
3028 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3029 ins->inst_destbasereg, ins->inst_offset);
3032 case OP_STOREI2_MEMBASE_REG: {
3033 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3034 ins->inst_destbasereg, ins->inst_offset);
3037 case OP_STOREI4_MEMBASE_REG: {
3038 S390_LONG (code, sty, st, ins->sreg1, 0,
3039 ins->inst_destbasereg, ins->inst_offset);
3042 case OP_STORE_MEMBASE_REG:
3043 case OP_STOREI8_MEMBASE_REG: {
3044 S390_LONG (code, stg, stg, ins->sreg1, 0,
3045 ins->inst_destbasereg, ins->inst_offset);
3049 g_assert_not_reached ();
3051 case OP_LOAD_MEMBASE:
3052 case OP_LOADI8_MEMBASE: {
3053 S390_LONG (code, lg, lg, ins->dreg, 0,
3054 ins->inst_basereg, ins->inst_offset);
3057 case OP_LOADI4_MEMBASE: {
3058 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3059 ins->inst_basereg, ins->inst_offset);
3062 case OP_LOADU4_MEMBASE: {
3063 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3064 ins->inst_basereg, ins->inst_offset);
3067 case OP_LOADU1_MEMBASE: {
3068 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3069 ins->inst_basereg, ins->inst_offset);
3072 case OP_LOADI1_MEMBASE: {
3073 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3074 ins->inst_basereg, ins->inst_offset);
3077 case OP_LOADU2_MEMBASE: {
3078 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3079 ins->inst_basereg, ins->inst_offset);
3082 case OP_LOADI2_MEMBASE: {
3083 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3084 ins->inst_basereg, ins->inst_offset);
3087 case OP_LCONV_TO_I1: {
3088 s390_lgbr (code, ins->dreg, ins->sreg1);
3091 case OP_LCONV_TO_I2: {
3092 s390_lghr (code, ins->dreg, ins->sreg1);
3095 case OP_LCONV_TO_U1: {
3096 s390_llgcr (code, ins->dreg, ins->sreg1);
3099 case OP_LCONV_TO_U2: {
3100 s390_llghr (code, ins->dreg, ins->sreg1);
3103 case OP_ICONV_TO_I1: {
3104 s390_lgbr (code, ins->dreg, ins->sreg1);
3107 case OP_ICONV_TO_I2: {
3108 s390_lghr (code, ins->dreg, ins->sreg1);
3111 case OP_ICONV_TO_U1: {
3112 s390_llgcr (code, ins->dreg, ins->sreg1);
3115 case OP_ICONV_TO_U2: {
3116 s390_llghr (code, ins->dreg, ins->sreg1);
3121 if (is_unsigned (ins->next))
3122 s390_clgr (code, ins->sreg1, ins->sreg2);
3124 s390_cgr (code, ins->sreg1, ins->sreg2);
3128 if (is_unsigned (ins->next))
3129 s390_clr (code, ins->sreg1, ins->sreg2);
3131 s390_cr (code, ins->sreg1, ins->sreg2);
3134 case OP_COMPARE_IMM:
3135 case OP_LCOMPARE_IMM: {
3136 S390_SET (code, s390_r0, ins->inst_imm);
3137 if (is_unsigned (ins->next))
3138 s390_clgr (code, ins->sreg1, s390_r0);
3140 s390_cgr (code, ins->sreg1, s390_r0);
3143 case OP_ICOMPARE_IMM: {
3144 S390_SET (code, s390_r0, ins->inst_imm);
3145 if (is_unsigned (ins->next))
3146 s390_clr (code, ins->sreg1, s390_r0);
3148 s390_cr (code, ins->sreg1, s390_r0);
3152 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3154 S390_CALL_TEMPLATE (code, s390_r14);
3159 s390_agr (code, ins->dreg, src2);
3164 s390_agr (code, ins->dreg, src2);
3169 s390_alcgr (code, ins->dreg, src2);
3173 if (ins->dreg != ins->sreg1) {
3174 s390_lgr (code, ins->dreg, ins->sreg1);
3176 if (s390_is_imm16 (ins->inst_imm)) {
3177 s390_aghi (code, ins->dreg, ins->inst_imm);
3178 } else if (s390_is_imm32 (ins->inst_imm)) {
3179 s390_agfi (code, ins->dreg, ins->inst_imm);
3181 S390_SET (code, s390_r0, ins->inst_imm);
3182 s390_agr (code, ins->dreg, s390_r0);
3187 if (ins->dreg != ins->sreg1) {
3188 s390_lgr (code, ins->dreg, ins->sreg1);
3190 g_assert (s390_is_imm16 (ins->inst_imm));
3191 s390_aghi (code, ins->dreg, ins->inst_imm);
3195 if (ins->dreg != ins->sreg1) {
3196 s390_lgr (code, ins->dreg, ins->sreg1);
3198 if (s390_is_imm16 (ins->inst_imm)) {
3199 s390_lghi (code, s390_r0, ins->inst_imm);
3200 s390_alcgr (code, ins->dreg, s390_r0);
3202 S390_SET (code, s390_r0, ins->inst_imm);
3203 s390_alcgr (code, ins->dreg, s390_r0);
3208 case OP_S390_IADD_OVF: {
3210 s390_ar (code, ins->dreg, src2);
3211 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3212 s390_lgfr (code, ins->dreg, ins->dreg);
3215 case OP_IADD_OVF_UN:
3216 case OP_S390_IADD_OVF_UN: {
3218 s390_algr (code, ins->dreg, src2);
3219 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3220 s390_llgfr (code, ins->dreg, ins->dreg);
3223 case OP_ADD_OVF_CARRY: {
3225 s390_lghi (code, s390_r0, 0);
3226 s390_lgr (code, s390_r1, s390_r0);
3227 s390_alcgr (code, s390_r0, s390_r1);
3228 s390_agr (code, ins->dreg, src2);
3229 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3230 s390_agr (code, ins->dreg, s390_r0);
3231 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3234 case OP_ADD_OVF_UN_CARRY: {
3236 s390_alcgr (code, ins->dreg, src2);
3237 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3242 s390_sgr (code, ins->dreg, src2);
3247 s390_sgr (code, ins->dreg, src2);
3252 s390_slbgr(code, ins->dreg, src2);
3256 if (ins->dreg != ins->sreg1) {
3257 s390_lgr (code, ins->dreg, ins->sreg1);
3259 if (s390_is_imm16 (-ins->inst_imm)) {
3260 s390_aghi (code, ins->dreg, -ins->inst_imm);
3261 } else if (s390_is_imm32 (-ins->inst_imm)) {
3262 s390_slgfi (code, ins->dreg, ins->inst_imm);
3264 S390_SET (code, s390_r0, ins->inst_imm);
3265 s390_slgr (code, ins->dreg, s390_r0);
3270 if (ins->dreg != ins->sreg1) {
3271 s390_lgr (code, ins->dreg, ins->sreg1);
3273 if (s390_is_imm16 (-ins->inst_imm)) {
3274 s390_aghi (code, ins->dreg, -ins->inst_imm);
3275 } else if (s390_is_imm32 (-ins->inst_imm)) {
3276 s390_slgfi (code, ins->dreg, ins->inst_imm);
3278 S390_SET (code, s390_r0, ins->inst_imm);
3279 s390_slgr (code, ins->dreg, s390_r0);
3284 if (ins->dreg != ins->sreg1) {
3285 s390_lgr (code, ins->dreg, ins->sreg1);
3287 if (s390_is_imm16 (-ins->inst_imm)) {
3288 s390_lghi (code, s390_r0, ins->inst_imm);
3289 s390_slbgr (code, ins->dreg, s390_r0);
3291 S390_SET (code, s390_r0, ins->inst_imm);
3292 s390_slbgr(code, ins->dreg, s390_r0);
3296 case OP_SUB_OVF_CARRY: {
3298 s390_lghi (code, s390_r0, 0);
3299 s390_lgr (code, s390_r1, s390_r0);
3300 s390_slbgr (code, s390_r0, s390_r1);
3301 s390_sgr (code, ins->dreg, src2);
3302 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3303 s390_agr (code, ins->dreg, s390_r0);
3304 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3307 case OP_SUB_OVF_UN_CARRY: {
3309 s390_slbgr (code, ins->dreg, src2);
3310 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3314 if (ins->sreg1 == ins->dreg) {
3315 s390_ngr (code, ins->dreg, ins->sreg2);
3318 if (ins->sreg2 == ins->dreg) {
3319 s390_ngr (code, ins->dreg, ins->sreg1);
3322 s390_lgr (code, ins->dreg, ins->sreg1);
3323 s390_ngr (code, ins->dreg, ins->sreg2);
3329 if (ins->dreg != ins->sreg1) {
3330 s390_lgr (code, ins->dreg, ins->sreg1);
3332 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3333 s390_ngr (code, ins->dreg, s390_r0);
3337 s390_lgr (code, s390_r1, ins->sreg1);
3338 s390_dsgr (code, s390_r0, ins->sreg2);
3339 s390_lgr (code, ins->dreg, s390_r1);
3343 s390_lgr (code, s390_r1, ins->sreg1);
3344 s390_lghi (code, s390_r0, 0);
3345 s390_dlgr (code, s390_r0, ins->sreg2);
3346 s390_lgr (code, ins->dreg, s390_r1);
3350 s390_lgr (code, s390_r1, ins->sreg1);
3351 s390_dsgr (code, s390_r0, ins->sreg2);
3352 s390_lgr (code, ins->dreg, s390_r0);
3356 if (s390_is_imm16 (ins->inst_imm)) {
3357 s390_lghi (code, s390_r13, ins->inst_imm);
3359 s390_lgfi (code, s390_r13, ins->inst_imm);
3361 s390_lgr (code, s390_r0, ins->sreg1);
3362 s390_dsgr (code, s390_r0, s390_r13);
3363 s390_lgfr (code, ins->dreg, s390_r0);
3367 s390_lgr (code, s390_r1, ins->sreg1);
3368 s390_lghi (code, s390_r0, 0);
3369 s390_dlgr (code, s390_r0, ins->sreg2);
3370 s390_lgr (code, ins->dreg, s390_r0);
3374 if (ins->sreg1 == ins->dreg) {
3375 s390_ogr (code, ins->dreg, ins->sreg2);
3378 if (ins->sreg2 == ins->dreg) {
3379 s390_ogr (code, ins->dreg, ins->sreg1);
3382 s390_lgr (code, ins->dreg, ins->sreg1);
3383 s390_ogr (code, ins->dreg, ins->sreg2);
3389 if (ins->dreg != ins->sreg1) {
3390 s390_lgr (code, ins->dreg, ins->sreg1);
3392 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3393 s390_ogr (code, ins->dreg, s390_r0);
3397 if (ins->sreg1 == ins->dreg) {
3398 s390_xgr (code, ins->dreg, ins->sreg2);
3401 if (ins->sreg2 == ins->dreg) {
3402 s390_xgr (code, ins->dreg, ins->sreg1);
3405 s390_lgr (code, ins->dreg, ins->sreg1);
3406 s390_xgr (code, ins->dreg, ins->sreg2);
3412 if (ins->dreg != ins->sreg1) {
3413 s390_lgr (code, ins->dreg, ins->sreg1);
3415 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3416 s390_xgr (code, ins->dreg, s390_r0);
3421 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3426 if (ins->sreg1 != ins->dreg) {
3427 s390_lgr (code, ins->dreg, ins->sreg1);
3429 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3434 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3439 if (ins->sreg1 != ins->dreg) {
3440 s390_lgr (code, ins->dreg, ins->sreg1);
3442 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3446 case OP_LSHR_UN_IMM: {
3447 if (ins->sreg1 != ins->dreg) {
3448 s390_lgr (code, ins->dreg, ins->sreg1);
3450 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3455 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3459 if (ins->sreg1 != ins->dreg) {
3460 s390_lgr (code, ins->dreg, ins->sreg1);
3462 s390_lghi (code, s390_r0, -1);
3463 s390_xgr (code, ins->dreg, s390_r0);
3467 s390_lcgr (code, ins->dreg, ins->sreg1);
3472 s390_msgr (code, ins->dreg, src2);
3477 if (ins->dreg != ins->sreg1) {
3478 s390_lgr (code, ins->dreg, ins->sreg1);
3480 if (s390_is_imm16 (ins->inst_imm)) {
3481 s390_lghi (code, s390_r13, ins->inst_imm);
3482 } else if (s390_is_imm32 (ins->inst_imm)) {
3483 s390_lgfi (code, s390_r13, ins->inst_imm);
3485 S390_SET (code, s390_r13, ins->inst_imm);
3487 s390_msgr (code, ins->dreg, s390_r13);
3492 s390_ltgr (code, s390_r1, ins->sreg1);
3493 s390_jz (code, 0); CODEPTR(code, o[0]);
3494 s390_ltgr (code, s390_r0, ins->sreg2);
3496 s390_lghi (code, s390_r1, 0);
3497 s390_j (code, 0); CODEPTR(code, o[1]);
3498 s390_xgr (code, s390_r0, s390_r1);
3499 s390_msgr (code, s390_r1, ins->sreg2);
3500 s390_xgr (code, s390_r0, s390_r1);
3501 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3502 s390_ltgr (code, s390_r0, s390_r0);
3503 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3504 PTRSLOT (code, o[0]);
3505 PTRSLOT (code, o[1]);
3506 s390_lgr (code, ins->dreg, s390_r1);
3509 case OP_LMUL_OVF_UN: {
3510 s390_lghi (code, s390_r0, 0);
3511 s390_lgr (code, s390_r1, ins->sreg1);
3512 s390_mlgr (code, s390_r0, ins->sreg2);
3513 s390_ltgr (code, s390_r0, s390_r0);
3514 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3515 s390_lgr (code, ins->dreg, s390_r1);
3519 g_assert_not_reached ();
3521 s390_algr (code, ins->dreg, src2);
3526 s390_agr (code, ins->dreg, src2);
3530 g_assert_not_reached ();
3532 s390_alcgr (code, ins->dreg, src2);
3536 if (ins->dreg != ins->sreg1) {
3537 s390_lgfr (code, ins->dreg, ins->sreg1);
3539 if (s390_is_imm16 (ins->inst_imm)) {
3540 s390_aghi (code, ins->dreg, ins->inst_imm);
3542 s390_afi (code, ins->dreg, ins->inst_imm);
3547 if (ins->dreg != ins->sreg1) {
3548 s390_lgfr (code, ins->dreg, ins->sreg1);
3550 if (s390_is_imm16 (ins->inst_imm)) {
3551 s390_lghi (code, s390_r0, ins->inst_imm);
3552 s390_alcgr (code, ins->dreg, s390_r0);
3554 S390_SET (code, s390_r0, ins->inst_imm);
3555 s390_alcgr (code, ins->dreg, s390_r0);
3560 case OP_S390_LADD_OVF: {
3562 s390_agr (code, ins->dreg, src2);
3563 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3566 case OP_LADD_OVF_UN:
3567 case OP_S390_LADD_OVF_UN: {
3569 s390_algr (code, ins->dreg, src2);
3570 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3574 CHECK_SRCDST_NCOM_I;
3575 s390_slgr (code, ins->dreg, src2);
3579 CHECK_SRCDST_NCOM_I;
3580 s390_sgr (code, ins->dreg, src2);
3584 CHECK_SRCDST_NCOM_I;
3585 s390_slbgr (code, ins->dreg, src2);
3589 if (ins->dreg != ins->sreg1) {
3590 s390_lgfr (code, ins->dreg, ins->sreg1);
3592 if (s390_is_imm16 (-ins->inst_imm)) {
3593 s390_aghi (code, ins->dreg, -ins->inst_imm);
3595 s390_agfi (code, ins->dreg, -ins->inst_imm);
3600 S390_SET (code, s390_r0, ins->inst_imm);
3601 s390_slgfr (code, ins->dreg, s390_r0);
3605 case OP_S390_ISUB_OVF: {
3607 s390_sr (code, ins->dreg, src2);
3608 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3609 s390_lgfr (code, ins->dreg, ins->dreg);
3612 case OP_ISUB_OVF_UN:
3613 case OP_S390_ISUB_OVF_UN: {
3615 s390_slr (code, ins->dreg, src2);
3616 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3617 s390_llgfr(code, ins->dreg, ins->dreg);
3621 case OP_S390_LSUB_OVF: {
3623 s390_sgr (code, ins->dreg, src2);
3624 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3627 case OP_LSUB_OVF_UN:
3628 case OP_S390_LSUB_OVF_UN: {
3630 s390_slgr (code, ins->dreg, src2);
3631 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3635 CHECK_SRCDST_NCOM_I;
3636 s390_ngr (code, ins->dreg, src2);
3640 if (ins->dreg != ins->sreg1) {
3641 s390_lgfr (code, ins->dreg, ins->sreg1);
3643 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3644 s390_ngr (code, ins->dreg, s390_r0);
3648 s390_lgfr (code, s390_r0, ins->sreg1);
3649 s390_srda (code, s390_r0, 0, 32);
3650 s390_dr (code, s390_r0, ins->sreg2);
3651 s390_lgfr (code, ins->dreg, s390_r1);
3655 s390_lgfr (code, s390_r0, ins->sreg1);
3656 s390_srdl (code, s390_r0, 0, 32);
3657 s390_dlr (code, s390_r0, ins->sreg2);
3658 s390_lgfr (code, ins->dreg, s390_r1);
3662 if (s390_is_imm16 (ins->inst_imm)) {
3663 s390_lghi (code, s390_r13, ins->inst_imm);
3665 s390_lgfi (code, s390_r13, ins->inst_imm);
3667 s390_lgfr (code, s390_r0, ins->sreg1);
3668 s390_srda (code, s390_r0, 0, 32);
3669 s390_dr (code, s390_r0, ins->sreg2);
3670 s390_lgfr (code, ins->dreg, s390_r1);
3674 s390_lgfr (code, s390_r0, ins->sreg1);
3675 s390_srda (code, s390_r0, 0, 32);
3676 s390_dr (code, s390_r0, ins->sreg2);
3677 s390_lgfr (code, ins->dreg, s390_r0);
3680 s390_lgfr (code, s390_r0, ins->sreg1);
3681 s390_srdl (code, s390_r0, 0, 32);
3682 s390_dlr (code, s390_r0, ins->sreg2);
3683 s390_lgfr (code, ins->dreg, s390_r0);
3687 if (s390_is_imm16 (ins->inst_imm)) {
3688 s390_lghi (code, s390_r13, ins->inst_imm);
3690 s390_lgfi (code, s390_r13, ins->inst_imm);
3692 s390_lgfr (code, s390_r0, ins->sreg1);
3693 s390_srda (code, s390_r0, 0, 32);
3694 s390_dr (code, s390_r0, ins->sreg2);
3695 s390_lgfr (code, ins->dreg, s390_r0);
3700 s390_ogr (code, ins->dreg, src2);
3704 if (ins->dreg != ins->sreg1) {
3705 s390_lgfr (code, ins->dreg, ins->sreg1);
3707 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3708 s390_ogr (code, ins->dreg, s390_r0);
3713 s390_xgr (code, ins->dreg, src2);
3717 if (ins->dreg != ins->sreg1) {
3718 s390_lgfr (code, ins->dreg, ins->sreg1);
3720 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3721 s390_xgr (code, ins->dreg, s390_r0);
3726 s390_sll (code, ins->dreg, src2, 0);
3730 if (ins->sreg1 != ins->dreg) {
3731 s390_lgfr (code, ins->dreg, ins->sreg1);
3733 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3738 s390_sra (code, ins->dreg, src2, 0);
3742 if (ins->sreg1 != ins->dreg) {
3743 s390_lgfr (code, ins->dreg, ins->sreg1);
3745 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3748 case OP_ISHR_UN_IMM: {
3749 if (ins->sreg1 != ins->dreg) {
3750 s390_lgfr (code, ins->dreg, ins->sreg1);
3752 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3757 s390_srl (code, ins->dreg, src2, 0);
3761 if (ins->sreg1 != ins->dreg) {
3762 s390_lgfr (code, ins->dreg, ins->sreg1);
3764 s390_lghi (code, s390_r0, -1);
3765 s390_xgr (code, ins->dreg, s390_r0);
3769 s390_lcgr (code, ins->dreg, ins->sreg1);
3774 s390_msr (code, ins->dreg, src2);
3778 if (ins->dreg != ins->sreg1) {
3779 s390_lgfr (code, ins->dreg, ins->sreg1);
3781 if (s390_is_imm16 (ins->inst_imm)) {
3782 s390_lghi (code, s390_r0, ins->inst_imm);
3784 s390_lgfi (code, s390_r0, ins->inst_imm);
3786 s390_msr (code, ins->dreg, s390_r0);
3791 s390_ltr (code, s390_r1, ins->sreg1);
3792 s390_jz (code, 0); CODEPTR(code, o[0]);
3793 s390_ltr (code, s390_r0, ins->sreg2);
3795 s390_lhi (code, s390_r1, 0);
3796 s390_j (code, 0); CODEPTR(code, o[1]);
3797 s390_xr (code, s390_r0, s390_r1);
3798 s390_msr (code, s390_r1, ins->sreg2);
3799 s390_xr (code, s390_r0, s390_r1);
3800 s390_srl (code, s390_r0, 0, 31);
3801 s390_ltr (code, s390_r0, s390_r0);
3802 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3803 PTRSLOT (code, o[0]);
3804 PTRSLOT (code, o[1]);
3805 s390_lgfr (code, ins->dreg, s390_r1);
3808 case OP_IMUL_OVF_UN: {
3809 s390_lhi (code, s390_r0, 0);
3810 s390_lr (code, s390_r1, ins->sreg1);
3811 s390_mlr (code, s390_r0, ins->sreg2);
3812 s390_ltr (code, s390_r0, s390_r0);
3813 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3814 s390_lgfr (code, ins->dreg, s390_r1);
3819 S390_SET (code, ins->dreg, ins->inst_c0);
3823 mono_add_patch_info (cfg, code - cfg->native_code,
3824 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3825 S390_LOAD_TEMPLATE (code, ins->dreg);
3828 case OP_JUMP_TABLE: {
3829 mono_add_patch_info (cfg, code - cfg->native_code,
3830 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3831 S390_LOAD_TEMPLATE (code, ins->dreg);
3835 if (ins->dreg != ins->sreg1) {
3836 s390_lgr (code, ins->dreg, ins->sreg1);
3840 case OP_LCONV_TO_I8:
3842 s390_lgfr (code, ins->dreg, ins->sreg1);
3844 case OP_LCONV_TO_I4:
3845 s390_lgfr (code, ins->dreg, ins->sreg1);
3848 case OP_LCONV_TO_U8:
3849 case OP_LCONV_TO_U4:
3851 s390_llgfr (code, ins->dreg, ins->sreg1);
3853 case OP_LCONV_TO_OVF_U4:
3854 S390_SET (code, s390_r0, 4294967295);
3855 s390_clgr (code, ins->sreg1, s390_r0);
3856 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3857 s390_ltgr (code, ins->sreg1, ins->sreg1);
3858 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3859 s390_llgfr(code, ins->dreg, ins->sreg1);
3861 case OP_LCONV_TO_OVF_I4_UN:
3862 S390_SET (code, s390_r0, 2147483647);
3863 s390_cgr (code, ins->sreg1, s390_r0);
3864 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3865 s390_ltgr (code, ins->sreg1, ins->sreg1);
3866 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3867 s390_lgfr (code, ins->dreg, ins->sreg1);
3870 if (ins->dreg != ins->sreg1) {
3871 s390_ldr (code, ins->dreg, ins->sreg1);
3874 case OP_MOVE_F_TO_I8:
3875 s390_lgdr (code, ins->dreg, ins->sreg1);
3877 case OP_MOVE_I8_TO_F:
3878 s390_ldgr (code, ins->dreg, ins->sreg1);
3880 case OP_MOVE_F_TO_I4:
3881 s390_ledbr (code, s390_f0, ins->sreg1);
3882 s390_lgdr (code, ins->dreg, s390_f0);
3883 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3885 case OP_MOVE_I4_TO_F:
3886 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3887 s390_ldgr (code, ins->dreg, s390_r0);
3888 s390_ldebr (code, ins->dreg, ins->dreg);
3890 case OP_FCONV_TO_R4:
3891 s390_ledbr (code, ins->dreg, ins->sreg1);
3892 s390_ldebr (code, ins->dreg, ins->dreg);
3894 case OP_S390_SETF4RET:
3895 s390_ledbr (code, ins->dreg, ins->sreg1);
3898 if (s390_is_imm16 (ins->inst_offset)) {
3899 s390_lghi (code, s390_r13, ins->inst_offset);
3900 } else if (s390_is_imm32 (ins->inst_offset)) {
3901 s390_lgfi (code, s390_r13, ins->inst_offset);
3903 S390_SET (code, s390_r13, ins->inst_offset);
3905 s390_ear (code, s390_r1, 0);
3906 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3907 s390_ear (code, s390_r1, 1);
3908 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3912 if (cfg->method->save_lmf)
3913 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3915 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3916 code = emit_load_volatile_arguments (code, cfg);
3919 code = backUpStackPtr(cfg, code);
3920 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3921 mono_add_patch_info (cfg, code - cfg->native_code,
3922 MONO_PATCH_INFO_METHOD_JUMP,
3924 s390_jcl (code, S390_CC_UN, 0);
3927 case OP_CHECK_THIS: {
3928 /* ensure ins->sreg1 is not NULL */
3929 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3930 s390_ltgr (code, s390_r0, s390_r0);
3931 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3935 int offset = cfg->sig_cookie + cfg->stack_usage;
3937 if (s390_is_imm16 (offset)) {
3938 s390_lghi (code, s390_r0, offset);
3939 } else if (s390_is_imm32 (offset)) {
3940 s390_lgfi (code, s390_r0, offset);
3942 S390_SET (code, s390_r0, offset);
3944 s390_agr (code, s390_r0, cfg->frame_reg);
3945 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3949 call = (MonoCallInst*)ins;
3950 if (ins->flags & MONO_INST_HAS_METHOD)
3951 mono_add_patch_info (cfg, code-cfg->native_code,
3952 MONO_PATCH_INFO_METHOD,
3955 mono_add_patch_info (cfg, code-cfg->native_code,
3956 MONO_PATCH_INFO_ABS,
3958 S390_CALL_TEMPLATE (code, s390_r14);
3959 if (call->signature->ret->type == MONO_TYPE_R4)
3960 s390_ldebr (code, s390_f0, s390_f0);
3968 call = (MonoCallInst*)ins;
3969 if (ins->flags & MONO_INST_HAS_METHOD)
3970 mono_add_patch_info (cfg, code-cfg->native_code,
3971 MONO_PATCH_INFO_METHOD,
3974 mono_add_patch_info (cfg, code-cfg->native_code,
3975 MONO_PATCH_INFO_ABS,
3977 S390_CALL_TEMPLATE (code, s390_r14);
3980 case OP_FCALL_REG: {
3981 call = (MonoCallInst*)ins;
3982 s390_lgr (code, s390_r1, ins->sreg1);
3983 s390_basr (code, s390_r14, s390_r1);
3984 if (call->signature->ret->type == MONO_TYPE_R4)
3985 s390_ldebr (code, s390_f0, s390_f0);
3991 case OP_VOIDCALL_REG:
3993 s390_lgr (code, s390_r1, ins->sreg1);
3994 s390_basr (code, s390_r14, s390_r1);
3997 case OP_FCALL_MEMBASE: {
3998 call = (MonoCallInst*)ins;
3999 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4000 s390_basr (code, s390_r14, s390_r1);
4001 if (call->signature->ret->type == MONO_TYPE_R4)
4002 s390_ldebr (code, s390_f0, s390_f0);
4005 case OP_LCALL_MEMBASE:
4006 case OP_VCALL_MEMBASE:
4007 case OP_VCALL2_MEMBASE:
4008 case OP_VOIDCALL_MEMBASE:
4009 case OP_CALL_MEMBASE: {
4010 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4011 s390_basr (code, s390_r14, s390_r1);
4018 if (cfg->param_area == 0)
4019 alloca_skip = S390_MINIMAL_STACK_SIZE;
4021 alloca_skip = cfg->param_area;
4023 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4024 s390_lgr (code, s390_r1, ins->sreg1);
4025 if (ins->flags & MONO_INST_INIT)
4026 s390_lgr (code, s390_r0, ins->sreg1);
4027 s390_aghi (code, s390_r1, 14);
4028 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4029 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4030 if (cfg->method->save_lmf) {
4031 /*----------------------------------*/
4032 /* we have to adjust lmf ebp value */
4033 /*----------------------------------*/
4034 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4036 s390_lgr (code, s390_r13, cfg->frame_reg);
4037 if (s390_is_imm16(lmfOffset)) {
4038 s390_aghi (code, s390_r13, lmfOffset);
4039 } else if (s390_is_imm32(lmfOffset)) {
4040 s390_agfi (code, s390_r13, lmfOffset);
4042 S390_SET (code, s390_r13, lmfOffset);
4044 s390_lgr (code, s390_r14, STK_BASE);
4045 s390_sgr (code, s390_r14, s390_r1);
4046 s390_stg (code, s390_r14, 0, s390_r13,
4047 G_STRUCT_OFFSET(MonoLMF, ebp));
4049 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4050 s390_sgr (code, STK_BASE, s390_r1);
4051 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4052 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4053 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4054 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4055 if (ins->flags & MONO_INST_INIT) {
4056 s390_lgr (code, s390_r1, s390_r0);
4057 s390_lgr (code, s390_r0, ins->dreg);
4058 s390_lgr (code, s390_r14, s390_r12);
4059 s390_lghi (code, s390_r13, 0);
4060 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4062 s390_lgr (code, s390_r12, s390_r14);
4067 s390_lgr (code, s390_r2, ins->sreg1);
4068 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4069 (gpointer) "mono_arch_throw_exception");
4070 S390_CALL_TEMPLATE(code, s390_r14);
4074 s390_lgr (code, s390_r2, ins->sreg1);
4075 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4076 (gpointer) "mono_arch_rethrow_exception");
4077 S390_CALL_TEMPLATE(code, s390_r14);
4080 case OP_START_HANDLER: {
4081 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4083 S390_LONG (code, stg, stg, s390_r14, 0,
4084 spvar->inst_basereg,
4085 spvar->inst_offset);
4088 case OP_ENDFILTER: {
4089 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4091 if (ins->sreg1 != s390_r2)
4092 s390_lgr(code, s390_r2, ins->sreg1);
4093 S390_LONG (code, lg, lg, s390_r14, 0,
4094 spvar->inst_basereg,
4095 spvar->inst_offset);
4096 s390_br (code, s390_r14);
4099 case OP_ENDFINALLY: {
4100 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4102 S390_LONG (code, lg, lg, s390_r14, 0,
4103 spvar->inst_basereg,
4104 spvar->inst_offset);
4105 s390_br (code, s390_r14);
4108 case OP_CALL_HANDLER: {
4109 mono_add_patch_info (cfg, code-cfg->native_code,
4110 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4111 s390_brasl (code, s390_r14, 0);
4112 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4116 ins->inst_c0 = code - cfg->native_code;
4119 case OP_RELAXED_NOP:
4122 case OP_DUMMY_STORE:
4123 case OP_NOT_REACHED:
4127 case OP_IL_SEQ_POINT:
4128 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4130 case OP_SEQ_POINT: {
4133 if (cfg->compile_aot)
4137 * Read from the single stepping trigger page. This will cause a
4138 * SIGSEGV when single stepping is enabled.
4139 * We do this _before_ the breakpoint, so single stepping after
4140 * a breakpoint is hit will step to the next IL offset.
4142 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4143 breakpointCode.pTrigger = ss_trigger_page;
4144 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4145 code += BREAKPOINT_SIZE;
4148 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4151 * A placeholder for a possible breakpoint inserted by
4152 * mono_arch_set_breakpoint ().
4154 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4158 * Add an additional nop so skipping the bp doesn't cause the ip to point
4159 * to another IL offset.
4165 case OP_GENERIC_CLASS_INIT: {
4166 static int byte_offset = -1;
4167 static guint8 bitmask;
4170 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4172 if (byte_offset < 0)
4173 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4175 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4176 s390_jo (code, 0); CODEPTR(code, jump);
4178 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4179 "mono_generic_class_init");
4180 S390_CALL_TEMPLATE(code, s390_r14);
4182 PTRSLOT (code, jump);
4184 ins->flags |= MONO_INST_GC_CALLSITE;
4185 ins->backend.pc_offset = code - cfg->native_code;
4189 EMIT_UNCOND_BRANCH(ins);
4192 s390_br (code, ins->sreg1);
4198 s390_lghi(code, ins->dreg, 1);
4200 s390_lghi(code, ins->dreg, 0);
4206 s390_lghi(code, ins->dreg, 1);
4208 s390_lghi(code, ins->dreg, 0);
4214 s390_lghi(code, ins->dreg, 1);
4216 s390_lghi(code, ins->dreg, 0);
4222 s390_lghi(code, ins->dreg, 1);
4224 s390_lghi(code, ins->dreg, 0);
4230 s390_lghi(code, ins->dreg, 1);
4232 s390_lghi(code, ins->dreg, 0);
4235 case OP_COND_EXC_EQ:
4236 case OP_COND_EXC_IEQ:
4237 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4239 case OP_COND_EXC_NE_UN:
4240 case OP_COND_EXC_INE_UN:
4241 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4243 case OP_COND_EXC_LT:
4244 case OP_COND_EXC_ILT:
4245 case OP_COND_EXC_LT_UN:
4246 case OP_COND_EXC_ILT_UN:
4247 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4249 case OP_COND_EXC_GT:
4250 case OP_COND_EXC_IGT:
4251 case OP_COND_EXC_GT_UN:
4252 case OP_COND_EXC_IGT_UN:
4253 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4255 case OP_COND_EXC_GE:
4256 case OP_COND_EXC_IGE:
4257 case OP_COND_EXC_GE_UN:
4258 case OP_COND_EXC_IGE_UN:
4259 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4261 case OP_COND_EXC_LE:
4262 case OP_COND_EXC_ILE:
4263 case OP_COND_EXC_LE_UN:
4264 case OP_COND_EXC_ILE_UN:
4265 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4267 case OP_COND_EXC_OV:
4268 case OP_COND_EXC_IOV:
4269 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4271 case OP_COND_EXC_NO:
4272 case OP_COND_EXC_INO:
4273 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4276 case OP_COND_EXC_IC:
4277 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4279 case OP_COND_EXC_NC:
4280 case OP_COND_EXC_INC:
4281 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4285 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4289 EMIT_COND_BRANCH (ins, S390_CC_NE);
4295 EMIT_COND_BRANCH (ins, S390_CC_LT);
4301 EMIT_COND_BRANCH (ins, S390_CC_GT);
4307 EMIT_COND_BRANCH (ins, S390_CC_GE);
4313 EMIT_COND_BRANCH (ins, S390_CC_LE);
4316 /* floating point opcodes */
4318 if (*((double *) ins->inst_p0) == 0) {
4319 s390_lzdr (code, ins->dreg);
4321 S390_SET (code, s390_r13, ins->inst_p0);
4322 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4327 if (*((float *) ins->inst_p0) == 0) {
4328 s390_lzdr (code, ins->dreg);
4330 S390_SET (code, s390_r13, ins->inst_p0);
4331 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4335 case OP_STORER8_MEMBASE_REG: {
4336 S390_LONG (code, stdy, std, ins->sreg1, 0,
4337 ins->inst_destbasereg, ins->inst_offset);
4340 case OP_LOADR8_MEMBASE: {
4341 S390_LONG (code, ldy, ld, ins->dreg, 0,
4342 ins->inst_basereg, ins->inst_offset);
4345 case OP_STORER4_MEMBASE_REG: {
4346 s390_ledbr (code, s390_f15, ins->sreg1);
4347 S390_LONG (code, stey, ste, s390_f15, 0,
4348 ins->inst_destbasereg, ins->inst_offset);
4351 case OP_LOADR4_MEMBASE: {
4352 S390_LONG (code, ley, le, s390_f15, 0,
4353 ins->inst_basereg, ins->inst_offset);
4354 s390_ldebr (code, ins->dreg, s390_f15);
4357 case OP_ICONV_TO_R_UN: {
4359 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4361 s390_llgfr (code, s390_r0, ins->sreg1);
4362 s390_cdgbr (code, ins->dreg, s390_r0);
4366 case OP_LCONV_TO_R_UN: {
4368 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4371 s390_cxgbr (code, s390_f12, ins->sreg1);
4372 s390_ltgr (code, ins->sreg1, ins->sreg1);
4373 s390_jnl (code, 0); CODEPTR(code, jump);
4374 S390_SET (code, s390_r13, 0x403f000000000000llu);
4375 s390_lgdr (code, s390_f13, s390_r13);
4376 s390_lzdr (code, s390_f15);
4377 s390_axbr (code, s390_f12, s390_f13);
4378 PTRSLOT(code, jump);
4379 s390_ldxbr (code, s390_f13, s390_f12);
4380 s390_ldr (code, ins->dreg, s390_f13);
4384 case OP_LCONV_TO_R4:
4385 case OP_ICONV_TO_R4: {
4386 s390_cegbr (code, ins->dreg, ins->sreg1);
4387 s390_ldebr (code, ins->dreg, ins->dreg);
4390 case OP_LCONV_TO_R8:
4391 case OP_ICONV_TO_R8: {
4392 s390_cdgbr (code, ins->dreg, ins->sreg1);
4395 case OP_FCONV_TO_I1:
4396 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4397 s390_ltgr (code, ins->dreg, ins->dreg);
4399 s390_oill (code, ins->dreg, 0x80);
4400 s390_lghi (code, s390_r0, 0xff);
4401 s390_ngr (code, ins->dreg, s390_r0);
4403 case OP_FCONV_TO_U1:
4405 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4406 s390_lghi (code, s390_r0, 0xff);
4407 s390_ngr (code, ins->dreg, s390_r0);
4409 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4412 case OP_FCONV_TO_I2:
4413 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4414 s390_ltgr (code, ins->dreg, ins->dreg);
4416 s390_oill (code, ins->dreg, 0x8000);
4417 s390_llill (code, s390_r0, 0xffff);
4418 s390_ngr (code, ins->dreg, s390_r0);
4420 case OP_FCONV_TO_U2:
4422 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4423 s390_llill (code, s390_r0, 0xffff);
4424 s390_ngr (code, ins->dreg, s390_r0);
4426 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4429 case OP_FCONV_TO_I4:
4431 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4433 case OP_FCONV_TO_U4:
4436 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4438 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4441 case OP_FCONV_TO_I8:
4442 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4444 case OP_FCONV_TO_U8:
4446 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4448 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4451 case OP_LCONV_TO_OVF_I: {
4452 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4454 s390_ltgr (code, ins->sreg2, ins->sreg2);
4455 s390_jnl (code, 0); CODEPTR(code, o[0]);
4456 s390_ltgr (code, ins->sreg1, ins->sreg1);
4457 s390_jnl (code, 0); CODEPTR(code, o[1]);
4458 s390_lhi (code, s390_r13, -1);
4459 s390_cgr (code, ins->sreg1, s390_r13);
4460 s390_jnz (code, 0); CODEPTR(code, o[2]);
4461 if (ins->dreg != ins->sreg2)
4462 s390_lgr (code, ins->dreg, ins->sreg2);
4463 s390_j (code, 0); CODEPTR(code, o[3]);
4464 PTRSLOT(code, o[0]);
4465 s390_jz (code, 0); CODEPTR(code, o[4]);
4466 PTRSLOT(code, o[1]);
4467 PTRSLOT(code, o[2]);
4468 mono_add_patch_info (cfg, code - cfg->native_code,
4469 MONO_PATCH_INFO_EXC, "OverflowException");
4470 s390_brasl (code, s390_r14, 0);
4471 PTRSLOT(code, o[3]);
4472 PTRSLOT(code, o[4]);
4476 s390_lpdbr (code, ins->dreg, ins->sreg1);
4480 s390_sqdbr (code, ins->dreg, ins->sreg1);
4485 s390_adbr (code, ins->dreg, src2);
4489 CHECK_SRCDST_NCOM_F;
4490 s390_sdbr (code, ins->dreg, src2);
4495 s390_mdbr (code, ins->dreg, src2);
4499 CHECK_SRCDST_NCOM_F;
4500 s390_ddbr (code, ins->dreg, src2);
4504 s390_lcdbr (code, ins->dreg, ins->sreg1);
4508 CHECK_SRCDST_NCOM_F;
4509 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4513 s390_cdbr (code, ins->sreg1, ins->sreg2);
4517 s390_cdbr (code, ins->sreg1, ins->sreg2);
4518 s390_lghi (code, ins->dreg, 1);
4520 s390_lghi (code, ins->dreg, 0);
4524 s390_cdbr (code, ins->sreg1, ins->sreg2);
4525 s390_lghi (code, ins->dreg, 1);
4527 s390_lghi (code, ins->dreg, 0);
4531 s390_cdbr (code, ins->sreg1, ins->sreg2);
4532 s390_lghi (code, ins->dreg, 1);
4534 s390_lghi (code, ins->dreg, 0);
4538 s390_cdbr (code, ins->sreg1, ins->sreg2);
4539 s390_lghi (code, ins->dreg, 1);
4541 s390_lghi (code, ins->dreg, 0);
4545 s390_cdbr (code, ins->sreg1, ins->sreg2);
4546 s390_lghi (code, ins->dreg, 1);
4548 s390_lghi (code, ins->dreg, 0);
4553 s390_jo (code, 0); CODEPTR(code, o);
4554 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4559 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4563 s390_jo (code, 0); CODEPTR(code, o);
4564 EMIT_COND_BRANCH (ins, S390_CC_LT);
4569 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4573 s390_jo (code, 0); CODEPTR(code, o);
4574 EMIT_COND_BRANCH (ins, S390_CC_GT);
4579 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4583 s390_jo (code, 0); CODEPTR(code, o);
4584 EMIT_COND_BRANCH (ins, S390_CC_GE);
4589 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4593 s390_jo (code, 0); CODEPTR(code, o);
4594 EMIT_COND_BRANCH (ins, S390_CC_LE);
4599 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4603 s390_lhi (code, s390_r13, 0x7f);
4604 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4605 s390_jz (code, 0); CODEPTR(code, o);
4606 mono_add_patch_info (cfg, code - cfg->native_code,
4607 MONO_PATCH_INFO_EXC, "OverflowException");
4608 s390_brasl (code, s390_r14,0);
4612 case OP_S390_MOVE: {
4613 if (ins->backend.size > 0) {
4614 if (ins->backend.size <= 256) {
4615 s390_mvc (code, ins->backend.size, ins->dreg,
4616 ins->inst_offset, ins->sreg1, ins->inst_imm);
4618 s390_lgr (code, s390_r0, ins->dreg);
4619 if (ins->inst_offset > 0) {
4620 if (s390_is_imm16 (ins->inst_offset)) {
4621 s390_aghi (code, s390_r0, ins->inst_offset);
4622 } else if (s390_is_imm32 (ins->inst_offset)) {
4623 s390_agfi (code, s390_r0, ins->inst_offset);
4625 S390_SET (code, s390_r13, ins->inst_offset);
4626 s390_agr (code, s390_r0, s390_r13);
4629 s390_lgr (code, s390_r12, ins->sreg1);
4630 if (ins->inst_imm > 0) {
4631 if (s390_is_imm16 (ins->inst_imm)) {
4632 s390_aghi (code, s390_r12, ins->inst_imm);
4633 } else if (s390_is_imm32 (ins->inst_imm)) {
4634 s390_agfi (code, s390_r12, ins->inst_imm);
4636 S390_SET (code, s390_r13, ins->inst_imm);
4637 s390_agr (code, s390_r12, s390_r13);
4640 if (s390_is_imm16 (ins->backend.size)) {
4641 s390_lghi (code, s390_r1, ins->backend.size);
4642 } else if (s390_is_imm32 (ins->inst_offset)) {
4643 s390_agfi (code, s390_r1, ins->backend.size);
4645 S390_SET (code, s390_r13, ins->backend.size);
4646 s390_agr (code, s390_r1, s390_r13);
4648 s390_lgr (code, s390_r13, s390_r1);
4649 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4655 case OP_ATOMIC_ADD_I8: {
4656 s390_lgr (code, s390_r1, ins->sreg2);
4657 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4658 s390_agr (code, s390_r1, s390_r0);
4659 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4660 s390_jnz (code, -10);
4661 s390_lgr (code, ins->dreg, s390_r1);
4664 case OP_ATOMIC_EXCHANGE_I8: {
4665 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4666 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4667 s390_jnz (code, -6);
4668 s390_lgr (code, ins->dreg, s390_r0);
4671 case OP_ATOMIC_ADD_I4: {
4672 s390_lgfr(code, s390_r1, ins->sreg2);
4673 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4674 s390_agr (code, s390_r1, s390_r0);
4675 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4676 s390_jnz (code, -9);
4677 s390_lgfr(code, ins->dreg, s390_r1);
4680 case OP_ATOMIC_EXCHANGE_I4: {
4681 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4682 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4683 s390_jnz (code, -4);
4684 s390_lgfr(code, ins->dreg, s390_r0);
4687 case OP_S390_BKCHAIN: {
4688 s390_lgr (code, ins->dreg, ins->sreg1);
4689 if (s390_is_imm16 (cfg->stack_offset)) {
4690 s390_aghi (code, ins->dreg, cfg->stack_offset);
4691 } else if (s390_is_imm32 (cfg->stack_offset)) {
4692 s390_agfi (code, ins->dreg, cfg->stack_offset);
4694 S390_SET (code, s390_r13, cfg->stack_offset);
4695 s390_agr (code, ins->dreg, s390_r13);
4699 case OP_MEMORY_BARRIER:
4702 case OP_GC_SAFE_POINT: {
4705 g_assert (mono_threads_is_coop_enabled ());
4707 s390_chi (code, ins->sreg1, 1);
4708 s390_je (code, 0); CODEPTR(code, br);
4709 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4710 mono_threads_state_poll);
4711 S390_CALL_TEMPLATE (code, s390_r14);
4715 case OP_GC_LIVENESS_DEF:
4716 case OP_GC_LIVENESS_USE:
4717 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4718 ins->backend.pc_offset = code - cfg->native_code;
4720 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4721 ins->backend.pc_offset = code - cfg->native_code;
4722 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4724 #ifdef MONO_ARCH_SIMD_INTRINSICS
4726 s390x_addps (code, ins->sreg1, ins->sreg2);
4729 s390x_divps (code, ins->sreg1, ins->sreg2);
4732 s390x_mulps (code, ins->sreg1, ins->sreg2);
4735 s390x_subps (code, ins->sreg1, ins->sreg2);
4738 s390x_maxps (code, ins->sreg1, ins->sreg2);
4741 s390x_minps (code, ins->sreg1, ins->sreg2);
4744 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4745 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4748 s390x_andps (code, ins->sreg1, ins->sreg2);
4751 s390x_andnps (code, ins->sreg1, ins->sreg2);
4754 s390x_orps (code, ins->sreg1, ins->sreg2);
4757 s390x_xorps (code, ins->sreg1, ins->sreg2);
4760 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4763 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4766 s390x_rcpps (code, ins->dreg, ins->sreg1);
4769 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4772 s390x_haddps (code, ins->sreg1, ins->sreg2);
4775 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4778 s390x_movshdup (code, ins->dreg, ins->sreg1);
4781 s390x_movsldup (code, ins->dreg, ins->sreg1);
4784 case OP_PSHUFLEW_HIGH:
4785 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4786 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4788 case OP_PSHUFLEW_LOW:
4789 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4790 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4793 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4794 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4797 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4798 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4801 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4802 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4806 s390x_addpd (code, ins->sreg1, ins->sreg2);
4809 s390x_divpd (code, ins->sreg1, ins->sreg2);
4812 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4815 s390x_subpd (code, ins->sreg1, ins->sreg2);
4818 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4821 s390x_minpd (code, ins->sreg1, ins->sreg2);
4824 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4825 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4828 s390x_andpd (code, ins->sreg1, ins->sreg2);
4831 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4834 s390x_orpd (code, ins->sreg1, ins->sreg2);
4837 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4840 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4843 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4846 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4849 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4852 s390x_movddup (code, ins->dreg, ins->sreg1);
4855 case OP_EXTRACT_MASK:
4856 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4860 s390x_pand (code, ins->sreg1, ins->sreg2);
4863 s390x_por (code, ins->sreg1, ins->sreg2);
4866 s390x_pxor (code, ins->sreg1, ins->sreg2);
4870 s390x_paddb (code, ins->sreg1, ins->sreg2);
4873 s390x_paddw (code, ins->sreg1, ins->sreg2);
4876 s390x_paddd (code, ins->sreg1, ins->sreg2);
4879 s390x_paddq (code, ins->sreg1, ins->sreg2);
4883 s390x_psubb (code, ins->sreg1, ins->sreg2);
4886 s390x_psubw (code, ins->sreg1, ins->sreg2);
4889 s390x_psubd (code, ins->sreg1, ins->sreg2);
4892 s390x_psubq (code, ins->sreg1, ins->sreg2);
4896 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4899 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4902 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4906 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4909 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4912 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4916 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4919 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4923 s390x_pminub (code, ins->sreg1, ins->sreg2);
4926 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4929 s390x_pminud (code, ins->sreg1, ins->sreg2);
4933 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4936 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4939 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4943 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4946 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4949 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4952 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4956 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4959 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4962 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4965 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4968 case OP_PSUM_ABS_DIFF:
4969 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4972 case OP_UNPACK_LOWB:
4973 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4975 case OP_UNPACK_LOWW:
4976 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4978 case OP_UNPACK_LOWD:
4979 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4981 case OP_UNPACK_LOWQ:
4982 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4984 case OP_UNPACK_LOWPS:
4985 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
4987 case OP_UNPACK_LOWPD:
4988 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
4991 case OP_UNPACK_HIGHB:
4992 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
4994 case OP_UNPACK_HIGHW:
4995 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
4997 case OP_UNPACK_HIGHD:
4998 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5000 case OP_UNPACK_HIGHQ:
5001 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5003 case OP_UNPACK_HIGHPS:
5004 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5006 case OP_UNPACK_HIGHPD:
5007 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5011 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5014 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5017 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5020 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5023 case OP_PADDB_SAT_UN:
5024 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5026 case OP_PSUBB_SAT_UN:
5027 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5029 case OP_PADDW_SAT_UN:
5030 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5032 case OP_PSUBW_SAT_UN:
5033 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5037 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5040 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5043 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5046 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5050 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5053 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5056 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5058 case OP_PMULW_HIGH_UN:
5059 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5062 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5066 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5069 s390x_psrlw (code, ins->dreg, ins->sreg2);
5073 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5076 s390x_psraw (code, ins->dreg, ins->sreg2);
5080 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5083 s390x_psllw (code, ins->dreg, ins->sreg2);
5087 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5090 s390x_psrld (code, ins->dreg, ins->sreg2);
5094 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5097 s390x_psrad (code, ins->dreg, ins->sreg2);
5101 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5104 s390x_pslld (code, ins->dreg, ins->sreg2);
5108 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5111 s390x_psrlq (code, ins->dreg, ins->sreg2);
5114 /*TODO: This is appart of the sse spec but not added
5116 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5119 s390x_psraq (code, ins->dreg, ins->sreg2);
5124 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5127 s390x_psllq (code, ins->dreg, ins->sreg2);
5130 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5133 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5136 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5139 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5142 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5145 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5148 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5151 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5155 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5158 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5162 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5163 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5165 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5170 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5172 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5173 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5177 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5179 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5180 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5181 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5185 amd64_movhlps (code, ins->dreg, ins->sreg1);
5187 s390x_movsd (code, ins->dreg, ins->sreg1);
5190 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5192 case OP_EXTRACTX_U2:
5193 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5195 case OP_INSERTX_U1_SLOW:
5196 /*sreg1 is the extracted ireg (scratch)
5197 /sreg2 is the to be inserted ireg (scratch)
5198 /dreg is the xreg to receive the value*/
5200 /*clear the bits from the extracted word*/
5201 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5202 /*shift the value to insert if needed*/
5203 if (ins->inst_c0 & 1)
5204 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5205 /*join them together*/
5206 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5207 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5209 case OP_INSERTX_I4_SLOW:
5210 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5211 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5212 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5214 case OP_INSERTX_I8_SLOW:
5215 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5217 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5219 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5222 case OP_INSERTX_R4_SLOW:
5223 switch (ins->inst_c0) {
5226 s390x_movss (code, ins->dreg, ins->sreg2);
5228 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5231 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5233 s390x_movss (code, ins->dreg, ins->sreg2);
5235 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5236 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5239 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5241 s390x_movss (code, ins->dreg, ins->sreg2);
5243 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5244 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5247 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5249 s390x_movss (code, ins->dreg, ins->sreg2);
5251 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5252 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5256 case OP_INSERTX_R8_SLOW:
5258 amd64_movlhps (code, ins->dreg, ins->sreg2);
5260 s390x_movsd (code, ins->dreg, ins->sreg2);
5262 case OP_STOREX_MEMBASE_REG:
5263 case OP_STOREX_MEMBASE:
5264 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5266 case OP_LOADX_MEMBASE:
5267 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5269 case OP_LOADX_ALIGNED_MEMBASE:
5270 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5272 case OP_STOREX_ALIGNED_MEMBASE_REG:
5273 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5275 case OP_STOREX_NTA_MEMBASE_REG:
5276 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5278 case OP_PREFETCH_MEMBASE:
5279 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5283 /*FIXME the peephole pass should have killed this*/
5284 if (ins->dreg != ins->sreg1)
5285 s390x_movaps (code, ins->dreg, ins->sreg1);
5288 s390x_pxor (code, ins->dreg, ins->dreg);
5290 case OP_ICONV_TO_R4_RAW:
5291 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5294 case OP_FCONV_TO_R8_X:
5295 s390x_movsd (code, ins->dreg, ins->sreg1);
5298 case OP_XCONV_R8_TO_I4:
5299 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5300 switch (ins->backend.source_opcode) {
5301 case OP_FCONV_TO_I1:
5302 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5304 case OP_FCONV_TO_U1:
5305 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5307 case OP_FCONV_TO_I2:
5308 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5310 case OP_FCONV_TO_U2:
5311 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5317 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5318 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5319 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5322 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5323 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5326 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5327 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5331 s390x_movsd (code, ins->dreg, ins->sreg1);
5333 s390x_movsd (code, ins->dreg, ins->sreg1);
5334 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5336 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5339 s390x_movsd (code, ins->dreg, ins->sreg1);
5340 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5344 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5345 g_assert_not_reached ();
5348 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5349 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5350 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5351 g_assert_not_reached ();
5354 last_offset = offset;
5357 cfg->code_len = code - cfg->native_code;
5360 /*========================= End of Function ========================*/
5362 /*------------------------------------------------------------------*/
5364 /* Name - mono_arch_register_lowlevel_calls */
5366 /* Function - Register routines to help with --trace operation. */
5368 /*------------------------------------------------------------------*/
5371 mono_arch_register_lowlevel_calls (void)
5375 /*========================= End of Function ========================*/
5377 /*------------------------------------------------------------------*/
5379 /* Name - mono_arch_patch_code */
5381 /* Function - Process the patch data created during the */
5382 /* instruction build process. This resolves jumps, */
5383 /* calls, variables etc. */
5385 /*------------------------------------------------------------------*/
5388 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5389 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5392 MonoJumpInfo *patch_info;
5394 mono_error_init (error);
5396 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5397 unsigned char *ip = patch_info->ip.i + code;
5398 gconstpointer target = NULL;
5400 target = mono_resolve_patch_target (method, domain, code,
5401 patch_info, run_cctors, error);
5402 return_if_nok (error);
5404 switch (patch_info->type) {
5405 case MONO_PATCH_INFO_IP:
5406 case MONO_PATCH_INFO_LDSTR:
5407 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5408 case MONO_PATCH_INFO_LDTOKEN:
5409 case MONO_PATCH_INFO_EXC:
5410 s390_patch_addr (ip, (guint64) target);
5412 case MONO_PATCH_INFO_METHOD:
5413 case MONO_PATCH_INFO_INTERNAL_METHOD:
5414 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5415 case MONO_PATCH_INFO_RGCTX_FETCH:
5416 case MONO_PATCH_INFO_ABS: {
5417 S390_EMIT_CALL (ip, target);
5420 case MONO_PATCH_INFO_SWITCH:
5421 /*----------------------------------*/
5422 /* ip points at the basr r13,0/j +4 */
5423 /* instruction the vtable value */
5424 /* follows this (i.e. ip+6) */
5425 /*----------------------------------*/
5426 S390_EMIT_LOAD (ip, target);
5428 case MONO_PATCH_INFO_METHODCONST:
5429 case MONO_PATCH_INFO_CLASS:
5430 case MONO_PATCH_INFO_IMAGE:
5431 case MONO_PATCH_INFO_FIELD:
5432 case MONO_PATCH_INFO_IID:
5433 case MONO_PATCH_INFO_EXC_NAME:
5434 target = S390_RELATIVE(target, ip);
5435 s390_patch_rel (ip, (guint64) target);
5437 case MONO_PATCH_INFO_R4:
5438 case MONO_PATCH_INFO_R8:
5439 case MONO_PATCH_INFO_METHOD_REL:
5440 g_assert_not_reached ();
5443 target = S390_RELATIVE(target, ip);
5445 s390_patch_rel (ip, (guint64) target);
5450 /*========================= End of Function ========================*/
5452 /*------------------------------------------------------------------*/
5454 /* Name - emit_load_volatile_arguments */
5456 /* Function - Emit the instructions to reload parameter regist- */
5457 /* registers for use with "tail" operations. */
5459 /* The register loading operations performed here */
5460 /* are the mirror of the store operations performed */
5461 /* in mono_arch_emit_prolog and need to be kept in */
5462 /* synchronization with it. */
5464 /*------------------------------------------------------------------*/
5467 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5470 MonoMethod *method = cfg->method;
5471 MonoMethodSignature *sig = mono_method_signature(method);
5475 cinfo = get_call_info (NULL, NULL, sig);
5477 if (cinfo->struct_ret) {
5478 ArgInfo *ainfo = &cinfo->ret;
5479 inst = cfg->vret_addr;
5480 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5483 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5484 ArgInfo *ainfo = cinfo->args + i;
5485 inst = cfg->args [pos];
5487 if (inst->opcode == OP_REGVAR) {
5488 if (ainfo->regtype == RegTypeGeneral)
5489 s390_lgr (code, ainfo->reg, inst->dreg);
5490 else if (ainfo->regtype == RegTypeFP) {
5491 if (inst->dreg != ainfo->reg) {
5492 if (ainfo->size == 4) {
5493 s390_ldebr (code, ainfo->reg, inst->dreg);
5495 s390_ldr (code, ainfo->reg, inst->dreg);
5499 else if (ainfo->regtype == RegTypeBase) {
5501 g_assert_not_reached ();
5503 if (ainfo->regtype == RegTypeGeneral) {
5504 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5505 g_assert_not_reached();
5506 switch (ainfo->size) {
5508 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5511 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5514 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5517 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5520 } else if (ainfo->regtype == RegTypeBase) {
5521 } else if (ainfo->regtype == RegTypeFP) {
5522 if (ainfo->size == 8)
5523 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5524 else if (ainfo->size == 4)
5525 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5527 g_assert_not_reached ();
5528 } else if (ainfo->regtype == RegTypeStructByVal) {
5529 if (ainfo->reg != STK_BASE) {
5530 switch (ainfo->size) {
5532 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5535 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5538 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5541 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5545 } else if (ainfo->regtype == RegTypeStructByAddr) {
5546 if (ainfo->reg != STK_BASE) {
5547 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550 g_assert_not_reached ();
5558 /*========================= End of Function ========================*/
5560 /*------------------------------------------------------------------*/
5562 /* Name - mono_arch_emit_prolog */
5564 /* Function - Create the instruction sequence for a function */
5567 /*------------------------------------------------------------------*/
5570 mono_arch_emit_prolog (MonoCompile *cfg)
5572 MonoMethod *method = cfg->method;
5574 MonoMethodSignature *sig;
5576 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5585 cfg->code_size = 512;
5587 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5589 cfg->code_size += 256;
5590 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5591 cfg->code_size += 256;
5593 if (method->save_lmf)
5594 cfg->code_size += 200;
5596 cfg->native_code = code = g_malloc (cfg->code_size);
5598 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5599 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5600 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5601 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5602 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5604 if (cfg->arch.bkchain_reg != -1)
5605 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5607 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5608 cfg->used_int_regs |= 1 << 11;
5611 alloc_size = cfg->stack_offset;
5613 cfg->stack_usage = cfa_offset = alloc_size;
5614 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5615 s390_lgr (code, s390_r11, STK_BASE);
5616 if (s390_is_imm16 (alloc_size)) {
5617 s390_aghi (code, STK_BASE, -alloc_size);
5618 } else if (s390_is_imm32 (alloc_size)) {
5619 s390_agfi (code, STK_BASE, -alloc_size);
5621 int stackSize = alloc_size;
5622 while (stackSize > INT_MAX) {
5623 s390_agfi (code, STK_BASE, -INT_MAX);
5624 stackSize -= INT_MAX;
5626 s390_agfi (code, STK_BASE, -stackSize);
5628 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5630 if (cfg->frame_reg != STK_BASE)
5631 s390_lgr (code, s390_r11, STK_BASE);
5633 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5635 /* store runtime generic context */
5636 if (cfg->rgctx_var) {
5637 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5639 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5640 cfg->rgctx_var->inst_basereg,
5641 cfg->rgctx_var->inst_offset);
5644 /* compute max_offset in order to use short forward jumps
5645 * we always do it on s390 because the immediate displacement
5646 * for jumps is too small
5649 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5651 bb->max_offset = max_offset;
5653 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5656 MONO_BB_FOR_EACH_INS (bb, ins)
5657 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5660 /* load arguments allocated to register from the stack */
5661 sig = mono_method_signature (method);
5664 cinfo = get_call_info (cfg, cfg->mempool, sig);
5666 if (cinfo->struct_ret) {
5667 ArgInfo *ainfo = &cinfo->ret;
5668 inst = cfg->vret_addr;
5669 inst->backend.size = ainfo->vtsize;
5670 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5673 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5674 ArgInfo *ainfo = cinfo->args + i;
5675 inst = cfg->args [pos];
5677 if (inst->opcode == OP_VTARG_ADDR)
5678 inst = inst->inst_left;
5680 if (inst->opcode == OP_REGVAR) {
5681 if (ainfo->regtype == RegTypeGeneral)
5682 s390_lgr (code, inst->dreg, ainfo->reg);
5683 else if (ainfo->regtype == RegTypeFP) {
5684 if (inst->dreg != ainfo->reg) {
5685 if (ainfo->size == 4) {
5686 s390_ledbr (code, inst->dreg, ainfo->reg);
5688 s390_ldr (code, inst->dreg, ainfo->reg);
5692 else if (ainfo->regtype == RegTypeBase) {
5693 s390_lgr (code, s390_r13, STK_BASE);
5694 s390_aghi (code, s390_r13, alloc_size);
5695 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5697 g_assert_not_reached ();
5699 if (cfg->verbose_level > 2)
5700 g_print ("Argument %d assigned to register %s\n",
5701 pos, mono_arch_regname (inst->dreg));
5703 if (ainfo->regtype == RegTypeGeneral) {
5704 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5705 g_assert_not_reached();
5706 switch (ainfo->size) {
5708 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5711 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5714 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5717 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5720 } else if (ainfo->regtype == RegTypeBase) {
5721 } else if (ainfo->regtype == RegTypeFP) {
5722 if (ainfo->size == 8)
5723 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5724 else if (ainfo->size == 4)
5725 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5727 g_assert_not_reached ();
5728 } else if (ainfo->regtype == RegTypeStructByVal) {
5729 int doffset = inst->inst_offset;
5731 if (ainfo->reg != STK_BASE)
5735 s390_lgr (code, s390_r13, STK_BASE);
5736 s390_aghi (code, s390_r13, alloc_size);
5739 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5740 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5745 if (ainfo->reg == STK_BASE)
5746 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5747 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5750 if (ainfo->reg == STK_BASE)
5751 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5752 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5755 if (ainfo->reg == STK_BASE)
5756 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5757 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5760 if (ainfo->reg == STK_BASE)
5761 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5762 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5765 } else if (ainfo->regtype == RegTypeStructByAddr) {
5766 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5767 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5769 g_assert_not_reached ();
5774 if (method->save_lmf) {
5775 /*---------------------------------------------------------------*/
5776 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5777 /*---------------------------------------------------------------*/
5778 lmfOffset = alloc_size - sizeof(MonoLMF);
5780 s390_lgr (code, s390_r13, cfg->frame_reg);
5781 s390_aghi (code, s390_r13, lmfOffset);
5783 /*---------------------------------------------------------------*/
5784 /* Preserve the parameter registers while we fix up the lmf */
5785 /*---------------------------------------------------------------*/
5786 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5787 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5789 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5790 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5791 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5792 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5793 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5795 /*---------------------------------------------------------------*/
5796 /* On return from this call r2 have the address of the &lmf */
5797 /*---------------------------------------------------------------*/
5798 if (lmf_addr_tls_offset == -1) {
5799 mono_add_patch_info (cfg, code - cfg->native_code,
5800 MONO_PATCH_INFO_INTERNAL_METHOD,
5801 (gpointer)"mono_get_lmf_addr");
5802 S390_CALL_TEMPLATE(code, s390_r1);
5804 /*-------------------------------------------------------*/
5805 /* Get LMF by getting value from thread level storage */
5806 /*-------------------------------------------------------*/
5807 s390_ear (code, s390_r1, 0);
5808 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5809 s390_ear (code, s390_r1, 1);
5810 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5813 /*---------------------------------------------------------------*/
5814 /* Set lmf.lmf_addr = jit_tls->lmf */
5815 /*---------------------------------------------------------------*/
5816 s390_stg (code, s390_r2, 0, s390_r13,
5817 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5818 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5820 /*---------------------------------------------------------------*/
5821 /* Get current lmf */
5822 /*---------------------------------------------------------------*/
5823 s390_lg (code, s390_r0, 0, s390_r2, 0);
5825 /*---------------------------------------------------------------*/
5826 /* Set our lmf as the current lmf */
5827 /*---------------------------------------------------------------*/
5828 s390_stg (code, s390_r13, 0, s390_r2, 0);
5830 /*---------------------------------------------------------------*/
5831 /* Have our lmf.previous_lmf point to the last lmf */
5832 /*---------------------------------------------------------------*/
5833 s390_stg (code, s390_r0, 0, s390_r13,
5834 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5835 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5837 /*---------------------------------------------------------------*/
5838 /* save method info */
5839 /*---------------------------------------------------------------*/
5840 S390_SET (code, s390_r1, method);
5841 s390_stg (code, s390_r1, 0, s390_r13,
5842 G_STRUCT_OFFSET(MonoLMF, method));
5843 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5845 /*---------------------------------------------------------------*/
5846 /* save the current IP */
5847 /*---------------------------------------------------------------*/
5848 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5849 s390_basr (code, s390_r1, 0);
5850 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5851 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5852 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5854 /*---------------------------------------------------------------*/
5855 /* Save general and floating point registers */
5856 /*---------------------------------------------------------------*/
5857 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5858 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5859 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5860 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5861 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5862 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5866 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5867 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5868 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5869 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5871 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5872 for (i = 0; i < 16; i++) {
5873 s390_std (code, i, 0, s390_r13,
5874 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5875 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5876 fpOffset += sizeof(double);
5879 /*---------------------------------------------------------------*/
5880 /* Restore the parameter registers now that we've set up the lmf */
5881 /*---------------------------------------------------------------*/
5882 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5883 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5886 if (cfg->method->save_lmf)
5887 argsClobbered = TRUE;
5890 argsClobbered = TRUE;
5891 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5894 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5895 argsClobbered = TRUE;
5898 * Optimize the common case of the first bblock making a call with the same
5899 * arguments as the method. This works because the arguments are still in their
5900 * original argument registers.
5902 if (!argsClobbered) {
5903 MonoBasicBlock *first_bb = cfg->bb_entry;
5905 int filter = FILTER_IL_SEQ_POINT;
5907 next = mono_bb_first_inst (first_bb, filter);
5908 if (!next && first_bb->next_bb) {
5909 first_bb = first_bb->next_bb;
5910 next = mono_bb_first_inst (first_bb, filter);
5913 if (first_bb->in_count > 1)
5916 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5917 ArgInfo *ainfo = cinfo->args + i;
5918 gboolean match = FALSE;
5920 inst = cfg->args [i];
5921 if (inst->opcode != OP_REGVAR) {
5922 switch (ainfo->regtype) {
5923 case RegTypeGeneral: {
5924 if (((next->opcode == OP_LOAD_MEMBASE) ||
5925 (next->opcode == OP_LOADI4_MEMBASE)) &&
5926 next->inst_basereg == inst->inst_basereg &&
5927 next->inst_offset == inst->inst_offset) {
5928 if (next->dreg == ainfo->reg) {
5932 next->opcode = OP_MOVE;
5933 next->sreg1 = ainfo->reg;
5934 /* Only continue if the instruction doesn't change argument regs */
5935 if (next->dreg == ainfo->reg)
5945 /* Argument allocated to (non-volatile) register */
5946 switch (ainfo->regtype) {
5947 case RegTypeGeneral:
5948 if (next->opcode == OP_MOVE &&
5949 next->sreg1 == inst->dreg &&
5950 next->dreg == ainfo->reg) {
5961 next = mono_inst_next (next, filter);
5968 cfg->code_len = code - cfg->native_code;
5969 g_assert (cfg->code_len < cfg->code_size);
5974 /*========================= End of Function ========================*/
5976 /*------------------------------------------------------------------*/
5978 /* Name - mono_arch_emit_epilog */
5980 /* Function - Emit the instructions for a function epilog. */
5982 /*------------------------------------------------------------------*/
5985 mono_arch_emit_epilog (MonoCompile *cfg)
5987 MonoMethod *method = cfg->method;
5990 int max_epilog_size = 96;
5992 if (cfg->method->save_lmf)
5993 max_epilog_size += 128;
5995 if (mono_jit_trace_calls != NULL)
5996 max_epilog_size += 128;
5997 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5998 max_epilog_size += 128;
6000 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6001 cfg->code_size *= 2;
6002 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6003 cfg->stat_code_reallocs++;
6006 code = cfg->native_code + cfg->code_len;
6008 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6009 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6013 if (method->save_lmf)
6014 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6016 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6017 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6019 code = backUpStackPtr(cfg, code);
6021 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6022 s390_br (code, s390_r14);
6024 cfg->code_len = code - cfg->native_code;
6026 g_assert (cfg->code_len < cfg->code_size);
6030 /*========================= End of Function ========================*/
6032 /*------------------------------------------------------------------*/
6034 /* Name - mono_arch_emit_exceptions */
6036 /* Function - Emit the blocks to handle exception conditions. */
6038 /*------------------------------------------------------------------*/
6041 mono_arch_emit_exceptions (MonoCompile *cfg)
6043 MonoJumpInfo *patch_info;
6049 MonoClass *exc_classes [MAX_EXC];
6050 guint8 *exc_throw_start [MAX_EXC];
6052 for (patch_info = cfg->patch_info;
6054 patch_info = patch_info->next) {
6055 if (patch_info->type == MONO_PATCH_INFO_EXC)
6059 code_size = exc_count * 48;
6061 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6062 cfg->code_size *= 2;
6063 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6064 cfg->stat_code_reallocs++;
6067 code = cfg->native_code + cfg->code_len;
6069 /*---------------------------------------------------------------------*/
6070 /* Add code to raise exceptions */
6071 /*---------------------------------------------------------------------*/
6072 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6073 switch (patch_info->type) {
6074 case MONO_PATCH_INFO_EXC: {
6075 guint8 *ip = patch_info->ip.i + cfg->native_code;
6076 MonoClass *exc_class;
6079 /*-----------------------------------------------------*/
6080 /* Patch the branch in epilog to come here */
6081 /*-----------------------------------------------------*/
6082 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6084 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6086 patch_info->data.name);
6087 throw_ip = patch_info->ip.i;
6089 for (iExc = 0; iExc < nThrows; ++iExc)
6090 if (exc_classes [iExc] == exc_class)
6093 if (iExc < nThrows) {
6094 s390_jcl (code, S390_CC_UN,
6095 (guint64) exc_throw_start [iExc]);
6096 patch_info->type = MONO_PATCH_INFO_NONE;
6099 if (nThrows < MAX_EXC) {
6100 exc_classes [nThrows] = exc_class;
6101 exc_throw_start [nThrows] = code;
6104 /*---------------------------------------------*/
6105 /* Patch the parameter passed to the handler */
6106 /*---------------------------------------------*/
6107 S390_SET (code, s390_r2, exc_class->type_token);
6108 /*---------------------------------------------*/
6109 /* Load return address & parameter register */
6110 /*---------------------------------------------*/
6111 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6112 cfg->native_code + 8), code));
6113 /*---------------------------------------------*/
6114 /* Reuse the current patch to set the jump */
6115 /*---------------------------------------------*/
6116 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6117 patch_info->data.name = "mono_arch_throw_corlib_exception";
6118 patch_info->ip.i = code - cfg->native_code;
6119 S390_BR_TEMPLATE (code, s390_r1);
6129 cfg->code_len = code - cfg->native_code;
6131 g_assert (cfg->code_len < cfg->code_size);
6135 /*========================= End of Function ========================*/
6137 /*------------------------------------------------------------------*/
6139 /* Name - mono_arch_finish_init */
6141 /* Function - Setup the JIT's Thread Level Specific Data. */
6143 /*------------------------------------------------------------------*/
6146 mono_arch_finish_init (void)
6148 appdomain_tls_offset = mono_domain_get_tls_offset();
6149 lmf_tls_offset = mono_get_lmf_tls_offset();
6150 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6153 /*========================= End of Function ========================*/
6155 /*------------------------------------------------------------------*/
6157 /* Name - mono_arch_free_jit_tls_data */
6159 /* Function - Free tls data. */
6161 /*------------------------------------------------------------------*/
6164 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6168 /*========================= End of Function ========================*/
6170 /*------------------------------------------------------------------*/
6172 /* Name - mono_arch_emit_inst_for_method */
6174 /*------------------------------------------------------------------*/
6177 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6182 /*========================= End of Function ========================*/
6184 /*------------------------------------------------------------------*/
6186 /* Name - mono_arch_decompose_opts */
6188 /* Function - Decompose opcode into a System z opcode. */
6190 /*------------------------------------------------------------------*/
6193 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6196 * Have to rename these to avoid being decomposed normally, since the normal
6197 * decomposition does not work on S390.
6199 switch (ins->opcode) {
6201 ins->opcode = OP_S390_ISUB_OVF;
6203 case OP_ISUB_OVF_UN:
6204 ins->opcode = OP_S390_ISUB_OVF_UN;
6207 ins->opcode = OP_S390_IADD_OVF;
6209 case OP_IADD_OVF_UN:
6210 ins->opcode = OP_S390_IADD_OVF_UN;
6213 ins->opcode = OP_S390_LADD_OVF;
6215 case OP_LADD_OVF_UN:
6216 ins->opcode = OP_S390_LADD_OVF_UN;
6219 ins->opcode = OP_S390_LSUB_OVF;
6221 case OP_LSUB_OVF_UN:
6222 ins->opcode = OP_S390_LSUB_OVF_UN;
6229 /*========================= End of Function ========================*/
6231 /*------------------------------------------------------------------*/
6233 /* Name - mono_arch_print_tree */
6235 /* Function - Print platform-specific opcode details. */
6237 /* Returns - 1 - opcode details have been printed */
6238 /* 0 - opcode details have not been printed */
6240 /*------------------------------------------------------------------*/
6243 mono_arch_print_tree (MonoInst *tree, int arity)
6247 switch (tree->opcode) {
6248 case OP_S390_LOADARG:
6249 case OP_S390_ARGREG:
6250 case OP_S390_ARGPTR:
6251 printf ("[0x%lx(%s)]", tree->inst_offset,
6252 mono_arch_regname (tree->inst_basereg));
6255 case OP_S390_STKARG:
6256 printf ("[0x%lx(previous_frame)]",
6261 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6262 tree->inst_offset, tree->backend.size,
6263 mono_arch_regname(tree->dreg),
6265 mono_arch_regname(tree->sreg1));
6268 case OP_S390_SETF4RET:
6269 printf ("[f%s,f%s]",
6270 mono_arch_regname (tree->dreg),
6271 mono_arch_regname (tree->sreg1));
6275 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6277 mono_arch_regname (tree->sreg1));
6280 case OP_S390_BKCHAIN:
6281 printf ("[previous_frame(%s)]",
6282 mono_arch_regname (tree->sreg1));
6290 /*========================= End of Function ========================*/
6292 /*------------------------------------------------------------------*/
6294 /* Name - mono_arch_regalloc_cost */
6296 /* Function - Determine the cost, in the number of memory */
6297 /* references, of the action of allocating the var- */
6298 /* iable VMV into a register during global register */
6301 /* Returns - Cost */
6303 /*------------------------------------------------------------------*/
6306 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6312 /*========================= End of Function ========================*/
6314 /*------------------------------------------------------------------*/
6316 /* Name - mono_arch_flush_register_windows */
6322 /*------------------------------------------------------------------*/
6325 mono_arch_flush_register_windows (void)
6329 /*========================= End of Function ========================*/
6331 /*------------------------------------------------------------------*/
6333 /* Name - mono_arch_is_inst_imm */
6335 /* Function - Determine if operand qualifies as an immediate */
6336 /* value. For s390 this is a value -32768-32768 */
6338 /* Returns - True|False - is [not] immediate value. */
6340 /*------------------------------------------------------------------*/
6343 mono_arch_is_inst_imm (gint64 imm)
6345 return s390_is_imm32 (imm);
6348 /*========================= End of Function ========================*/
6350 /*------------------------------------------------------------------*/
6352 /* Name - mono_arch_get_patch_offset */
6354 /* Function - Dummy entry point until s390x supports aot. */
6356 /* Returns - Offset for patch. */
6358 /*------------------------------------------------------------------*/
6361 mono_arch_get_patch_offset (guint8 *code)
6366 /*========================= End of Function ========================*/
6368 /*------------------------------------------------------------------*/
6370 /* Name - mono_arch_context_get_int_reg. */
6374 /* Returns - Return a register from the context. */
6376 /*------------------------------------------------------------------*/
6379 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6381 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6384 /*========================= End of Function ========================*/
6386 /*------------------------------------------------------------------*/
6388 /* Name - mono_arch_context_set_int_reg. */
6390 /* Function - Set a value in a specified register. */
6392 /*------------------------------------------------------------------*/
6395 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6397 ctx->uc_mcontext.gregs[reg] = val;
6400 /*========================= End of Function ========================*/
6402 /*------------------------------------------------------------------*/
6404 /* Name - mono_arch_get_this_arg_from_call. */
6408 /*------------------------------------------------------------------*/
6411 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6413 return (gpointer) regs [s390_r2];
6416 /*========================= End of Function ========================*/
6418 /*------------------------------------------------------------------*/
6420 /* Name - mono_arch_install_handler_block_guard */
6424 /*------------------------------------------------------------------*/
6427 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6428 MonoContext *ctx, gpointer new_value)
6431 gpointer *sp, old_value;
6434 offset = clause->exvar_offset;
6437 bp = MONO_CONTEXT_GET_BP (ctx);
6438 sp = *(gpointer*)(bp + offset);
6441 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6449 /*========================= End of Function ========================*/
6451 /*------------------------------------------------------------------*/
6453 /* Name - get_delegate_invoke_impl. */
6457 /*------------------------------------------------------------------*/
6460 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6462 guint8 *code, *start;
6467 start = code = mono_global_codeman_reserve (size);
6469 /* Replace the this argument with the target */
6470 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6471 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6472 s390_br (code, s390_r1);
6473 g_assert ((code - start) <= size);
6475 mono_arch_flush_icache (start, size);
6479 size = 32 + param_count * 8;
6480 start = code = mono_global_codeman_reserve (size);
6482 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6483 /* slide down the arguments */
6484 for (i = 0; i < param_count; ++i) {
6485 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6487 s390_br (code, s390_r1);
6489 g_assert ((code - start) <= size);
6491 mono_arch_flush_icache (start, size);
6494 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6497 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6499 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6500 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6507 /*========================= End of Function ========================*/
6509 /*------------------------------------------------------------------*/
6511 /* Name - mono_arch_get_delegate_invoke_impls. */
6515 /*------------------------------------------------------------------*/
6518 mono_arch_get_delegate_invoke_impls (void)
6521 MonoTrampInfo *info;
6524 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6525 res = g_slist_prepend (res, info);
6527 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6528 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6529 res = g_slist_prepend (res, info);
6535 /*========================= End of Function ========================*/
6537 /*------------------------------------------------------------------*/
6539 /* Name - mono_arch_get_delegate_invoke_impl. */
6543 /*------------------------------------------------------------------*/
6546 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6548 guint8 *code, *start;
6550 /* FIXME: Support more cases */
6551 if (MONO_TYPE_ISSTRUCT (sig->ret))
6555 static guint8* cached = NULL;
6560 if (mono_aot_only) {
6561 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6563 MonoTrampInfo *info;
6564 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6565 mono_tramp_info_register (info, NULL);
6568 mono_memory_barrier ();
6572 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6575 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6577 for (i = 0; i < sig->param_count; ++i)
6578 if (!mono_is_regsize_var (sig->params [i]))
6582 code = cache [sig->param_count];
6586 if (mono_aot_only) {
6587 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6588 start = mono_aot_get_trampoline (name);
6591 MonoTrampInfo *info;
6592 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6593 mono_tramp_info_register (info, NULL);
6596 mono_memory_barrier ();
6598 cache [sig->param_count] = start;
6603 /*========================= End of Function ========================*/
6605 /*------------------------------------------------------------------*/
6607 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6611 /*------------------------------------------------------------------*/
6614 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6615 int offset, gboolean load_imt_reg)
6617 guint8 *code, *start;
6620 start = code = mono_global_codeman_reserve (size);
6623 * Replace the "this" argument with the target
6625 s390_lgr (code, s390_r1, s390_r2);
6626 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6629 * Load the IMT register, if needed
6632 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6638 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6640 s390_agfi(code, s390_r1, offset);
6642 s390_lg (code, s390_r1, 0, s390_r1, 0);
6643 s390_br (code, s390_r1);
6648 /*========================= End of Function ========================*/
6650 /*------------------------------------------------------------------*/
6652 /* Name - mono_arch_build_imt_thunk. */
6656 /*------------------------------------------------------------------*/
6659 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
6660 MonoIMTCheckItem **imt_entries, int count,
6661 gpointer fail_tramp)
6665 guchar *code, *start;
6668 for (i = 0; i < count; ++i) {
6669 MonoIMTCheckItem *item = imt_entries [i];
6670 if (item->is_equals) {
6671 if (item->check_target_idx) {
6672 if (!item->compare_done)
6673 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6674 if (item->has_target_code)
6675 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6677 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6681 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6683 if (!item->has_target_code)
6684 item->chunk_size += LOAD_SIZE;
6686 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6687 #if ENABLE_WRONG_METHOD_CHECK
6688 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6693 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6694 imt_entries [item->check_target_idx]->compare_done = TRUE;
6696 size += item->chunk_size;
6700 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6702 code = mono_domain_code_reserve (domain, size);
6706 for (i = 0; i < count; ++i) {
6707 MonoIMTCheckItem *item = imt_entries [i];
6708 item->code_target = (guint8 *) code;
6709 if (item->is_equals) {
6710 if (item->check_target_idx) {
6711 if (!item->compare_done) {
6712 S390_SET (code, s390_r0, item->key);
6713 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6715 item->jmp_code = (guint8*) code;
6716 s390_jcl (code, S390_CC_NE, 0);
6718 if (item->has_target_code) {
6719 S390_SET (code, s390_r1, item->value.target_code);
6721 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6722 s390_lg (code, s390_r1, 0, s390_r1, 0);
6724 s390_br (code, s390_r1);
6729 S390_SET (code, s390_r0, item->key);
6730 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6731 item->jmp_code = (guint8*) code;
6732 s390_jcl (code, S390_CC_NE, 0);
6733 if (item->has_target_code) {
6734 S390_SET (code, s390_r1, item->value.target_code);
6737 S390_SET (code, s390_r1,
6738 (&(vtable->vtable [item->value.vtable_slot])));
6739 s390_lg (code, s390_r1, 0, s390_r1, 0);
6741 s390_br (code, s390_r1);
6742 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6743 s390_patch_rel(item->jmp_code+2, target);
6744 S390_SET (code, s390_r1, fail_tramp);
6745 s390_br (code, s390_r1);
6746 item->jmp_code = NULL;
6748 /* enable the commented code to assert on wrong method */
6749 #if ENABLE_WRONG_METHOD_CHECK
6750 g_assert_not_reached ();
6752 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6753 s390_lg (code, s390_r1, 0, s390_r1, 0);
6754 s390_br (code, s390_r1);
6758 S390_SET (code, s390_r0, item->key);
6759 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6760 item->jmp_code = (guint8 *) code;
6761 s390_jcl (code, S390_CC_GE, 0);
6765 * patch the branches to get to the target items
6767 for (i = 0; i < count; ++i) {
6768 MonoIMTCheckItem *item = imt_entries [i];
6769 if (item->jmp_code) {
6770 if (item->check_target_idx) {
6772 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6774 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6779 mono_arch_flush_icache ((guint8*)start, (code - start));
6780 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6783 mono_stats.imt_thunks_size += (code - start);
6785 g_assert (code - start <= size);
6787 snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6788 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6793 /*========================= End of Function ========================*/
6795 /*------------------------------------------------------------------*/
6797 /* Name - mono_arch_find_imt_method. */
6799 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6800 /* found in the save area. */
6802 /*------------------------------------------------------------------*/
6805 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6807 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6810 /*========================= End of Function ========================*/
6812 /*------------------------------------------------------------------*/
6814 /* Name - mono_arch_find_static_call_vtable */
6816 /* Function - Find the static call vtable. */
6818 /*------------------------------------------------------------------*/
6821 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6823 mgreg_t *r = (mgreg_t*)regs;
6825 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6828 /*========================= End of Function ========================*/
6830 /*------------------------------------------------------------------*/
6832 /* Name - mono_arch_get_cie_program */
6834 /* Function - Find the static call vtable. */
6836 /*------------------------------------------------------------------*/
6839 mono_arch_get_cie_program (void)
6843 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6848 /*========================= End of Function ========================*/
6850 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6852 /*------------------------------------------------------------------*/
6854 /* Name - mono_arch_set_breakpoint. */
6856 /* Function - Set a breakpoint at the native code corresponding */
6857 /* to JI at NATIVE_OFFSET. The location should */
6858 /* contain code emitted by OP_SEQ_POINT. */
6860 /*------------------------------------------------------------------*/
6863 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6867 breakpointCode.pTrigger = bp_trigger_page;
6868 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6869 code += BREAKPOINT_SIZE;
6872 /*========================= End of Function ========================*/
6874 /*------------------------------------------------------------------*/
6876 /* Name - mono_arch_clear_breakpoint. */
6878 /* Function - Clear the breakpoint at IP. */
6880 /*------------------------------------------------------------------*/
6883 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6888 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6892 /*========================= End of Function ========================*/
6894 /*------------------------------------------------------------------*/
6896 /* Name - mono_arch_is_breakpoint_event. */
6900 /*------------------------------------------------------------------*/
6903 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6905 siginfo_t* sinfo = (siginfo_t*) info;
6908 * Sometimes the address is off by 4
6910 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6916 /*========================= End of Function ========================*/
6918 /*------------------------------------------------------------------*/
6920 /* Name - mono_arch_skip_breakpoint. */
6922 /* Function - Modify the CTX so the IP is placed after the */
6923 /* breakpoint instruction, so when we resume, the */
6924 /* instruction is not executed again. */
6926 /*------------------------------------------------------------------*/
6929 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6931 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6934 /*========================= End of Function ========================*/
6936 /*------------------------------------------------------------------*/
6938 /* Name - mono_arch_start_single_stepping. */
6940 /* Function - Start single stepping. */
6942 /*------------------------------------------------------------------*/
6945 mono_arch_start_single_stepping (void)
6947 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6950 /*========================= End of Function ========================*/
6952 /*------------------------------------------------------------------*/
6954 /* Name - mono_arch_stop_single_stepping. */
6956 /* Function - Stop single stepping. */
6958 /*------------------------------------------------------------------*/
6961 mono_arch_stop_single_stepping (void)
6963 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6966 /*========================= End of Function ========================*/
6968 /*------------------------------------------------------------------*/
6970 /* Name - mono_arch_is_single_step_event. */
6972 /* Function - Return whether the machine state in sigctx cor- */
6973 /* responds to a single step event. */
6975 /*------------------------------------------------------------------*/
6978 mono_arch_is_single_step_event (void *info, void *sigctx)
6980 siginfo_t* sinfo = (siginfo_t*) info;
6983 * Sometimes the address is off by 4
6985 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
6991 /*========================= End of Function ========================*/
6993 /*------------------------------------------------------------------*/
6995 /* Name - mono_arch_skip_single_step. */
6997 /* Function - Modify the ctx so the IP is placed after the */
6998 /* single step trigger instruction, so that the */
6999 /* instruction is not executed again. */
7001 /*------------------------------------------------------------------*/
7004 mono_arch_skip_single_step (MonoContext *ctx)
7006 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7009 /*========================= End of Function ========================*/
7011 /*------------------------------------------------------------------*/
7013 /* Name - mono_arch_create_seq_point_info. */
7015 /* Function - Return a pointer to a data struction which is */
7016 /* used by the sequence point implementation in */
7019 /*------------------------------------------------------------------*/
7022 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7028 /*========================= End of Function ========================*/
7030 /*------------------------------------------------------------------*/
7032 /* Name - mono_arch_init_lmf_ext. */
7036 /*------------------------------------------------------------------*/
7039 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7041 ext->lmf.previous_lmf = prev_lmf;
7042 /* Mark that this is a MonoLMFExt */
7043 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7044 ext->lmf.ebp = (gssize)ext;
7047 /*========================= End of Function ========================*/
7051 /*------------------------------------------------------------------*/
7053 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7055 /* Function - If this CPU supports vector operations then it */
7056 /* supports the equivalent of SSE1-4. */
7058 /*------------------------------------------------------------------*/
7061 mono_arch_cpu_enumerate_simd_versions (void)
7063 guint32 sseOpts = 0;
7066 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7067 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7068 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7069 SIMD_VERSION_SSE4a);
7074 /*========================= End of Function ========================*/
7076 /*------------------------------------------------------------------*/
7078 /* Name - mono_arch_opcode_supported. */
7080 /* Function - Check if a given return code is supported. */
7082 /*------------------------------------------------------------------*/
7085 mono_arch_opcode_supported (int opcode)
7088 case OP_ATOMIC_ADD_I4:
7089 case OP_ATOMIC_ADD_I8:
7090 case OP_ATOMIC_EXCHANGE_I4:
7091 case OP_ATOMIC_EXCHANGE_I8:
7098 /*========================= End of Function ========================*/