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 decodeParmString (MonoString *s)
771 char *str = mono_string_to_utf8(s, &error);
772 if (is_ok (&error)) {
773 printf("[STRING:%p:%s], ", s, str);
776 mono_error_cleanup (&error);
777 printf("[STRING:%p:], ", s);
782 decodeParm(MonoType *type, void *curParm, int size)
787 printf("[BYREF:%p], ", *((char **) curParm));
789 simpleType = mini_get_underlying_type(type)->type;
791 switch (simpleType) {
793 printf ("[INTPTR:%p], ", *((int **) curParm));
796 printf ("[UINTPTR:%p], ", *((int **) curParm));
798 case MONO_TYPE_BOOLEAN :
799 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
801 case MONO_TYPE_CHAR :
802 printf ("[CHAR:%c], ", *((int *) curParm));
805 printf ("[INT1:%ld], ", *((gint64 *) curParm));
808 printf ("[INT2:%ld], ", *((gint64 *) curParm));
811 printf ("[INT4:%ld], ", *((gint64 *) curParm));
814 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
817 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
820 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
823 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
825 case MONO_TYPE_STRING : {
826 MonoString *s = *((MonoString **) curParm);
828 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
829 decodeParmString (s);
831 printf("[STRING:null], ");
835 case MONO_TYPE_CLASS :
836 case MONO_TYPE_OBJECT : {
837 MonoObject *obj = *((MonoObject **) curParm);
839 if ((obj) && (obj->vtable)) {
840 printf("[CLASS/OBJ:");
841 klass = obj->vtable->klass;
842 printf("%p [%p] ",obj,curParm);
843 if (klass == mono_defaults.string_class) {
844 decodeParmString ((MonoString *)obj);
845 } else if (klass == mono_defaults.int32_class) {
846 printf("[INT32:%p:%d]",
847 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
850 klass->name_space, klass->name, obj);
853 printf("[OBJECT:null], ");
858 printf("[PTR:%p], ", *((gpointer **) (curParm)));
860 case MONO_TYPE_FNPTR :
861 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
863 case MONO_TYPE_ARRAY :
864 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
866 case MONO_TYPE_SZARRAY :
867 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
870 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
873 printf("[FLOAT4:%g], ", *((float *) (curParm)));
876 printf("[FLOAT8:%g], ", *((double *) (curParm)));
878 case MONO_TYPE_VALUETYPE : {
880 MonoMarshalType *info;
882 if (type->data.klass->enumtype) {
883 simpleType = mono_class_enum_basetype (type->data.klass)->type;
884 printf("{VALUETYPE} - ");
888 info = mono_marshal_load_type_info (type->data.klass);
890 if ((info->native_size == sizeof(float)) &&
891 (info->num_fields == 1) &&
892 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
893 printf("[FLOAT4:%f], ", *((float *) (curParm)));
897 if ((info->native_size == sizeof(double)) &&
898 (info->num_fields == 1) &&
899 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
900 printf("[FLOAT8:%g], ", *((double *) (curParm)));
904 printf("[VALUETYPE:");
905 for (i = 0; i < size; i++)
906 printf("%02x,", *((guint8 *)curParm+i));
910 case MONO_TYPE_TYPEDBYREF: {
912 printf("[TYPEDBYREF:");
913 for (i = 0; i < size; i++)
914 printf("%02x,", *((guint8 *)curParm+i));
919 printf("[%s], ",cvtMonoType(simpleType));
924 /*========================= End of Function ========================*/
926 /*------------------------------------------------------------------*/
928 /* Name - enter_method */
930 /* Function - Perform tracing of the entry to the current */
933 /*------------------------------------------------------------------*/
936 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
938 int i, oParm = 0, iParm = 0;
941 MonoMethodSignature *sig;
948 fname = mono_method_full_name (method, TRUE);
950 printf ("ENTER: %s ", fname);
953 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
954 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
959 sig = mono_method_signature (method);
961 cinfo = get_call_info (NULL, NULL, sig);
963 if (cinfo->struct_ret) {
964 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
969 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
970 obj = (MonoObject *) this_arg;
971 switch(method->klass->this_arg.type) {
972 case MONO_TYPE_VALUETYPE:
974 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
975 printf("this:[value:%p:%016lx], ", this_arg, *value);
977 printf ("this:[NULL], ");
979 case MONO_TYPE_STRING:
982 klass = obj->vtable->klass;
983 if (klass == mono_defaults.string_class) {
985 decodeParmString((MonoString *)obj);
987 printf ("this:%p[%s.%s], ",
988 obj, klass->name_space, klass->name);
991 printf("vtable:[NULL], ");
993 printf ("this:[NULL], ");
996 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1001 for (i = 0; i < sig->param_count; ++i) {
1002 ainfo = &cinfo->args[i + oParm];
1003 switch (ainfo->regtype) {
1004 case RegTypeGeneral :
1005 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1008 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1011 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1013 case RegTypeStructByVal :
1014 if (ainfo->reg != STK_BASE) {
1015 int offset = sizeof(glong) - ainfo->size;
1016 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1019 curParm = sp+ainfo->offset;
1021 if (retFitsInReg (ainfo->vtsize))
1022 decodeParm(sig->params[i],
1026 decodeParm(sig->params[i],
1027 *((char **) curParm),
1030 case RegTypeStructByAddr :
1031 if (ainfo->reg != STK_BASE)
1032 curParm = &(rParm->gr[ainfo->reg-2]);
1034 curParm = sp+ainfo->offset;
1036 decodeParm(sig->params[i],
1037 *((char **) curParm),
1049 /*========================= End of Function ========================*/
1051 /*------------------------------------------------------------------*/
1053 /* Name - leave_method */
1057 /*------------------------------------------------------------------*/
1060 leave_method (MonoMethod *method, ...)
1067 va_start(ap, method);
1069 fname = mono_method_full_name (method, TRUE);
1071 printf ("LEAVE: %s", fname);
1074 type = mono_method_signature (method)->ret;
1077 switch (type->type) {
1078 case MONO_TYPE_VOID:
1080 case MONO_TYPE_BOOLEAN: {
1081 int val = va_arg (ap, int);
1083 printf ("[TRUE:%d]", val);
1089 case MONO_TYPE_CHAR: {
1090 int val = va_arg (ap, int);
1091 printf ("[CHAR:%d]", val);
1094 case MONO_TYPE_I1: {
1095 int val = va_arg (ap, int);
1096 printf ("[INT1:%d]", val);
1099 case MONO_TYPE_U1: {
1100 int val = va_arg (ap, int);
1101 printf ("[UINT1:%d]", val);
1104 case MONO_TYPE_I2: {
1105 int val = va_arg (ap, int);
1106 printf ("[INT2:%d]", val);
1109 case MONO_TYPE_U2: {
1110 int val = va_arg (ap, int);
1111 printf ("[UINT2:%d]", val);
1114 case MONO_TYPE_I4: {
1115 int val = va_arg (ap, int);
1116 printf ("[INT4:%d]", val);
1119 case MONO_TYPE_U4: {
1120 int val = va_arg (ap, int);
1121 printf ("[UINT4:%d]", val);
1125 gint64 val = va_arg (ap, gint64);
1126 printf ("[INT:%ld]", val);
1131 gint64 val = va_arg (ap, gint64);
1132 printf ("[UINT:%lu]", val);
1136 case MONO_TYPE_STRING: {
1137 MonoString *s = va_arg (ap, MonoString *);
1140 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1141 decodeParmString (s);
1143 printf ("[STRING:null], ");
1146 case MONO_TYPE_CLASS:
1147 case MONO_TYPE_OBJECT: {
1148 MonoObject *o = va_arg (ap, MonoObject *);
1150 if ((o) && (o->vtable)) {
1151 if (o->vtable->klass == mono_defaults.boolean_class) {
1152 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1153 } else if (o->vtable->klass == mono_defaults.int32_class) {
1154 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1155 } else if (o->vtable->klass == mono_defaults.int64_class) {
1156 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1158 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1160 printf ("[OBJECT:%p]", o);
1165 case MONO_TYPE_FNPTR:
1166 case MONO_TYPE_ARRAY:
1167 case MONO_TYPE_SZARRAY: {
1168 gpointer p = va_arg (ap, gpointer);
1169 printf ("[result=%p]", p);
1172 case MONO_TYPE_I8: {
1173 gint64 l = va_arg (ap, gint64);
1174 printf ("[LONG:%ld]", l);
1177 case MONO_TYPE_U8: {
1178 guint64 l = va_arg (ap, guint64);
1179 printf ("[ULONG:%lu]", l);
1182 case MONO_TYPE_R4: {
1183 double f = va_arg (ap, double);
1184 printf ("[FLOAT4:%g]\n", f);
1187 case MONO_TYPE_R8: {
1188 double f = va_arg (ap, double);
1189 printf ("[FLOAT8:%g]\n", f);
1192 case MONO_TYPE_VALUETYPE: {
1193 MonoMarshalType *info;
1194 if (type->data.klass->enumtype) {
1195 type = mono_class_enum_basetype (type->data.klass);
1200 info = mono_marshal_load_type_info (type->data.klass);
1202 if ((info->native_size == sizeof(float)) &&
1203 (info->num_fields == 1) &&
1204 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1205 double f = va_arg (ap, double);
1206 printf("[FLOAT4:%g]\n", (double) f);
1210 if ((info->native_size == sizeof(double)) &&
1211 (info->num_fields == 1) &&
1212 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1213 double f = va_arg (ap, double);
1214 printf("[FLOAT8:%g]\n", f);
1218 size = mono_type_size (type, &align);
1221 guint32 p = va_arg (ap, guint32);
1222 printf ("[%02x]\n",p);
1226 guint32 p = va_arg (ap, guint32);
1227 printf ("[%04x]\n",p);
1231 guint32 p = va_arg (ap, guint32);
1232 printf ("[%08x]\n",p);
1236 guint64 p = va_arg (ap, guint64);
1237 printf ("[%016lx]\n",p);
1241 gpointer p = va_arg (ap, gpointer);
1242 printf ("[VALUETYPE] %p\n",p);
1248 case MONO_TYPE_TYPEDBYREF: {
1249 guint8 *p = va_arg (ap, gpointer);
1251 size = mono_type_size (type, &align);
1258 for (j = 0; p && j < size; j++)
1259 printf ("%02x,", p [j]);
1263 printf ("[TYPEDBYREF]\n");
1267 case MONO_TYPE_GENERICINST: {
1268 printf("[GENERICINST]\n");
1271 case MONO_TYPE_MVAR: {
1275 case MONO_TYPE_CMOD_REQD: {
1276 printf("[CMOD_REQD]\n");
1279 case MONO_TYPE_CMOD_OPT: {
1280 printf("[CMOD_OPT]\n");
1283 case MONO_TYPE_INTERNAL: {
1284 printf("[INTERNAL]\n");
1288 printf ("(unknown return type %x)",
1289 mono_method_signature (method)->ret->type);
1292 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1293 printf (" ip: %p\n", (gpointer) ip);
1296 /*========================= End of Function ========================*/
1298 /*------------------------------------------------------------------*/
1300 /* Name - mono_arch_cpu_init */
1302 /* Function - Perform CPU specific initialization to execute */
1305 /*------------------------------------------------------------------*/
1308 mono_arch_cpu_init (void)
1312 /*========================= End of Function ========================*/
1314 /*------------------------------------------------------------------*/
1316 /* Name - mono_arch_init. */
1318 /* Function - Initialize architecture specific code. */
1320 /*------------------------------------------------------------------*/
1323 mono_arch_init (void)
1327 mono_set_partial_sharing_supported (FALSE);
1328 mono_os_mutex_init_recursive (&mini_arch_mutex);
1330 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1331 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1332 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1334 code = (guint8 *) &breakpointCode;
1335 s390_basr(code, s390_r13, 0);
1337 s390_llong(code, 0);
1338 s390_lg(code, s390_r13, 0, s390_r13, 4);
1339 s390_lg(code, s390_r0, 0, s390_r13, 0);
1342 /*========================= End of Function ========================*/
1344 /*------------------------------------------------------------------*/
1346 /* Name - mono_arch_cleanup. */
1348 /* Function - Cleanup architecture specific code . */
1350 /*------------------------------------------------------------------*/
1353 mono_arch_cleanup (void)
1355 if (ss_trigger_page)
1356 mono_vfree (ss_trigger_page, mono_pagesize ());
1357 if (bp_trigger_page)
1358 mono_vfree (bp_trigger_page, mono_pagesize ());
1359 mono_os_mutex_destroy (&mini_arch_mutex);
1362 /*========================= End of Function ========================*/
1364 /*------------------------------------------------------------------*/
1366 /* Name - mono_arch_cpu_optimizations */
1368 /* Function - Returns the optimizations supported on this CPU */
1370 /*------------------------------------------------------------------*/
1373 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1377 /*----------------------------------------------------------*/
1378 /* No s390-specific optimizations yet */
1379 /*----------------------------------------------------------*/
1380 *exclude_mask = MONO_OPT_LINEARS;
1384 /*========================= End of Function ========================*/
1386 /*------------------------------------------------------------------*/
1388 /* Name - mono_arch_get_allocatable_int_vars */
1392 /*------------------------------------------------------------------*/
1395 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1400 for (i = 0; i < cfg->num_varinfo; i++) {
1401 MonoInst *ins = cfg->varinfo [i];
1402 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1405 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1408 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1409 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1412 /* we can only allocate 32 bit values */
1413 if (mono_is_regsize_var(ins->inst_vtype)) {
1414 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1415 g_assert (i == vmv->idx);
1416 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1423 /*========================= End of Function ========================*/
1425 /*------------------------------------------------------------------*/
1427 /* Name - mono_arch_global_int_regs */
1429 /* Function - Return a list of usable integer registers. */
1431 /*------------------------------------------------------------------*/
1434 mono_arch_get_global_int_regs (MonoCompile *cfg)
1437 MonoMethodHeader *header;
1440 header = cfg->header;
1441 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1442 cfg->frame_reg = s390_r11;
1445 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1447 for (i = 8; i < top; ++i) {
1448 if (cfg->frame_reg != i)
1449 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1455 /*========================= End of Function ========================*/
1457 /*------------------------------------------------------------------*/
1459 /* Name - mono_arch_flush_icache */
1461 /* Function - Flush the CPU icache. */
1463 /*------------------------------------------------------------------*/
1466 mono_arch_flush_icache (guint8 *code, gint size)
1470 /*========================= End of Function ========================*/
1472 /*------------------------------------------------------------------*/
1474 /* Name - add_general */
1476 /* Function - Determine code and stack size incremements for a */
1479 /*------------------------------------------------------------------*/
1482 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1484 if (*gr > S390_LAST_ARG_REG) {
1485 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1486 ainfo->offset = sz->stack_size;
1487 ainfo->reg = STK_BASE;
1488 ainfo->regtype = RegTypeBase;
1489 sz->stack_size += sizeof(long);
1490 sz->local_size += sizeof(long);
1491 sz->offStruct += sizeof(long);
1492 sz->code_size += 12;
1500 /*========================= End of Function ========================*/
1502 /*------------------------------------------------------------------*/
1504 /* Name - add_stackParm */
1506 /* Function - Determine code and stack size incremements for a */
1509 /*------------------------------------------------------------------*/
1512 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1514 if (*gr > S390_LAST_ARG_REG) {
1515 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1516 ainfo->reg = STK_BASE;
1517 ainfo->offset = sz->stack_size;
1518 ainfo->regtype = RegTypeStructByAddrOnStack;
1519 sz->stack_size += sizeof (gpointer);
1520 sz->parm_size += sizeof(gpointer);
1521 sz->offStruct += sizeof(gpointer);
1524 ainfo->offset = sz->stack_size;
1525 ainfo->regtype = RegTypeStructByAddr;
1528 ainfo->offparm = sz->offset;
1529 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1531 ainfo->vtsize = size;
1532 sz->parm_size += size;
1535 /*========================= End of Function ========================*/
1537 /*------------------------------------------------------------------*/
1539 /* Name - add_float */
1541 /* Function - Determine code and stack size incremements for a */
1542 /* float parameter. */
1544 /*------------------------------------------------------------------*/
1547 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1549 if ((*fr) <= S390_LAST_FPARG_REG) {
1550 ainfo->regtype = RegTypeFP;
1556 ainfo->offset = sz->stack_size;
1557 ainfo->reg = STK_BASE;
1558 ainfo->regtype = RegTypeBase;
1560 sz->stack_size += sizeof(double);
1561 sz->local_size += sizeof(double);
1562 sz->offStruct += sizeof(double);
1566 /*========================= End of Function ========================*/
1568 /*------------------------------------------------------------------*/
1570 /* Name - get_call_info */
1572 /* Function - Determine the amount of space required for code */
1573 /* and stack. In addition determine starting points */
1574 /* for stack-based parameters, and area for struct- */
1575 /* ures being returned on the stack. */
1577 /*------------------------------------------------------------------*/
1580 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1582 guint i, fr, gr, size, pstart;
1583 int nParm = sig->hasthis + sig->param_count;
1585 guint32 simpleType, align;
1586 gboolean is_pinvoke = sig->pinvoke;
1591 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1593 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1598 cinfo->struct_ret = 0;
1602 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1603 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1610 /*----------------------------------------------------------*/
1611 /* We determine the size of the return code/stack in case we*/
1612 /* need to reserve a register to be used to address a stack */
1613 /* area that the callee will use. */
1614 /*----------------------------------------------------------*/
1616 ret_type = mini_get_underlying_type (sig->ret);
1617 simpleType = ret_type->type;
1619 switch (simpleType) {
1620 case MONO_TYPE_BOOLEAN:
1625 case MONO_TYPE_CHAR:
1630 case MONO_TYPE_CLASS:
1631 case MONO_TYPE_OBJECT:
1632 case MONO_TYPE_SZARRAY:
1633 case MONO_TYPE_ARRAY:
1635 case MONO_TYPE_FNPTR:
1636 case MONO_TYPE_STRING:
1637 cinfo->ret.reg = s390_r2;
1642 cinfo->ret.reg = s390_f0;
1647 cinfo->ret.reg = s390_r2;
1650 case MONO_TYPE_GENERICINST:
1651 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1652 cinfo->ret.reg = s390_r2;
1657 case MONO_TYPE_VALUETYPE: {
1658 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1659 if (klass->enumtype) {
1660 simpleType = mono_class_enum_basetype (klass)->type;
1663 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1665 cinfo->struct_ret = 1;
1666 cinfo->ret.size = size;
1667 cinfo->ret.vtsize = size;
1670 case MONO_TYPE_TYPEDBYREF:
1671 size = sizeof (MonoTypedRef);
1672 cinfo->struct_ret = 1;
1673 cinfo->ret.size = size;
1674 cinfo->ret.vtsize = size;
1676 case MONO_TYPE_VOID:
1679 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1685 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1686 * the first argument, allowing 'this' to be always passed in the first arg reg.
1687 * Also do this if the first argument is a reference type, since virtual calls
1688 * are sometimes made using calli without sig->hasthis set, like in the delegate
1691 if (cinfo->struct_ret && !is_pinvoke &&
1693 (sig->param_count > 0 &&
1694 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1696 cinfo->args[nParm].size = sizeof (gpointer);
1697 add_general (&gr, sz, cinfo->args + nParm);
1699 cinfo->args[nParm].size = sizeof (gpointer);
1700 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1704 cinfo->vret_arg_index = 1;
1705 cinfo->ret.reg = gr;
1710 cinfo->args[nParm].size = sizeof (gpointer);
1711 add_general (&gr, sz, cinfo->args + nParm);
1715 if (cinfo->struct_ret) {
1716 cinfo->ret.reg = gr;
1721 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1722 gr = S390_LAST_ARG_REG + 1;
1723 fr = S390_LAST_FPARG_REG + 1;
1725 /* Emit the signature cookie just before the implicit arguments */
1726 add_general (&gr, sz, &cinfo->sigCookie);
1729 /*----------------------------------------------------------*/
1730 /* We determine the size of the parameter code and stack */
1731 /* requirements by checking the types and sizes of the */
1733 /*----------------------------------------------------------*/
1735 for (i = pstart; i < sig->param_count; ++i) {
1738 /*--------------------------------------------------*/
1739 /* Handle vararg type calls. All args are put on */
1741 /*--------------------------------------------------*/
1742 if ((sig->call_convention == MONO_CALL_VARARG) &&
1743 (i == sig->sentinelpos)) {
1744 gr = S390_LAST_ARG_REG + 1;
1745 fr = S390_LAST_FPARG_REG + 1;
1746 add_general (&gr, sz, &cinfo->sigCookie);
1749 if (sig->params [i]->byref) {
1750 add_general (&gr, sz, cinfo->args+nParm);
1751 cinfo->args[nParm].size = sizeof(gpointer);
1756 ptype = mini_get_underlying_type (sig->params [i]);
1757 simpleType = ptype->type;
1758 cinfo->args[nParm].type = simpleType;
1759 switch (simpleType) {
1760 case MONO_TYPE_BOOLEAN:
1763 cinfo->args[nParm].size = sizeof(char);
1764 add_general (&gr, sz, cinfo->args+nParm);
1769 case MONO_TYPE_CHAR:
1770 cinfo->args[nParm].size = sizeof(short);
1771 add_general (&gr, sz, cinfo->args+nParm);
1776 cinfo->args[nParm].size = sizeof(int);
1777 add_general (&gr, sz, cinfo->args+nParm);
1783 case MONO_TYPE_FNPTR:
1784 case MONO_TYPE_CLASS:
1785 case MONO_TYPE_OBJECT:
1786 case MONO_TYPE_STRING:
1787 case MONO_TYPE_SZARRAY:
1788 case MONO_TYPE_ARRAY:
1789 cinfo->args[nParm].size = sizeof(gpointer);
1790 add_general (&gr, sz, cinfo->args+nParm);
1795 cinfo->args[nParm].size = sizeof(long long);
1796 add_general (&gr, sz, cinfo->args+nParm);
1800 cinfo->args[nParm].size = sizeof(float);
1801 add_float (&fr, sz, cinfo->args+nParm);
1805 cinfo->args[nParm].size = sizeof(double);
1806 add_float (&fr, sz, cinfo->args+nParm);
1809 case MONO_TYPE_GENERICINST:
1810 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1811 cinfo->args[nParm].size = sizeof(gpointer);
1812 add_general (&gr, sz, cinfo->args+nParm);
1817 case MONO_TYPE_VALUETYPE: {
1818 MonoMarshalType *info;
1819 MonoClass *klass = mono_class_from_mono_type (ptype);
1822 size = mono_class_native_size(klass, NULL);
1824 size = mono_class_value_size(klass, NULL);
1826 if (simpleType != MONO_TYPE_GENERICINST) {
1827 info = mono_marshal_load_type_info(klass);
1829 if ((info->native_size == sizeof(float)) &&
1830 (info->num_fields == 1) &&
1831 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1832 cinfo->args[nParm].size = sizeof(float);
1833 add_float(&fr, sz, cinfo->args+nParm);
1838 if ((info->native_size == sizeof(double)) &&
1839 (info->num_fields == 1) &&
1840 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1841 cinfo->args[nParm].size = sizeof(double);
1842 add_float(&fr, sz, cinfo->args+nParm);
1848 cinfo->args[nParm].vtsize = 0;
1849 cinfo->args[nParm].size = 0;
1852 /*----------------------------------*/
1853 /* On S/390, structures of size 1, */
1854 /* 2, 4, and 8 bytes are passed in */
1855 /* (a) register(s). */
1856 /*----------------------------------*/
1862 add_general(&gr, sz, cinfo->args+nParm);
1863 cinfo->args[nParm].size = size;
1864 cinfo->args[nParm].regtype = RegTypeStructByVal;
1866 sz->local_size += sizeof(long);
1869 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1874 case MONO_TYPE_TYPEDBYREF: {
1875 int size = sizeof (MonoTypedRef);
1877 cinfo->args[nParm].vtsize = 0;
1878 cinfo->args[nParm].size = 0;
1881 /*----------------------------------*/
1882 /* On S/390, structures of size 1, */
1883 /* 2, 4, and 8 bytes are passed in */
1884 /* (a) register(s). */
1885 /*----------------------------------*/
1891 add_general(&gr, sz, cinfo->args+nParm);
1892 cinfo->args[nParm].size = size;
1893 cinfo->args[nParm].regtype = RegTypeStructByVal;
1895 sz->local_size += sizeof(long);
1898 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1904 g_error ("Can't trampoline 0x%x", ptype);
1908 /*----------------------------------------------------------*/
1909 /* Handle the case where there are no implicit arguments */
1910 /*----------------------------------------------------------*/
1911 if ((sig->call_convention == MONO_CALL_VARARG) &&
1914 (sig->param_count == sig->sentinelpos)) {
1915 gr = S390_LAST_ARG_REG + 1;
1916 fr = S390_LAST_FPARG_REG + 1;
1917 add_general (&gr, sz, &cinfo->sigCookie);
1920 /*----------------------------------------------------------*/
1921 /* If we are passing a structure back then if it won't be */
1922 /* in a register(s) then we make room at the end of the */
1923 /* parameters that may have been placed on the stack */
1924 /*----------------------------------------------------------*/
1925 if (cinfo->struct_ret) {
1926 cinfo->ret.offset = sz->stack_size;
1927 switch (cinfo->ret.size) {
1935 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1940 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1942 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1947 /*========================= End of Function ========================*/
1949 /*------------------------------------------------------------------*/
1951 /* Name - mono_arch_allocate_vars */
1953 /* Function - Set var information according to the calling */
1954 /* convention for S/390. The local var stuff should */
1955 /* most likely be split in another method. */
1957 /* Parameter - @m - Compile unit. */
1959 /*------------------------------------------------------------------*/
1962 mono_arch_allocate_vars (MonoCompile *cfg)
1964 MonoMethodSignature *sig;
1965 MonoMethodHeader *header;
1968 int iParm, iVar, offset, align, size, curinst;
1969 int frame_reg = STK_BASE;
1972 header = cfg->header;
1974 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1976 /*---------------------------------------------------------*/
1977 /* We use the frame register also for any method that has */
1978 /* filter clauses. This way, when the handlers are called, */
1979 /* the code will reference local variables using the frame */
1980 /* reg instead of the stack pointer: if we had to restore */
1981 /* the stack pointer, we'd corrupt the method frames that */
1982 /* are already on the stack (since filters get called */
1983 /* before stack unwinding happens) when the filter code */
1984 /* would call any method. */
1985 /*---------------------------------------------------------*/
1986 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1987 frame_reg = s390_r11;
1989 cfg->frame_reg = frame_reg;
1991 cfg->arch.bkchain_reg = -1;
1993 if (frame_reg != STK_BASE)
1994 cfg->used_int_regs |= (1 << frame_reg);
1996 if (cfg->uses_rgctx_reg)
1997 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
1999 sig = mono_method_signature (cfg->method);
2001 cinfo = get_call_info (cfg, cfg->mempool, sig);
2003 if (!cinfo->struct_ret) {
2004 switch (mini_get_underlying_type (sig->ret)->type) {
2005 case MONO_TYPE_VOID:
2008 cfg->ret->opcode = OP_REGVAR;
2009 cfg->ret->dreg = s390_r2;
2014 /*--------------------------------------------------------------*/
2015 /* local vars are at a positive offset from the stack pointer */
2016 /* also note that if the function uses alloca, we use s390_r11 */
2017 /* to point at the local variables. */
2018 /* add parameter area size for called functions */
2019 /*--------------------------------------------------------------*/
2020 if (cfg->param_area == 0)
2021 offset = S390_MINIMAL_STACK_SIZE;
2023 offset = cfg->param_area;
2025 cfg->sig_cookie = 0;
2027 if (cinfo->struct_ret) {
2028 inst = cfg->vret_addr;
2029 offset = S390_ALIGN(offset, sizeof(gpointer));
2030 inst->inst_offset = offset;
2031 inst->opcode = OP_REGOFFSET;
2032 inst->inst_basereg = frame_reg;
2033 offset += sizeof(gpointer);
2034 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2035 printf ("vret_addr =");
2036 mono_print_ins (cfg->vret_addr);
2041 inst = cfg->args [0];
2042 if (inst->opcode != OP_REGVAR) {
2043 inst->opcode = OP_REGOFFSET;
2044 inst->inst_basereg = frame_reg;
2045 offset = S390_ALIGN(offset, sizeof(gpointer));
2046 inst->inst_offset = offset;
2047 offset += sizeof (gpointer);
2054 eArg = sig->param_count + sArg;
2056 if (sig->call_convention == MONO_CALL_VARARG)
2057 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2059 for (iParm = sArg; iParm < eArg; ++iParm) {
2060 inst = cfg->args [curinst];
2061 if (inst->opcode != OP_REGVAR) {
2062 switch (cinfo->args[iParm].regtype) {
2063 case RegTypeStructByAddr : {
2066 size = sizeof (gpointer);
2068 inst->opcode = OP_REGOFFSET;
2069 inst->inst_basereg = frame_reg;
2070 offset = S390_ALIGN (offset, sizeof (gpointer));
2071 inst->inst_offset = offset;
2073 /* Add a level of indirection */
2074 MONO_INST_NEW (cfg, indir, 0);
2076 inst->opcode = OP_VTARG_ADDR;
2077 inst->inst_left = indir;
2080 case RegTypeStructByAddrOnStack : {
2083 size = sizeof (gpointer);
2085 /* Similar to the == STK_BASE case below */
2086 cfg->arch.bkchain_reg = s390_r12;
2087 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2089 inst->opcode = OP_REGOFFSET;
2090 inst->dreg = mono_alloc_preg (cfg);
2091 inst->inst_basereg = cfg->arch.bkchain_reg;
2092 inst->inst_offset = cinfo->args [iParm].offset;
2094 /* Add a level of indirection */
2095 MONO_INST_NEW (cfg, indir, 0);
2097 inst->opcode = OP_VTARG_ADDR;
2098 inst->inst_left = indir;
2101 case RegTypeStructByVal :
2102 size = cinfo->args[iParm].size;
2103 offset = S390_ALIGN(offset, size);
2104 inst->opcode = OP_REGOFFSET;
2105 inst->inst_basereg = frame_reg;
2106 inst->inst_offset = offset;
2109 if (cinfo->args [iParm].reg == STK_BASE) {
2111 * These arguments are in the previous frame, so we can't
2112 * compute their offset from the current frame pointer right
2113 * now, since cfg->stack_offset is not yet known, so dedicate a
2114 * register holding the previous frame pointer.
2116 cfg->arch.bkchain_reg = s390_r12;
2117 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2119 inst->opcode = OP_REGOFFSET;
2120 inst->inst_basereg = cfg->arch.bkchain_reg;
2121 size = (cinfo->args[iParm].size < 8
2122 ? 8 - cinfo->args[iParm].size
2124 inst->inst_offset = cinfo->args [iParm].offset + size;
2125 size = sizeof (long);
2127 inst->opcode = OP_REGOFFSET;
2128 inst->inst_basereg = frame_reg;
2129 size = (cinfo->args[iParm].size < 8
2132 offset = S390_ALIGN(offset, size);
2133 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2134 inst->inst_offset = offset;
2136 inst->inst_offset = offset + (8 - size);
2141 if ((sig->call_convention == MONO_CALL_VARARG) &&
2142 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2143 (iParm < sig->sentinelpos))
2144 cfg->sig_cookie += size;
2145 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2148 offset += MAX(size, 8);
2153 cfg->locals_min_stack_offset = offset;
2155 curinst = cfg->locals_start;
2156 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2157 inst = cfg->varinfo [iVar];
2158 if ((inst->flags & MONO_INST_IS_DEAD) ||
2159 (inst->opcode == OP_REGVAR))
2162 /*--------------------------------------------------*/
2163 /* inst->backend.is_pinvoke indicates native sized */
2164 /* value typs this is used by the pinvoke wrappers */
2165 /* when they call functions returning structure */
2166 /*--------------------------------------------------*/
2167 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2168 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2169 (guint32 *) &align);
2171 size = mono_type_size (inst->inst_vtype, &align);
2173 offset = S390_ALIGN(offset, align);
2174 inst->inst_offset = offset;
2175 inst->opcode = OP_REGOFFSET;
2176 inst->inst_basereg = frame_reg;
2178 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2179 iVar, inst->inst_offset, size));
2182 cfg->locals_max_stack_offset = offset;
2184 /*------------------------------------------------------*/
2185 /* Allow space for the trace method stack area if needed*/
2186 /*------------------------------------------------------*/
2187 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2188 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2189 offset += S390_TRACE_STACK_SIZE;
2191 /*------------------------------------------------------*/
2192 /* Reserve space to save LMF and caller saved registers */
2193 /*------------------------------------------------------*/
2194 if (cfg->method->save_lmf)
2195 offset += sizeof (MonoLMF);
2197 /*------------------------------------------------------*/
2198 /* align the offset */
2199 /*------------------------------------------------------*/
2200 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2202 /*------------------------------------------------------*/
2203 /* Fix offsets for args whose value is in parent frame */
2204 /*------------------------------------------------------*/
2205 for (iParm = sArg; iParm < eArg; ++iParm) {
2206 inst = cfg->args [iParm];
2208 if (inst->opcode == OP_S390_STKARG) {
2209 inst->opcode = OP_REGOFFSET;
2210 inst->inst_offset += cfg->stack_offset;
2215 /*========================= End of Function ========================*/
2217 /*------------------------------------------------------------------*/
2219 /* Name - mono_arch_create_vars */
2221 /*------------------------------------------------------------------*/
2224 mono_arch_create_vars (MonoCompile *cfg)
2226 MonoMethodSignature *sig;
2229 sig = mono_method_signature (cfg->method);
2231 cinfo = get_call_info (cfg, cfg->mempool, sig);
2233 if (cinfo->struct_ret) {
2234 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2235 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2236 printf ("vret_addr = ");
2237 mono_print_ins (cfg->vret_addr);
2242 /*========================= End of Function ========================*/
2244 /*------------------------------------------------------------------*/
2246 /* Name - add_outarg_reg2. */
2248 /*------------------------------------------------------------------*/
2251 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2256 case RegTypeGeneral:
2257 MONO_INST_NEW (cfg, ins, OP_MOVE);
2258 ins->dreg = mono_alloc_ireg (cfg);
2259 ins->sreg1 = tree->dreg;
2260 MONO_ADD_INS (cfg->cbb, ins);
2261 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2264 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2265 ins->dreg = mono_alloc_freg (cfg);
2266 ins->sreg1 = tree->dreg;
2267 MONO_ADD_INS (cfg->cbb, ins);
2268 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2271 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2272 ins->dreg = mono_alloc_freg (cfg);
2273 ins->sreg1 = tree->dreg;
2274 MONO_ADD_INS (cfg->cbb, ins);
2275 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2278 g_assert_not_reached ();
2282 /*========================= End of Function ========================*/
2284 /*------------------------------------------------------------------*/
2286 /* Name - emit_sig_cookie. */
2288 /*------------------------------------------------------------------*/
2291 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2293 MonoMethodSignature *tmpSig;
2296 cfg->disable_aot = TRUE;
2298 /*----------------------------------------------------------*/
2299 /* mono_ArgIterator_Setup assumes the signature cookie is */
2300 /* passed first and all the arguments which were before it */
2301 /* passed on the stack after the signature. So compensate */
2302 /* by passing a different signature. */
2303 /*----------------------------------------------------------*/
2304 tmpSig = mono_metadata_signature_dup (call->signature);
2305 tmpSig->param_count -= call->signature->sentinelpos;
2306 tmpSig->sentinelpos = 0;
2307 if (tmpSig->param_count > 0)
2308 memcpy (tmpSig->params,
2309 call->signature->params + call->signature->sentinelpos,
2310 tmpSig->param_count * sizeof(MonoType *));
2312 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2313 sig_arg->dreg = mono_alloc_ireg (cfg);
2314 sig_arg->inst_p0 = tmpSig;
2315 MONO_ADD_INS (cfg->cbb, sig_arg);
2317 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2318 cinfo->sigCookie.offset, sig_arg->dreg);
2321 /*========================= End of Function ========================*/
2323 /*------------------------------------------------------------------*/
2325 /* Name - mono_arch_emit_call */
2327 /*------------------------------------------------------------------*/
2330 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2333 MonoMethodSignature *sig;
2335 int i, n, lParamArea;
2337 ArgInfo *ainfo = NULL;
2339 MonoMethodHeader *header;
2342 sig = call->signature;
2343 n = sig->param_count + sig->hasthis;
2344 DEBUG (g_print ("Call requires: %d parameters\n",n));
2346 cinfo = get_call_info (cfg, cfg->mempool, sig);
2348 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2349 cinfo->sz.parm_size + cinfo->sz.offset;
2350 call->stack_usage = MAX(stackSize, call->stack_usage);
2351 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2352 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2353 cfg->flags |= MONO_CFG_HAS_CALLS;
2355 if (cinfo->struct_ret) {
2356 MONO_INST_NEW (cfg, ins, OP_MOVE);
2357 ins->sreg1 = call->vret_var->dreg;
2358 ins->dreg = mono_alloc_preg (cfg);
2359 MONO_ADD_INS (cfg->cbb, ins);
2360 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2363 header = cfg->header;
2364 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2369 for (i = 0; i < n; ++i) {
2372 ainfo = cinfo->args + i;
2373 if (i >= sig->hasthis)
2374 t = sig->params [i - sig->hasthis];
2376 t = &mono_defaults.int_class->byval_arg;
2377 t = mini_get_underlying_type (t);
2379 in = call->args [i];
2381 if ((sig->call_convention == MONO_CALL_VARARG) &&
2383 (i == sig->sentinelpos)) {
2384 emit_sig_cookie (cfg, call, cinfo);
2387 switch (ainfo->regtype) {
2388 case RegTypeGeneral:
2389 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2392 if (MONO_TYPE_ISSTRUCT (t)) {
2393 /* Valuetype passed in one fp register */
2394 ainfo->regtype = RegTypeStructByValInFP;
2397 if (ainfo->size == 4)
2398 ainfo->regtype = RegTypeFPR4;
2399 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2402 case RegTypeStructByVal:
2403 case RegTypeStructByAddr:
2404 case RegTypeStructByAddrOnStack: {
2408 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2409 size = sizeof (MonoTypedRef);
2410 align = sizeof (gpointer);
2414 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2417 * Other backends use mono_type_stack_size (), but that
2418 * aligns the size to 8, which is larger than the size of
2419 * the source, leading to reads of invalid memory if the
2420 * source is at the end of address space.
2422 size = mono_class_value_size (in->klass, &align);
2425 g_assert (in->klass);
2427 ainfo->offparm += cinfo->sz.offStruct;
2429 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2430 ins->sreg1 = in->dreg;
2431 ins->klass = in->klass;
2432 ins->backend.size = ainfo->size;
2433 ins->inst_p0 = call;
2434 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2435 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2437 MONO_ADD_INS (cfg->cbb, ins);
2439 if (ainfo->regtype == RegTypeStructByAddr) {
2441 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2442 * use the normal OUTARG opcodes to pass the address of the location to
2445 int treg = mono_alloc_preg (cfg);
2446 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2447 frmReg, ainfo->offparm);
2448 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2449 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2450 /* The address of the valuetype is passed on the stack */
2451 int treg = mono_alloc_preg (cfg);
2452 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2453 frmReg, ainfo->offparm);
2454 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2455 ainfo->reg, ainfo->offset, treg);
2457 if (cfg->compute_gc_maps) {
2460 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2466 if (!t->byref && t->type == MONO_TYPE_R4) {
2467 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2468 STK_BASE, ainfo->offset + 4,
2470 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2471 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2472 STK_BASE, ainfo->offset,
2475 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2476 ins->inst_destbasereg = STK_BASE;
2477 ins->inst_offset = ainfo->offset;
2478 ins->sreg1 = in->dreg;
2481 /* This is needed by MonoTypedRef->value to point to the correct data */
2482 if ((sig->call_convention == MONO_CALL_VARARG) &&
2483 (i >= sig->sentinelpos)) {
2484 switch (ainfo->size) {
2486 ins->opcode = OP_STOREI1_MEMBASE_REG;
2489 ins->opcode = OP_STOREI2_MEMBASE_REG;
2492 ins->opcode = OP_STOREI4_MEMBASE_REG;
2500 MONO_ADD_INS (cfg->cbb, ins);
2504 g_assert_not_reached ();
2510 * Handle the case where there are no implicit arguments
2512 if ((sig->call_convention == MONO_CALL_VARARG) &&
2514 (i == sig->sentinelpos)) {
2515 emit_sig_cookie (cfg, call, cinfo);
2519 /*========================= End of Function ========================*/
2521 /*------------------------------------------------------------------*/
2523 /* Name - mono_arch_emit_outarg_vt */
2525 /*------------------------------------------------------------------*/
2528 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2530 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2531 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2532 int size = ins->backend.size;
2534 if (ainfo->regtype == RegTypeStructByVal) {
2536 arg->ins.sreg1 = ainfo->reg;
2537 arg->ins.opcode = OP_OUTARG_VT;
2538 arg->size = ainfo->size;
2539 arg->offset = ainfo->offset;
2540 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2542 if (ainfo->reg != STK_BASE) {
2543 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2545 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2548 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2549 int dreg = mono_alloc_freg (cfg);
2551 if (ainfo->size == 4) {
2552 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2553 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2555 g_assert (ainfo->size == 8);
2557 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2560 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2563 MonoMethodHeader *header;
2566 header = mono_method_get_header_checked (cfg->method, &error);
2567 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2568 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2573 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2574 src->dreg, 0, size);
2576 if (cfg->compute_gc_maps) {
2579 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2584 /*========================= End of Function ========================*/
2586 /*------------------------------------------------------------------*/
2588 /* Name - mono_arch_emit_setret */
2590 /*------------------------------------------------------------------*/
2593 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2595 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2598 if (ret->type == MONO_TYPE_R4) {
2599 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2601 } else if (ret->type == MONO_TYPE_R8) {
2602 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2607 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2610 /*========================= End of Function ========================*/
2612 /*------------------------------------------------------------------*/
2614 /* Name - mono_arch_instrument_mem_needs */
2616 /* Function - Allow tracing to work with this interface (with */
2617 /* an optional argument). */
2619 /*------------------------------------------------------------------*/
2622 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2624 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2626 /* split prolog-epilog requirements? */
2627 *code = 50; /* max bytes needed: check this number */
2630 /*========================= End of Function ========================*/
2632 /*------------------------------------------------------------------*/
2634 /* Name - mono_arch_instrument_prolog */
2636 /* Function - Create an "instrumented" prolog. */
2638 /*------------------------------------------------------------------*/
2641 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2642 gboolean enable_arguments)
2649 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2650 if (cfg->method->save_lmf)
2651 parmOffset -= sizeof(MonoLMF);
2652 fpOffset = parmOffset + (5*sizeof(gpointer));
2655 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2656 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2657 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2658 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2659 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2660 S390_SET (code, s390_r1, func);
2661 S390_SET (code, s390_r2, cfg->method);
2662 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2663 s390_lgr (code, s390_r4, STK_BASE);
2664 s390_aghi (code, s390_r4, cfg->stack_usage);
2665 s390_basr (code, s390_r14, s390_r1);
2666 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2667 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2668 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2669 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2670 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2675 /*========================= End of Function ========================*/
2677 /*------------------------------------------------------------------*/
2679 /* Name - mono_arch_instrument_epilog */
2681 /* Function - Create an epilog that will handle the returned */
2682 /* values used in instrumentation. */
2684 /*------------------------------------------------------------------*/
2687 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2690 int save_mode = SAVE_NONE,
2693 MonoMethod *method = cfg->method;
2694 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2696 offset = code - cfg->native_code;
2697 /*-----------------------------------------*/
2698 /* We need about 128 bytes of instructions */
2699 /*-----------------------------------------*/
2700 if (offset > (cfg->code_size - 128)) {
2701 cfg->code_size *= 2;
2702 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2703 code = cfg->native_code + offset;
2706 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2707 if (method->save_lmf)
2708 saveOffset -= sizeof(MonoLMF);
2712 case MONO_TYPE_VOID:
2713 /* special case string .ctor icall */
2714 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2715 save_mode = SAVE_ONE;
2717 save_mode = SAVE_NONE;
2721 save_mode = SAVE_ONE;
2724 save_mode = SAVE_R4;
2727 save_mode = SAVE_R8;
2729 case MONO_TYPE_VALUETYPE:
2730 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2731 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2734 save_mode = SAVE_STRUCT;
2737 save_mode = SAVE_ONE;
2741 switch (save_mode) {
2743 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2744 if (enable_arguments) {
2745 s390_lgr (code, s390_r3, s390_r2);
2749 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2750 if (enable_arguments) {
2751 s390_ldebr (code, s390_f0, s390_f0);
2755 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2758 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2759 if (enable_arguments) {
2760 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2761 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2769 S390_SET (code, s390_r1, func);
2770 S390_SET (code, s390_r2, cfg->method);
2771 s390_basr (code, s390_r14, s390_r1);
2773 switch (save_mode) {
2775 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2779 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2782 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2792 /*========================= End of Function ========================*/
2794 /*------------------------------------------------------------------*/
2796 /* Name - mono_arch_peephole_pass_1 */
2798 /* Function - Form a peephole pass at the code looking for */
2799 /* simple optimizations. */
2801 /*------------------------------------------------------------------*/
2804 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2808 /*========================= End of Function ========================*/
2810 /*------------------------------------------------------------------*/
2812 /* Name - mono_arch_peephole_pass_2 */
2814 /* Function - Form a peephole pass at the code looking for */
2815 /* simple optimizations. */
2817 /*------------------------------------------------------------------*/
2820 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2824 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2825 mono_peephole_ins (bb, ins);
2829 /*========================= End of Function ========================*/
2831 /*------------------------------------------------------------------*/
2833 /* Name - mono_arch_lowering_pass. */
2835 /*------------------------------------------------------------------*/
2838 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2840 MonoInst *ins, *next;
2842 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2843 switch (ins->opcode) {
2848 case OP_IDIV_UN_IMM:
2849 case OP_IREM_UN_IMM:
2854 case OP_LOCALLOC_IMM:
2855 mono_decompose_op_imm (cfg, bb, ins);
2858 if (!s390_is_imm16 (ins->inst_imm))
2859 /* This is created by the memcpy code which ignores is_inst_imm */
2860 mono_decompose_op_imm (cfg, bb, ins);
2867 bb->max_vreg = cfg->next_vreg;
2870 /*========================= End of Function ========================*/
2872 /*------------------------------------------------------------------*/
2874 /* Name - emit_float_to_int */
2876 /* Function - Create instructions which will convert a floating */
2877 /* point value to integer. */
2879 /*------------------------------------------------------------------*/
2882 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2884 /* sreg is a float, dreg is an integer reg. */
2886 s390_cgdbr (code, dreg, 5, sreg);
2889 s390_ltgr (code, dreg, dreg);
2891 s390_oill (code, dreg, 0x80);
2892 s390_lghi (code, s390_r0, 0xff);
2893 s390_ngr (code, dreg, s390_r0);
2896 s390_ltgr (code, dreg, dreg);
2898 s390_oill (code, dreg, 0x8000);
2899 s390_llill(code, s390_r0, 0xffff);
2900 s390_ngr (code, dreg, s390_r0);
2905 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2906 s390_ldgr (code, s390_f14, s390_r13);
2907 s390_ldr (code, s390_f15, sreg);
2908 s390_cdbr (code, s390_f15, s390_f14);
2909 s390_jl (code, 0); CODEPTR (code, o[0]);
2910 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2911 s390_ldgr (code, s390_f14, s390_r13);
2912 s390_sdbr (code, s390_f15, s390_f14);
2913 s390_cfdbr (code, dreg, 7, s390_f15);
2915 PTRSLOT (code, o[0]);
2916 s390_cfdbr (code, dreg, 5, sreg);
2919 s390_lghi (code, s390_r0, 0xff);
2920 s390_ngr (code, dreg, s390_r0);
2923 s390_llill(code, s390_r0, 0xffff);
2924 s390_ngr (code, dreg, s390_r0);
2931 /*========================= End of Function ========================*/
2933 /*------------------------------------------------------------------*/
2935 /* Name - gboolean_is_unsigned. */
2937 /* Function - Return TRUE if next opcode is checking for un- */
2940 /*------------------------------------------------------------------*/
2943 gboolean is_unsigned (MonoInst *next)
2946 (((next->opcode >= OP_IBNE_UN) &&
2947 (next->opcode <= OP_IBLT_UN)) ||
2948 ((next->opcode >= OP_LBNE_UN) &&
2949 (next->opcode <= OP_LBLT_UN)) ||
2950 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2951 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2952 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2953 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2954 ((next->opcode == OP_CLT_UN) ||
2955 (next->opcode == OP_CGT_UN)) ||
2956 ((next->opcode == OP_ICLT_UN) ||
2957 (next->opcode == OP_ICGT_UN) ||
2958 (next->opcode == OP_LCLT_UN) ||
2959 (next->opcode == OP_LCGT_UN))))
2965 /*========================= End of Function ========================*/
2967 /*------------------------------------------------------------------*/
2969 /* Name - mono_arch_output_basic_block */
2971 /* Function - Perform the "real" work of emitting instructions */
2972 /* that will do the work of in the basic block. */
2974 /*------------------------------------------------------------------*/
2977 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2982 guint8 *code = cfg->native_code + cfg->code_len;
2983 guint last_offset = 0;
2986 /* we don't align basic blocks of loops on s390 */
2988 if (cfg->verbose_level > 2)
2989 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2991 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2992 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2993 g_assert (!mono_compile_aot);
2994 cov->data [bb->dfn].cil_code = bb->cil_code;
2995 /* This is not thread save, but good enough */
2996 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2997 s390_alsi (code, 0, s390_r1, 1);
3000 MONO_BB_FOR_EACH_INS (bb, ins) {
3001 offset = code - cfg->native_code;
3003 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3005 if (offset > (cfg->code_size - max_len - 16)) {
3006 cfg->code_size *= 2;
3007 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3008 code = cfg->native_code + offset;
3011 mono_debug_record_line_number (cfg, ins, offset);
3013 switch (ins->opcode) {
3014 case OP_STOREI1_MEMBASE_IMM: {
3015 s390_lghi (code, s390_r0, ins->inst_imm);
3016 S390_LONG (code, stcy, stc, s390_r0, 0,
3017 ins->inst_destbasereg, ins->inst_offset);
3020 case OP_STOREI2_MEMBASE_IMM: {
3021 s390_lghi (code, s390_r0, ins->inst_imm);
3022 S390_LONG (code, sthy, sth, s390_r0, 0,
3023 ins->inst_destbasereg, ins->inst_offset);
3026 case OP_STOREI4_MEMBASE_IMM: {
3027 s390_lgfi (code, s390_r0, ins->inst_imm);
3028 S390_LONG (code, sty, st, s390_r0, 0,
3029 ins->inst_destbasereg, ins->inst_offset);
3032 case OP_STORE_MEMBASE_IMM:
3033 case OP_STOREI8_MEMBASE_IMM: {
3034 S390_SET (code, s390_r0, ins->inst_imm);
3035 S390_LONG (code, stg, stg, s390_r0, 0,
3036 ins->inst_destbasereg, ins->inst_offset);
3039 case OP_STOREI1_MEMBASE_REG: {
3040 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3041 ins->inst_destbasereg, ins->inst_offset);
3044 case OP_STOREI2_MEMBASE_REG: {
3045 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3046 ins->inst_destbasereg, ins->inst_offset);
3049 case OP_STOREI4_MEMBASE_REG: {
3050 S390_LONG (code, sty, st, ins->sreg1, 0,
3051 ins->inst_destbasereg, ins->inst_offset);
3054 case OP_STORE_MEMBASE_REG:
3055 case OP_STOREI8_MEMBASE_REG: {
3056 S390_LONG (code, stg, stg, ins->sreg1, 0,
3057 ins->inst_destbasereg, ins->inst_offset);
3061 g_assert_not_reached ();
3063 case OP_LOAD_MEMBASE:
3064 case OP_LOADI8_MEMBASE: {
3065 S390_LONG (code, lg, lg, ins->dreg, 0,
3066 ins->inst_basereg, ins->inst_offset);
3069 case OP_LOADI4_MEMBASE: {
3070 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3071 ins->inst_basereg, ins->inst_offset);
3074 case OP_LOADU4_MEMBASE: {
3075 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3076 ins->inst_basereg, ins->inst_offset);
3079 case OP_LOADU1_MEMBASE: {
3080 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3081 ins->inst_basereg, ins->inst_offset);
3084 case OP_LOADI1_MEMBASE: {
3085 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3086 ins->inst_basereg, ins->inst_offset);
3089 case OP_LOADU2_MEMBASE: {
3090 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3091 ins->inst_basereg, ins->inst_offset);
3094 case OP_LOADI2_MEMBASE: {
3095 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3096 ins->inst_basereg, ins->inst_offset);
3099 case OP_LCONV_TO_I1: {
3100 s390_lgbr (code, ins->dreg, ins->sreg1);
3103 case OP_LCONV_TO_I2: {
3104 s390_lghr (code, ins->dreg, ins->sreg1);
3107 case OP_LCONV_TO_U1: {
3108 s390_llgcr (code, ins->dreg, ins->sreg1);
3111 case OP_LCONV_TO_U2: {
3112 s390_llghr (code, ins->dreg, ins->sreg1);
3115 case OP_ICONV_TO_I1: {
3116 s390_lgbr (code, ins->dreg, ins->sreg1);
3119 case OP_ICONV_TO_I2: {
3120 s390_lghr (code, ins->dreg, ins->sreg1);
3123 case OP_ICONV_TO_U1: {
3124 s390_llgcr (code, ins->dreg, ins->sreg1);
3127 case OP_ICONV_TO_U2: {
3128 s390_llghr (code, ins->dreg, ins->sreg1);
3133 if (is_unsigned (ins->next))
3134 s390_clgr (code, ins->sreg1, ins->sreg2);
3136 s390_cgr (code, ins->sreg1, ins->sreg2);
3140 if (is_unsigned (ins->next))
3141 s390_clr (code, ins->sreg1, ins->sreg2);
3143 s390_cr (code, ins->sreg1, ins->sreg2);
3146 case OP_COMPARE_IMM:
3147 case OP_LCOMPARE_IMM: {
3148 S390_SET (code, s390_r0, ins->inst_imm);
3149 if (is_unsigned (ins->next))
3150 s390_clgr (code, ins->sreg1, s390_r0);
3152 s390_cgr (code, ins->sreg1, s390_r0);
3155 case OP_ICOMPARE_IMM: {
3156 S390_SET (code, s390_r0, ins->inst_imm);
3157 if (is_unsigned (ins->next))
3158 s390_clr (code, ins->sreg1, s390_r0);
3160 s390_cr (code, ins->sreg1, s390_r0);
3164 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3166 S390_CALL_TEMPLATE (code, s390_r14);
3171 s390_agr (code, ins->dreg, src2);
3176 s390_agr (code, ins->dreg, src2);
3181 s390_alcgr (code, ins->dreg, src2);
3185 if (ins->dreg != ins->sreg1) {
3186 s390_lgr (code, ins->dreg, ins->sreg1);
3188 if (s390_is_imm16 (ins->inst_imm)) {
3189 s390_aghi (code, ins->dreg, ins->inst_imm);
3190 } else if (s390_is_imm32 (ins->inst_imm)) {
3191 s390_agfi (code, ins->dreg, ins->inst_imm);
3193 S390_SET (code, s390_r0, ins->inst_imm);
3194 s390_agr (code, ins->dreg, s390_r0);
3199 if (ins->dreg != ins->sreg1) {
3200 s390_lgr (code, ins->dreg, ins->sreg1);
3202 g_assert (s390_is_imm16 (ins->inst_imm));
3203 s390_aghi (code, ins->dreg, ins->inst_imm);
3207 if (ins->dreg != ins->sreg1) {
3208 s390_lgr (code, ins->dreg, ins->sreg1);
3210 if (s390_is_imm16 (ins->inst_imm)) {
3211 s390_lghi (code, s390_r0, ins->inst_imm);
3212 s390_alcgr (code, ins->dreg, s390_r0);
3214 S390_SET (code, s390_r0, ins->inst_imm);
3215 s390_alcgr (code, ins->dreg, s390_r0);
3220 case OP_S390_IADD_OVF: {
3222 s390_ar (code, ins->dreg, src2);
3223 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3224 s390_lgfr (code, ins->dreg, ins->dreg);
3227 case OP_IADD_OVF_UN:
3228 case OP_S390_IADD_OVF_UN: {
3230 s390_algr (code, ins->dreg, src2);
3231 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3232 s390_llgfr (code, ins->dreg, ins->dreg);
3235 case OP_ADD_OVF_CARRY: {
3237 s390_lghi (code, s390_r0, 0);
3238 s390_lgr (code, s390_r1, s390_r0);
3239 s390_alcgr (code, s390_r0, s390_r1);
3240 s390_agr (code, ins->dreg, src2);
3241 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3242 s390_agr (code, ins->dreg, s390_r0);
3243 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3246 case OP_ADD_OVF_UN_CARRY: {
3248 s390_alcgr (code, ins->dreg, src2);
3249 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3254 s390_sgr (code, ins->dreg, src2);
3259 s390_sgr (code, ins->dreg, src2);
3264 s390_slbgr(code, ins->dreg, src2);
3268 if (ins->dreg != ins->sreg1) {
3269 s390_lgr (code, ins->dreg, ins->sreg1);
3271 if (s390_is_imm16 (-ins->inst_imm)) {
3272 s390_aghi (code, ins->dreg, -ins->inst_imm);
3273 } else if (s390_is_imm32 (-ins->inst_imm)) {
3274 s390_slgfi (code, ins->dreg, ins->inst_imm);
3276 S390_SET (code, s390_r0, ins->inst_imm);
3277 s390_slgr (code, ins->dreg, s390_r0);
3282 if (ins->dreg != ins->sreg1) {
3283 s390_lgr (code, ins->dreg, ins->sreg1);
3285 if (s390_is_imm16 (-ins->inst_imm)) {
3286 s390_aghi (code, ins->dreg, -ins->inst_imm);
3287 } else if (s390_is_imm32 (-ins->inst_imm)) {
3288 s390_slgfi (code, ins->dreg, ins->inst_imm);
3290 S390_SET (code, s390_r0, ins->inst_imm);
3291 s390_slgr (code, ins->dreg, s390_r0);
3296 if (ins->dreg != ins->sreg1) {
3297 s390_lgr (code, ins->dreg, ins->sreg1);
3299 if (s390_is_imm16 (-ins->inst_imm)) {
3300 s390_lghi (code, s390_r0, ins->inst_imm);
3301 s390_slbgr (code, ins->dreg, s390_r0);
3303 S390_SET (code, s390_r0, ins->inst_imm);
3304 s390_slbgr(code, ins->dreg, s390_r0);
3308 case OP_SUB_OVF_CARRY: {
3310 s390_lghi (code, s390_r0, 0);
3311 s390_lgr (code, s390_r1, s390_r0);
3312 s390_slbgr (code, s390_r0, s390_r1);
3313 s390_sgr (code, ins->dreg, src2);
3314 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3315 s390_agr (code, ins->dreg, s390_r0);
3316 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3319 case OP_SUB_OVF_UN_CARRY: {
3321 s390_slbgr (code, ins->dreg, src2);
3322 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3326 if (ins->sreg1 == ins->dreg) {
3327 s390_ngr (code, ins->dreg, ins->sreg2);
3330 if (ins->sreg2 == ins->dreg) {
3331 s390_ngr (code, ins->dreg, ins->sreg1);
3334 s390_lgr (code, ins->dreg, ins->sreg1);
3335 s390_ngr (code, ins->dreg, ins->sreg2);
3341 if (ins->dreg != ins->sreg1) {
3342 s390_lgr (code, ins->dreg, ins->sreg1);
3344 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3345 s390_ngr (code, ins->dreg, s390_r0);
3349 s390_lgr (code, s390_r1, ins->sreg1);
3350 s390_dsgr (code, s390_r0, ins->sreg2);
3351 s390_lgr (code, ins->dreg, s390_r1);
3355 s390_lgr (code, s390_r1, ins->sreg1);
3356 s390_lghi (code, s390_r0, 0);
3357 s390_dlgr (code, s390_r0, ins->sreg2);
3358 s390_lgr (code, ins->dreg, s390_r1);
3362 s390_lgr (code, s390_r1, ins->sreg1);
3363 s390_dsgr (code, s390_r0, ins->sreg2);
3364 s390_lgr (code, ins->dreg, s390_r0);
3368 if (s390_is_imm16 (ins->inst_imm)) {
3369 s390_lghi (code, s390_r13, ins->inst_imm);
3371 s390_lgfi (code, s390_r13, ins->inst_imm);
3373 s390_lgr (code, s390_r0, ins->sreg1);
3374 s390_dsgr (code, s390_r0, s390_r13);
3375 s390_lgfr (code, ins->dreg, s390_r0);
3379 s390_lgr (code, s390_r1, ins->sreg1);
3380 s390_lghi (code, s390_r0, 0);
3381 s390_dlgr (code, s390_r0, ins->sreg2);
3382 s390_lgr (code, ins->dreg, s390_r0);
3386 if (ins->sreg1 == ins->dreg) {
3387 s390_ogr (code, ins->dreg, ins->sreg2);
3390 if (ins->sreg2 == ins->dreg) {
3391 s390_ogr (code, ins->dreg, ins->sreg1);
3394 s390_lgr (code, ins->dreg, ins->sreg1);
3395 s390_ogr (code, ins->dreg, ins->sreg2);
3401 if (ins->dreg != ins->sreg1) {
3402 s390_lgr (code, ins->dreg, ins->sreg1);
3404 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3405 s390_ogr (code, ins->dreg, s390_r0);
3409 if (ins->sreg1 == ins->dreg) {
3410 s390_xgr (code, ins->dreg, ins->sreg2);
3413 if (ins->sreg2 == ins->dreg) {
3414 s390_xgr (code, ins->dreg, ins->sreg1);
3417 s390_lgr (code, ins->dreg, ins->sreg1);
3418 s390_xgr (code, ins->dreg, ins->sreg2);
3424 if (ins->dreg != ins->sreg1) {
3425 s390_lgr (code, ins->dreg, ins->sreg1);
3427 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3428 s390_xgr (code, ins->dreg, s390_r0);
3433 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3438 if (ins->sreg1 != ins->dreg) {
3439 s390_lgr (code, ins->dreg, ins->sreg1);
3441 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3446 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3451 if (ins->sreg1 != ins->dreg) {
3452 s390_lgr (code, ins->dreg, ins->sreg1);
3454 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3458 case OP_LSHR_UN_IMM: {
3459 if (ins->sreg1 != ins->dreg) {
3460 s390_lgr (code, ins->dreg, ins->sreg1);
3462 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3467 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3471 if (ins->sreg1 != ins->dreg) {
3472 s390_lgr (code, ins->dreg, ins->sreg1);
3474 s390_lghi (code, s390_r0, -1);
3475 s390_xgr (code, ins->dreg, s390_r0);
3479 s390_lcgr (code, ins->dreg, ins->sreg1);
3484 s390_msgr (code, ins->dreg, src2);
3489 if (ins->dreg != ins->sreg1) {
3490 s390_lgr (code, ins->dreg, ins->sreg1);
3492 if (s390_is_imm16 (ins->inst_imm)) {
3493 s390_lghi (code, s390_r13, ins->inst_imm);
3494 } else if (s390_is_imm32 (ins->inst_imm)) {
3495 s390_lgfi (code, s390_r13, ins->inst_imm);
3497 S390_SET (code, s390_r13, ins->inst_imm);
3499 s390_msgr (code, ins->dreg, s390_r13);
3504 s390_ltgr (code, s390_r1, ins->sreg1);
3505 s390_jz (code, 0); CODEPTR(code, o[0]);
3506 s390_ltgr (code, s390_r0, ins->sreg2);
3508 s390_lghi (code, s390_r1, 0);
3509 s390_j (code, 0); CODEPTR(code, o[1]);
3510 s390_xgr (code, s390_r0, s390_r1);
3511 s390_msgr (code, s390_r1, ins->sreg2);
3512 s390_xgr (code, s390_r0, s390_r1);
3513 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3514 s390_ltgr (code, s390_r0, s390_r0);
3515 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3516 PTRSLOT (code, o[0]);
3517 PTRSLOT (code, o[1]);
3518 s390_lgr (code, ins->dreg, s390_r1);
3521 case OP_LMUL_OVF_UN: {
3522 s390_lghi (code, s390_r0, 0);
3523 s390_lgr (code, s390_r1, ins->sreg1);
3524 s390_mlgr (code, s390_r0, ins->sreg2);
3525 s390_ltgr (code, s390_r0, s390_r0);
3526 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3527 s390_lgr (code, ins->dreg, s390_r1);
3531 g_assert_not_reached ();
3533 s390_algr (code, ins->dreg, src2);
3538 s390_agr (code, ins->dreg, src2);
3542 g_assert_not_reached ();
3544 s390_alcgr (code, ins->dreg, src2);
3548 if (ins->dreg != ins->sreg1) {
3549 s390_lgfr (code, ins->dreg, ins->sreg1);
3551 if (s390_is_imm16 (ins->inst_imm)) {
3552 s390_aghi (code, ins->dreg, ins->inst_imm);
3554 s390_afi (code, ins->dreg, ins->inst_imm);
3559 if (ins->dreg != ins->sreg1) {
3560 s390_lgfr (code, ins->dreg, ins->sreg1);
3562 if (s390_is_imm16 (ins->inst_imm)) {
3563 s390_lghi (code, s390_r0, ins->inst_imm);
3564 s390_alcgr (code, ins->dreg, s390_r0);
3566 S390_SET (code, s390_r0, ins->inst_imm);
3567 s390_alcgr (code, ins->dreg, s390_r0);
3572 case OP_S390_LADD_OVF: {
3574 s390_agr (code, ins->dreg, src2);
3575 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3578 case OP_LADD_OVF_UN:
3579 case OP_S390_LADD_OVF_UN: {
3581 s390_algr (code, ins->dreg, src2);
3582 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3586 CHECK_SRCDST_NCOM_I;
3587 s390_slgr (code, ins->dreg, src2);
3591 CHECK_SRCDST_NCOM_I;
3592 s390_sgr (code, ins->dreg, src2);
3596 CHECK_SRCDST_NCOM_I;
3597 s390_slbgr (code, ins->dreg, src2);
3601 if (ins->dreg != ins->sreg1) {
3602 s390_lgfr (code, ins->dreg, ins->sreg1);
3604 if (s390_is_imm16 (-ins->inst_imm)) {
3605 s390_aghi (code, ins->dreg, -ins->inst_imm);
3607 s390_agfi (code, ins->dreg, -ins->inst_imm);
3612 S390_SET (code, s390_r0, ins->inst_imm);
3613 s390_slgfr (code, ins->dreg, s390_r0);
3617 case OP_S390_ISUB_OVF: {
3619 s390_sr (code, ins->dreg, src2);
3620 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3621 s390_lgfr (code, ins->dreg, ins->dreg);
3624 case OP_ISUB_OVF_UN:
3625 case OP_S390_ISUB_OVF_UN: {
3627 s390_slr (code, ins->dreg, src2);
3628 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3629 s390_llgfr(code, ins->dreg, ins->dreg);
3633 case OP_S390_LSUB_OVF: {
3635 s390_sgr (code, ins->dreg, src2);
3636 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3639 case OP_LSUB_OVF_UN:
3640 case OP_S390_LSUB_OVF_UN: {
3642 s390_slgr (code, ins->dreg, src2);
3643 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3647 CHECK_SRCDST_NCOM_I;
3648 s390_ngr (code, ins->dreg, src2);
3652 if (ins->dreg != ins->sreg1) {
3653 s390_lgfr (code, ins->dreg, ins->sreg1);
3655 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3656 s390_ngr (code, ins->dreg, s390_r0);
3660 s390_lgfr (code, s390_r0, ins->sreg1);
3661 s390_srda (code, s390_r0, 0, 32);
3662 s390_dr (code, s390_r0, ins->sreg2);
3663 s390_lgfr (code, ins->dreg, s390_r1);
3667 s390_lgfr (code, s390_r0, ins->sreg1);
3668 s390_srdl (code, s390_r0, 0, 32);
3669 s390_dlr (code, s390_r0, ins->sreg2);
3670 s390_lgfr (code, ins->dreg, s390_r1);
3674 if (s390_is_imm16 (ins->inst_imm)) {
3675 s390_lghi (code, s390_r13, ins->inst_imm);
3677 s390_lgfi (code, s390_r13, ins->inst_imm);
3679 s390_lgfr (code, s390_r0, ins->sreg1);
3680 s390_srda (code, s390_r0, 0, 32);
3681 s390_dr (code, s390_r0, ins->sreg2);
3682 s390_lgfr (code, ins->dreg, s390_r1);
3686 s390_lgfr (code, s390_r0, ins->sreg1);
3687 s390_srda (code, s390_r0, 0, 32);
3688 s390_dr (code, s390_r0, ins->sreg2);
3689 s390_lgfr (code, ins->dreg, s390_r0);
3692 s390_lgfr (code, s390_r0, ins->sreg1);
3693 s390_srdl (code, s390_r0, 0, 32);
3694 s390_dlr (code, s390_r0, ins->sreg2);
3695 s390_lgfr (code, ins->dreg, s390_r0);
3699 if (s390_is_imm16 (ins->inst_imm)) {
3700 s390_lghi (code, s390_r13, ins->inst_imm);
3702 s390_lgfi (code, s390_r13, ins->inst_imm);
3704 s390_lgfr (code, s390_r0, ins->sreg1);
3705 s390_srda (code, s390_r0, 0, 32);
3706 s390_dr (code, s390_r0, ins->sreg2);
3707 s390_lgfr (code, ins->dreg, s390_r0);
3712 s390_ogr (code, ins->dreg, src2);
3716 if (ins->dreg != ins->sreg1) {
3717 s390_lgfr (code, ins->dreg, ins->sreg1);
3719 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3720 s390_ogr (code, ins->dreg, s390_r0);
3725 s390_xgr (code, ins->dreg, src2);
3729 if (ins->dreg != ins->sreg1) {
3730 s390_lgfr (code, ins->dreg, ins->sreg1);
3732 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3733 s390_xgr (code, ins->dreg, s390_r0);
3738 s390_sll (code, ins->dreg, src2, 0);
3742 if (ins->sreg1 != ins->dreg) {
3743 s390_lgfr (code, ins->dreg, ins->sreg1);
3745 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3750 s390_sra (code, ins->dreg, src2, 0);
3754 if (ins->sreg1 != ins->dreg) {
3755 s390_lgfr (code, ins->dreg, ins->sreg1);
3757 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3760 case OP_ISHR_UN_IMM: {
3761 if (ins->sreg1 != ins->dreg) {
3762 s390_lgfr (code, ins->dreg, ins->sreg1);
3764 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3769 s390_srl (code, ins->dreg, src2, 0);
3773 if (ins->sreg1 != ins->dreg) {
3774 s390_lgfr (code, ins->dreg, ins->sreg1);
3776 s390_lghi (code, s390_r0, -1);
3777 s390_xgr (code, ins->dreg, s390_r0);
3781 s390_lcgr (code, ins->dreg, ins->sreg1);
3786 s390_msr (code, ins->dreg, src2);
3790 if (ins->dreg != ins->sreg1) {
3791 s390_lgfr (code, ins->dreg, ins->sreg1);
3793 if (s390_is_imm16 (ins->inst_imm)) {
3794 s390_lghi (code, s390_r0, ins->inst_imm);
3796 s390_lgfi (code, s390_r0, ins->inst_imm);
3798 s390_msr (code, ins->dreg, s390_r0);
3803 s390_ltr (code, s390_r1, ins->sreg1);
3804 s390_jz (code, 0); CODEPTR(code, o[0]);
3805 s390_ltr (code, s390_r0, ins->sreg2);
3807 s390_lhi (code, s390_r1, 0);
3808 s390_j (code, 0); CODEPTR(code, o[1]);
3809 s390_xr (code, s390_r0, s390_r1);
3810 s390_msr (code, s390_r1, ins->sreg2);
3811 s390_xr (code, s390_r0, s390_r1);
3812 s390_srl (code, s390_r0, 0, 31);
3813 s390_ltr (code, s390_r0, s390_r0);
3814 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3815 PTRSLOT (code, o[0]);
3816 PTRSLOT (code, o[1]);
3817 s390_lgfr (code, ins->dreg, s390_r1);
3820 case OP_IMUL_OVF_UN: {
3821 s390_lhi (code, s390_r0, 0);
3822 s390_lr (code, s390_r1, ins->sreg1);
3823 s390_mlr (code, s390_r0, ins->sreg2);
3824 s390_ltr (code, s390_r0, s390_r0);
3825 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3826 s390_lgfr (code, ins->dreg, s390_r1);
3831 S390_SET (code, ins->dreg, ins->inst_c0);
3835 mono_add_patch_info (cfg, code - cfg->native_code,
3836 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3837 S390_LOAD_TEMPLATE (code, ins->dreg);
3840 case OP_JUMP_TABLE: {
3841 mono_add_patch_info (cfg, code - cfg->native_code,
3842 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3843 S390_LOAD_TEMPLATE (code, ins->dreg);
3847 if (ins->dreg != ins->sreg1) {
3848 s390_lgr (code, ins->dreg, ins->sreg1);
3852 case OP_LCONV_TO_I8:
3854 s390_lgfr (code, ins->dreg, ins->sreg1);
3856 case OP_LCONV_TO_I4:
3857 s390_lgfr (code, ins->dreg, ins->sreg1);
3860 case OP_LCONV_TO_U8:
3861 case OP_LCONV_TO_U4:
3863 s390_llgfr (code, ins->dreg, ins->sreg1);
3865 case OP_LCONV_TO_OVF_U4:
3866 S390_SET (code, s390_r0, 4294967295);
3867 s390_clgr (code, ins->sreg1, s390_r0);
3868 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3869 s390_ltgr (code, ins->sreg1, ins->sreg1);
3870 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3871 s390_llgfr(code, ins->dreg, ins->sreg1);
3873 case OP_LCONV_TO_OVF_I4_UN:
3874 S390_SET (code, s390_r0, 2147483647);
3875 s390_cgr (code, ins->sreg1, s390_r0);
3876 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3877 s390_ltgr (code, ins->sreg1, ins->sreg1);
3878 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3879 s390_lgfr (code, ins->dreg, ins->sreg1);
3882 if (ins->dreg != ins->sreg1) {
3883 s390_ldr (code, ins->dreg, ins->sreg1);
3886 case OP_MOVE_F_TO_I8:
3887 s390_lgdr (code, ins->dreg, ins->sreg1);
3889 case OP_MOVE_I8_TO_F:
3890 s390_ldgr (code, ins->dreg, ins->sreg1);
3892 case OP_MOVE_F_TO_I4:
3893 s390_ledbr (code, s390_f0, ins->sreg1);
3894 s390_lgdr (code, ins->dreg, s390_f0);
3895 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3897 case OP_MOVE_I4_TO_F:
3898 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3899 s390_ldgr (code, ins->dreg, s390_r0);
3900 s390_ldebr (code, ins->dreg, ins->dreg);
3902 case OP_FCONV_TO_R4:
3903 s390_ledbr (code, ins->dreg, ins->sreg1);
3904 s390_ldebr (code, ins->dreg, ins->dreg);
3906 case OP_S390_SETF4RET:
3907 s390_ledbr (code, ins->dreg, ins->sreg1);
3910 if (s390_is_imm16 (ins->inst_offset)) {
3911 s390_lghi (code, s390_r13, ins->inst_offset);
3912 } else if (s390_is_imm32 (ins->inst_offset)) {
3913 s390_lgfi (code, s390_r13, ins->inst_offset);
3915 S390_SET (code, s390_r13, ins->inst_offset);
3917 s390_ear (code, s390_r1, 0);
3918 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3919 s390_ear (code, s390_r1, 1);
3920 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3924 if (cfg->method->save_lmf)
3925 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3927 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3928 code = emit_load_volatile_arguments (code, cfg);
3931 code = backUpStackPtr(cfg, code);
3932 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3933 mono_add_patch_info (cfg, code - cfg->native_code,
3934 MONO_PATCH_INFO_METHOD_JUMP,
3936 s390_jcl (code, S390_CC_UN, 0);
3939 case OP_CHECK_THIS: {
3940 /* ensure ins->sreg1 is not NULL */
3941 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3942 s390_ltgr (code, s390_r0, s390_r0);
3943 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3947 int offset = cfg->sig_cookie + cfg->stack_usage;
3949 if (s390_is_imm16 (offset)) {
3950 s390_lghi (code, s390_r0, offset);
3951 } else if (s390_is_imm32 (offset)) {
3952 s390_lgfi (code, s390_r0, offset);
3954 S390_SET (code, s390_r0, offset);
3956 s390_agr (code, s390_r0, cfg->frame_reg);
3957 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3961 call = (MonoCallInst*)ins;
3962 if (ins->flags & MONO_INST_HAS_METHOD)
3963 mono_add_patch_info (cfg, code-cfg->native_code,
3964 MONO_PATCH_INFO_METHOD,
3967 mono_add_patch_info (cfg, code-cfg->native_code,
3968 MONO_PATCH_INFO_ABS,
3970 S390_CALL_TEMPLATE (code, s390_r14);
3971 if (call->signature->ret->type == MONO_TYPE_R4)
3972 s390_ldebr (code, s390_f0, s390_f0);
3980 call = (MonoCallInst*)ins;
3981 if (ins->flags & MONO_INST_HAS_METHOD)
3982 mono_add_patch_info (cfg, code-cfg->native_code,
3983 MONO_PATCH_INFO_METHOD,
3986 mono_add_patch_info (cfg, code-cfg->native_code,
3987 MONO_PATCH_INFO_ABS,
3989 S390_CALL_TEMPLATE (code, s390_r14);
3992 case OP_FCALL_REG: {
3993 call = (MonoCallInst*)ins;
3994 s390_lgr (code, s390_r1, ins->sreg1);
3995 s390_basr (code, s390_r14, s390_r1);
3996 if (call->signature->ret->type == MONO_TYPE_R4)
3997 s390_ldebr (code, s390_f0, s390_f0);
4003 case OP_VOIDCALL_REG:
4005 s390_lgr (code, s390_r1, ins->sreg1);
4006 s390_basr (code, s390_r14, s390_r1);
4009 case OP_FCALL_MEMBASE: {
4010 call = (MonoCallInst*)ins;
4011 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4012 s390_basr (code, s390_r14, s390_r1);
4013 if (call->signature->ret->type == MONO_TYPE_R4)
4014 s390_ldebr (code, s390_f0, s390_f0);
4017 case OP_LCALL_MEMBASE:
4018 case OP_VCALL_MEMBASE:
4019 case OP_VCALL2_MEMBASE:
4020 case OP_VOIDCALL_MEMBASE:
4021 case OP_CALL_MEMBASE: {
4022 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4023 s390_basr (code, s390_r14, s390_r1);
4030 if (cfg->param_area == 0)
4031 alloca_skip = S390_MINIMAL_STACK_SIZE;
4033 alloca_skip = cfg->param_area;
4035 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4036 s390_lgr (code, s390_r1, ins->sreg1);
4037 if (ins->flags & MONO_INST_INIT)
4038 s390_lgr (code, s390_r0, ins->sreg1);
4039 s390_aghi (code, s390_r1, 14);
4040 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4041 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4042 if (cfg->method->save_lmf) {
4043 /*----------------------------------*/
4044 /* we have to adjust lmf ebp value */
4045 /*----------------------------------*/
4046 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4048 s390_lgr (code, s390_r13, cfg->frame_reg);
4049 if (s390_is_imm16(lmfOffset)) {
4050 s390_aghi (code, s390_r13, lmfOffset);
4051 } else if (s390_is_imm32(lmfOffset)) {
4052 s390_agfi (code, s390_r13, lmfOffset);
4054 S390_SET (code, s390_r13, lmfOffset);
4056 s390_lgr (code, s390_r14, STK_BASE);
4057 s390_sgr (code, s390_r14, s390_r1);
4058 s390_stg (code, s390_r14, 0, s390_r13,
4059 G_STRUCT_OFFSET(MonoLMF, ebp));
4061 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4062 s390_sgr (code, STK_BASE, s390_r1);
4063 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4064 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4065 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4066 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4067 if (ins->flags & MONO_INST_INIT) {
4068 s390_lgr (code, s390_r1, s390_r0);
4069 s390_lgr (code, s390_r0, ins->dreg);
4070 s390_lgr (code, s390_r14, s390_r12);
4071 s390_lghi (code, s390_r13, 0);
4072 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4074 s390_lgr (code, s390_r12, s390_r14);
4079 s390_lgr (code, s390_r2, ins->sreg1);
4080 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4081 (gpointer) "mono_arch_throw_exception");
4082 S390_CALL_TEMPLATE(code, s390_r14);
4086 s390_lgr (code, s390_r2, ins->sreg1);
4087 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4088 (gpointer) "mono_arch_rethrow_exception");
4089 S390_CALL_TEMPLATE(code, s390_r14);
4092 case OP_START_HANDLER: {
4093 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4095 S390_LONG (code, stg, stg, s390_r14, 0,
4096 spvar->inst_basereg,
4097 spvar->inst_offset);
4100 case OP_ENDFILTER: {
4101 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4103 if (ins->sreg1 != s390_r2)
4104 s390_lgr(code, s390_r2, ins->sreg1);
4105 S390_LONG (code, lg, lg, s390_r14, 0,
4106 spvar->inst_basereg,
4107 spvar->inst_offset);
4108 s390_br (code, s390_r14);
4111 case OP_ENDFINALLY: {
4112 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4114 S390_LONG (code, lg, lg, s390_r14, 0,
4115 spvar->inst_basereg,
4116 spvar->inst_offset);
4117 s390_br (code, s390_r14);
4120 case OP_CALL_HANDLER: {
4121 mono_add_patch_info (cfg, code-cfg->native_code,
4122 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4123 s390_brasl (code, s390_r14, 0);
4124 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4128 ins->inst_c0 = code - cfg->native_code;
4131 case OP_RELAXED_NOP:
4134 case OP_DUMMY_STORE:
4135 case OP_NOT_REACHED:
4139 case OP_IL_SEQ_POINT:
4140 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4142 case OP_SEQ_POINT: {
4145 if (cfg->compile_aot)
4149 * Read from the single stepping trigger page. This will cause a
4150 * SIGSEGV when single stepping is enabled.
4151 * We do this _before_ the breakpoint, so single stepping after
4152 * a breakpoint is hit will step to the next IL offset.
4154 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4155 breakpointCode.pTrigger = ss_trigger_page;
4156 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4157 code += BREAKPOINT_SIZE;
4160 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4163 * A placeholder for a possible breakpoint inserted by
4164 * mono_arch_set_breakpoint ().
4166 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4170 * Add an additional nop so skipping the bp doesn't cause the ip to point
4171 * to another IL offset.
4177 case OP_GENERIC_CLASS_INIT: {
4178 static int byte_offset = -1;
4179 static guint8 bitmask;
4182 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4184 if (byte_offset < 0)
4185 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4187 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4188 s390_jo (code, 0); CODEPTR(code, jump);
4190 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4191 "mono_generic_class_init");
4192 S390_CALL_TEMPLATE(code, s390_r14);
4194 PTRSLOT (code, jump);
4196 ins->flags |= MONO_INST_GC_CALLSITE;
4197 ins->backend.pc_offset = code - cfg->native_code;
4201 EMIT_UNCOND_BRANCH(ins);
4204 s390_br (code, ins->sreg1);
4210 s390_lghi(code, ins->dreg, 1);
4212 s390_lghi(code, ins->dreg, 0);
4218 s390_lghi(code, ins->dreg, 1);
4220 s390_lghi(code, ins->dreg, 0);
4226 s390_lghi(code, ins->dreg, 1);
4228 s390_lghi(code, ins->dreg, 0);
4234 s390_lghi(code, ins->dreg, 1);
4236 s390_lghi(code, ins->dreg, 0);
4242 s390_lghi(code, ins->dreg, 1);
4244 s390_lghi(code, ins->dreg, 0);
4247 case OP_COND_EXC_EQ:
4248 case OP_COND_EXC_IEQ:
4249 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4251 case OP_COND_EXC_NE_UN:
4252 case OP_COND_EXC_INE_UN:
4253 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4255 case OP_COND_EXC_LT:
4256 case OP_COND_EXC_ILT:
4257 case OP_COND_EXC_LT_UN:
4258 case OP_COND_EXC_ILT_UN:
4259 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4261 case OP_COND_EXC_GT:
4262 case OP_COND_EXC_IGT:
4263 case OP_COND_EXC_GT_UN:
4264 case OP_COND_EXC_IGT_UN:
4265 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4267 case OP_COND_EXC_GE:
4268 case OP_COND_EXC_IGE:
4269 case OP_COND_EXC_GE_UN:
4270 case OP_COND_EXC_IGE_UN:
4271 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4273 case OP_COND_EXC_LE:
4274 case OP_COND_EXC_ILE:
4275 case OP_COND_EXC_LE_UN:
4276 case OP_COND_EXC_ILE_UN:
4277 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4279 case OP_COND_EXC_OV:
4280 case OP_COND_EXC_IOV:
4281 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4283 case OP_COND_EXC_NO:
4284 case OP_COND_EXC_INO:
4285 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4288 case OP_COND_EXC_IC:
4289 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4291 case OP_COND_EXC_NC:
4292 case OP_COND_EXC_INC:
4293 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4297 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4301 EMIT_COND_BRANCH (ins, S390_CC_NE);
4307 EMIT_COND_BRANCH (ins, S390_CC_LT);
4313 EMIT_COND_BRANCH (ins, S390_CC_GT);
4319 EMIT_COND_BRANCH (ins, S390_CC_GE);
4325 EMIT_COND_BRANCH (ins, S390_CC_LE);
4328 /* floating point opcodes */
4330 if (*((double *) ins->inst_p0) == 0) {
4331 s390_lzdr (code, ins->dreg);
4333 S390_SET (code, s390_r13, ins->inst_p0);
4334 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4339 if (*((float *) ins->inst_p0) == 0) {
4340 s390_lzdr (code, ins->dreg);
4342 S390_SET (code, s390_r13, ins->inst_p0);
4343 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4347 case OP_STORER8_MEMBASE_REG: {
4348 S390_LONG (code, stdy, std, ins->sreg1, 0,
4349 ins->inst_destbasereg, ins->inst_offset);
4352 case OP_LOADR8_MEMBASE: {
4353 S390_LONG (code, ldy, ld, ins->dreg, 0,
4354 ins->inst_basereg, ins->inst_offset);
4357 case OP_STORER4_MEMBASE_REG: {
4358 s390_ledbr (code, s390_f15, ins->sreg1);
4359 S390_LONG (code, stey, ste, s390_f15, 0,
4360 ins->inst_destbasereg, ins->inst_offset);
4363 case OP_LOADR4_MEMBASE: {
4364 S390_LONG (code, ley, le, s390_f15, 0,
4365 ins->inst_basereg, ins->inst_offset);
4366 s390_ldebr (code, ins->dreg, s390_f15);
4369 case OP_ICONV_TO_R_UN: {
4371 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4373 s390_llgfr (code, s390_r0, ins->sreg1);
4374 s390_cdgbr (code, ins->dreg, s390_r0);
4378 case OP_LCONV_TO_R_UN: {
4380 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4383 s390_cxgbr (code, s390_f12, ins->sreg1);
4384 s390_ltgr (code, ins->sreg1, ins->sreg1);
4385 s390_jnl (code, 0); CODEPTR(code, jump);
4386 S390_SET (code, s390_r13, 0x403f000000000000llu);
4387 s390_lgdr (code, s390_f13, s390_r13);
4388 s390_lzdr (code, s390_f15);
4389 s390_axbr (code, s390_f12, s390_f13);
4390 PTRSLOT(code, jump);
4391 s390_ldxbr (code, s390_f13, s390_f12);
4392 s390_ldr (code, ins->dreg, s390_f13);
4396 case OP_LCONV_TO_R4:
4397 case OP_ICONV_TO_R4: {
4398 s390_cegbr (code, ins->dreg, ins->sreg1);
4399 s390_ldebr (code, ins->dreg, ins->dreg);
4402 case OP_LCONV_TO_R8:
4403 case OP_ICONV_TO_R8: {
4404 s390_cdgbr (code, ins->dreg, ins->sreg1);
4407 case OP_FCONV_TO_I1:
4408 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4409 s390_ltgr (code, ins->dreg, ins->dreg);
4411 s390_oill (code, ins->dreg, 0x80);
4412 s390_lghi (code, s390_r0, 0xff);
4413 s390_ngr (code, ins->dreg, s390_r0);
4415 case OP_FCONV_TO_U1:
4417 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4418 s390_lghi (code, s390_r0, 0xff);
4419 s390_ngr (code, ins->dreg, s390_r0);
4421 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4424 case OP_FCONV_TO_I2:
4425 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4426 s390_ltgr (code, ins->dreg, ins->dreg);
4428 s390_oill (code, ins->dreg, 0x8000);
4429 s390_llill (code, s390_r0, 0xffff);
4430 s390_ngr (code, ins->dreg, s390_r0);
4432 case OP_FCONV_TO_U2:
4434 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4435 s390_llill (code, s390_r0, 0xffff);
4436 s390_ngr (code, ins->dreg, s390_r0);
4438 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4441 case OP_FCONV_TO_I4:
4443 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4445 case OP_FCONV_TO_U4:
4448 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4450 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4453 case OP_FCONV_TO_I8:
4454 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4456 case OP_FCONV_TO_U8:
4458 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4460 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4463 case OP_LCONV_TO_OVF_I: {
4464 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4466 s390_ltgr (code, ins->sreg2, ins->sreg2);
4467 s390_jnl (code, 0); CODEPTR(code, o[0]);
4468 s390_ltgr (code, ins->sreg1, ins->sreg1);
4469 s390_jnl (code, 0); CODEPTR(code, o[1]);
4470 s390_lhi (code, s390_r13, -1);
4471 s390_cgr (code, ins->sreg1, s390_r13);
4472 s390_jnz (code, 0); CODEPTR(code, o[2]);
4473 if (ins->dreg != ins->sreg2)
4474 s390_lgr (code, ins->dreg, ins->sreg2);
4475 s390_j (code, 0); CODEPTR(code, o[3]);
4476 PTRSLOT(code, o[0]);
4477 s390_jz (code, 0); CODEPTR(code, o[4]);
4478 PTRSLOT(code, o[1]);
4479 PTRSLOT(code, o[2]);
4480 mono_add_patch_info (cfg, code - cfg->native_code,
4481 MONO_PATCH_INFO_EXC, "OverflowException");
4482 s390_brasl (code, s390_r14, 0);
4483 PTRSLOT(code, o[3]);
4484 PTRSLOT(code, o[4]);
4488 s390_lpdbr (code, ins->dreg, ins->sreg1);
4492 s390_sqdbr (code, ins->dreg, ins->sreg1);
4497 s390_adbr (code, ins->dreg, src2);
4501 CHECK_SRCDST_NCOM_F;
4502 s390_sdbr (code, ins->dreg, src2);
4507 s390_mdbr (code, ins->dreg, src2);
4511 CHECK_SRCDST_NCOM_F;
4512 s390_ddbr (code, ins->dreg, src2);
4516 s390_lcdbr (code, ins->dreg, ins->sreg1);
4520 CHECK_SRCDST_NCOM_F;
4521 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4525 s390_cdbr (code, ins->sreg1, ins->sreg2);
4529 s390_cdbr (code, ins->sreg1, ins->sreg2);
4530 s390_lghi (code, ins->dreg, 1);
4532 s390_lghi (code, ins->dreg, 0);
4536 s390_cdbr (code, ins->sreg1, ins->sreg2);
4537 s390_lghi (code, ins->dreg, 1);
4539 s390_lghi (code, ins->dreg, 0);
4543 s390_cdbr (code, ins->sreg1, ins->sreg2);
4544 s390_lghi (code, ins->dreg, 1);
4546 s390_lghi (code, ins->dreg, 0);
4550 s390_cdbr (code, ins->sreg1, ins->sreg2);
4551 s390_lghi (code, ins->dreg, 1);
4553 s390_lghi (code, ins->dreg, 0);
4557 s390_cdbr (code, ins->sreg1, ins->sreg2);
4558 s390_lghi (code, ins->dreg, 1);
4560 s390_lghi (code, ins->dreg, 0);
4565 s390_jo (code, 0); CODEPTR(code, o);
4566 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4571 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4575 s390_jo (code, 0); CODEPTR(code, o);
4576 EMIT_COND_BRANCH (ins, S390_CC_LT);
4581 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4585 s390_jo (code, 0); CODEPTR(code, o);
4586 EMIT_COND_BRANCH (ins, S390_CC_GT);
4591 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4595 s390_jo (code, 0); CODEPTR(code, o);
4596 EMIT_COND_BRANCH (ins, S390_CC_GE);
4601 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4605 s390_jo (code, 0); CODEPTR(code, o);
4606 EMIT_COND_BRANCH (ins, S390_CC_LE);
4611 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4615 s390_lhi (code, s390_r13, 0x7f);
4616 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4617 s390_jz (code, 0); CODEPTR(code, o);
4618 mono_add_patch_info (cfg, code - cfg->native_code,
4619 MONO_PATCH_INFO_EXC, "OverflowException");
4620 s390_brasl (code, s390_r14,0);
4624 case OP_S390_MOVE: {
4625 if (ins->backend.size > 0) {
4626 if (ins->backend.size <= 256) {
4627 s390_mvc (code, ins->backend.size, ins->dreg,
4628 ins->inst_offset, ins->sreg1, ins->inst_imm);
4630 s390_lgr (code, s390_r0, ins->dreg);
4631 if (ins->inst_offset > 0) {
4632 if (s390_is_imm16 (ins->inst_offset)) {
4633 s390_aghi (code, s390_r0, ins->inst_offset);
4634 } else if (s390_is_imm32 (ins->inst_offset)) {
4635 s390_agfi (code, s390_r0, ins->inst_offset);
4637 S390_SET (code, s390_r13, ins->inst_offset);
4638 s390_agr (code, s390_r0, s390_r13);
4641 s390_lgr (code, s390_r12, ins->sreg1);
4642 if (ins->inst_imm > 0) {
4643 if (s390_is_imm16 (ins->inst_imm)) {
4644 s390_aghi (code, s390_r12, ins->inst_imm);
4645 } else if (s390_is_imm32 (ins->inst_imm)) {
4646 s390_agfi (code, s390_r12, ins->inst_imm);
4648 S390_SET (code, s390_r13, ins->inst_imm);
4649 s390_agr (code, s390_r12, s390_r13);
4652 if (s390_is_imm16 (ins->backend.size)) {
4653 s390_lghi (code, s390_r1, ins->backend.size);
4654 } else if (s390_is_imm32 (ins->inst_offset)) {
4655 s390_agfi (code, s390_r1, ins->backend.size);
4657 S390_SET (code, s390_r13, ins->backend.size);
4658 s390_agr (code, s390_r1, s390_r13);
4660 s390_lgr (code, s390_r13, s390_r1);
4661 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4667 case OP_ATOMIC_ADD_I8: {
4668 s390_lgr (code, s390_r1, ins->sreg2);
4669 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4670 s390_agr (code, s390_r1, s390_r0);
4671 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4672 s390_jnz (code, -10);
4673 s390_lgr (code, ins->dreg, s390_r1);
4676 case OP_ATOMIC_EXCHANGE_I8: {
4677 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4678 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4679 s390_jnz (code, -6);
4680 s390_lgr (code, ins->dreg, s390_r0);
4683 case OP_ATOMIC_ADD_I4: {
4684 s390_lgfr(code, s390_r1, ins->sreg2);
4685 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4686 s390_agr (code, s390_r1, s390_r0);
4687 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4688 s390_jnz (code, -9);
4689 s390_lgfr(code, ins->dreg, s390_r1);
4692 case OP_ATOMIC_EXCHANGE_I4: {
4693 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4694 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4695 s390_jnz (code, -4);
4696 s390_lgfr(code, ins->dreg, s390_r0);
4699 case OP_S390_BKCHAIN: {
4700 s390_lgr (code, ins->dreg, ins->sreg1);
4701 if (s390_is_imm16 (cfg->stack_offset)) {
4702 s390_aghi (code, ins->dreg, cfg->stack_offset);
4703 } else if (s390_is_imm32 (cfg->stack_offset)) {
4704 s390_agfi (code, ins->dreg, cfg->stack_offset);
4706 S390_SET (code, s390_r13, cfg->stack_offset);
4707 s390_agr (code, ins->dreg, s390_r13);
4711 case OP_MEMORY_BARRIER:
4714 case OP_GC_SAFE_POINT: {
4717 g_assert (mono_threads_is_coop_enabled ());
4719 s390_chi (code, ins->sreg1, 1);
4720 s390_je (code, 0); CODEPTR(code, br);
4721 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4722 mono_threads_state_poll);
4723 S390_CALL_TEMPLATE (code, s390_r14);
4727 case OP_GC_LIVENESS_DEF:
4728 case OP_GC_LIVENESS_USE:
4729 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4730 ins->backend.pc_offset = code - cfg->native_code;
4732 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4733 ins->backend.pc_offset = code - cfg->native_code;
4734 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4736 #ifdef MONO_ARCH_SIMD_INTRINSICS
4738 s390x_addps (code, ins->sreg1, ins->sreg2);
4741 s390x_divps (code, ins->sreg1, ins->sreg2);
4744 s390x_mulps (code, ins->sreg1, ins->sreg2);
4747 s390x_subps (code, ins->sreg1, ins->sreg2);
4750 s390x_maxps (code, ins->sreg1, ins->sreg2);
4753 s390x_minps (code, ins->sreg1, ins->sreg2);
4756 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4757 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4760 s390x_andps (code, ins->sreg1, ins->sreg2);
4763 s390x_andnps (code, ins->sreg1, ins->sreg2);
4766 s390x_orps (code, ins->sreg1, ins->sreg2);
4769 s390x_xorps (code, ins->sreg1, ins->sreg2);
4772 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4775 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4778 s390x_rcpps (code, ins->dreg, ins->sreg1);
4781 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4784 s390x_haddps (code, ins->sreg1, ins->sreg2);
4787 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4790 s390x_movshdup (code, ins->dreg, ins->sreg1);
4793 s390x_movsldup (code, ins->dreg, ins->sreg1);
4796 case OP_PSHUFLEW_HIGH:
4797 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4798 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4800 case OP_PSHUFLEW_LOW:
4801 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4802 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4805 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4806 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4809 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4810 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4813 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4814 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4818 s390x_addpd (code, ins->sreg1, ins->sreg2);
4821 s390x_divpd (code, ins->sreg1, ins->sreg2);
4824 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4827 s390x_subpd (code, ins->sreg1, ins->sreg2);
4830 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4833 s390x_minpd (code, ins->sreg1, ins->sreg2);
4836 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4837 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4840 s390x_andpd (code, ins->sreg1, ins->sreg2);
4843 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4846 s390x_orpd (code, ins->sreg1, ins->sreg2);
4849 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4852 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4855 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4858 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4861 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4864 s390x_movddup (code, ins->dreg, ins->sreg1);
4867 case OP_EXTRACT_MASK:
4868 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4872 s390x_pand (code, ins->sreg1, ins->sreg2);
4875 s390x_por (code, ins->sreg1, ins->sreg2);
4878 s390x_pxor (code, ins->sreg1, ins->sreg2);
4882 s390x_paddb (code, ins->sreg1, ins->sreg2);
4885 s390x_paddw (code, ins->sreg1, ins->sreg2);
4888 s390x_paddd (code, ins->sreg1, ins->sreg2);
4891 s390x_paddq (code, ins->sreg1, ins->sreg2);
4895 s390x_psubb (code, ins->sreg1, ins->sreg2);
4898 s390x_psubw (code, ins->sreg1, ins->sreg2);
4901 s390x_psubd (code, ins->sreg1, ins->sreg2);
4904 s390x_psubq (code, ins->sreg1, ins->sreg2);
4908 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4911 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4914 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4918 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4921 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4924 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4928 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4931 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4935 s390x_pminub (code, ins->sreg1, ins->sreg2);
4938 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4941 s390x_pminud (code, ins->sreg1, ins->sreg2);
4945 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4948 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4951 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4955 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4958 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4961 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4964 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4968 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4971 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4974 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4977 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4980 case OP_PSUM_ABS_DIFF:
4981 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4984 case OP_UNPACK_LOWB:
4985 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4987 case OP_UNPACK_LOWW:
4988 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4990 case OP_UNPACK_LOWD:
4991 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4993 case OP_UNPACK_LOWQ:
4994 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4996 case OP_UNPACK_LOWPS:
4997 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
4999 case OP_UNPACK_LOWPD:
5000 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5003 case OP_UNPACK_HIGHB:
5004 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5006 case OP_UNPACK_HIGHW:
5007 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5009 case OP_UNPACK_HIGHD:
5010 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5012 case OP_UNPACK_HIGHQ:
5013 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5015 case OP_UNPACK_HIGHPS:
5016 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5018 case OP_UNPACK_HIGHPD:
5019 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5023 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5026 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5029 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5032 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5035 case OP_PADDB_SAT_UN:
5036 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5038 case OP_PSUBB_SAT_UN:
5039 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5041 case OP_PADDW_SAT_UN:
5042 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5044 case OP_PSUBW_SAT_UN:
5045 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5049 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5052 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5055 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5058 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5062 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5065 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5068 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5070 case OP_PMULW_HIGH_UN:
5071 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5074 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5078 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5081 s390x_psrlw (code, ins->dreg, ins->sreg2);
5085 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5088 s390x_psraw (code, ins->dreg, ins->sreg2);
5092 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5095 s390x_psllw (code, ins->dreg, ins->sreg2);
5099 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5102 s390x_psrld (code, ins->dreg, ins->sreg2);
5106 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5109 s390x_psrad (code, ins->dreg, ins->sreg2);
5113 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5116 s390x_pslld (code, ins->dreg, ins->sreg2);
5120 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5123 s390x_psrlq (code, ins->dreg, ins->sreg2);
5126 /*TODO: This is appart of the sse spec but not added
5128 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5131 s390x_psraq (code, ins->dreg, ins->sreg2);
5136 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5139 s390x_psllq (code, ins->dreg, ins->sreg2);
5142 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5145 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5148 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5151 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5154 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5157 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5160 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5163 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5167 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5170 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5174 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5175 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5177 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5182 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5184 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5185 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5189 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5191 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5192 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5193 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5197 amd64_movhlps (code, ins->dreg, ins->sreg1);
5199 s390x_movsd (code, ins->dreg, ins->sreg1);
5202 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5204 case OP_EXTRACTX_U2:
5205 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5207 case OP_INSERTX_U1_SLOW:
5208 /*sreg1 is the extracted ireg (scratch)
5209 /sreg2 is the to be inserted ireg (scratch)
5210 /dreg is the xreg to receive the value*/
5212 /*clear the bits from the extracted word*/
5213 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5214 /*shift the value to insert if needed*/
5215 if (ins->inst_c0 & 1)
5216 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5217 /*join them together*/
5218 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5219 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5221 case OP_INSERTX_I4_SLOW:
5222 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5223 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5224 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5226 case OP_INSERTX_I8_SLOW:
5227 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5229 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5231 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5234 case OP_INSERTX_R4_SLOW:
5235 switch (ins->inst_c0) {
5238 s390x_movss (code, ins->dreg, ins->sreg2);
5240 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5243 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5245 s390x_movss (code, ins->dreg, ins->sreg2);
5247 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5248 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5251 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5253 s390x_movss (code, ins->dreg, ins->sreg2);
5255 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5256 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5259 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5261 s390x_movss (code, ins->dreg, ins->sreg2);
5263 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5264 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5268 case OP_INSERTX_R8_SLOW:
5270 amd64_movlhps (code, ins->dreg, ins->sreg2);
5272 s390x_movsd (code, ins->dreg, ins->sreg2);
5274 case OP_STOREX_MEMBASE_REG:
5275 case OP_STOREX_MEMBASE:
5276 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5278 case OP_LOADX_MEMBASE:
5279 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5281 case OP_LOADX_ALIGNED_MEMBASE:
5282 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5284 case OP_STOREX_ALIGNED_MEMBASE_REG:
5285 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5287 case OP_STOREX_NTA_MEMBASE_REG:
5288 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5290 case OP_PREFETCH_MEMBASE:
5291 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5295 /*FIXME the peephole pass should have killed this*/
5296 if (ins->dreg != ins->sreg1)
5297 s390x_movaps (code, ins->dreg, ins->sreg1);
5300 s390x_pxor (code, ins->dreg, ins->dreg);
5302 case OP_ICONV_TO_R4_RAW:
5303 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5306 case OP_FCONV_TO_R8_X:
5307 s390x_movsd (code, ins->dreg, ins->sreg1);
5310 case OP_XCONV_R8_TO_I4:
5311 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5312 switch (ins->backend.source_opcode) {
5313 case OP_FCONV_TO_I1:
5314 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5316 case OP_FCONV_TO_U1:
5317 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5319 case OP_FCONV_TO_I2:
5320 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5322 case OP_FCONV_TO_U2:
5323 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5329 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5330 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5331 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5334 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5335 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5338 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5339 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5343 s390x_movsd (code, ins->dreg, ins->sreg1);
5345 s390x_movsd (code, ins->dreg, ins->sreg1);
5346 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5348 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5351 s390x_movsd (code, ins->dreg, ins->sreg1);
5352 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5356 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5357 g_assert_not_reached ();
5360 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5361 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5362 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5363 g_assert_not_reached ();
5366 last_offset = offset;
5369 cfg->code_len = code - cfg->native_code;
5372 /*========================= End of Function ========================*/
5374 /*------------------------------------------------------------------*/
5376 /* Name - mono_arch_register_lowlevel_calls */
5378 /* Function - Register routines to help with --trace operation. */
5380 /*------------------------------------------------------------------*/
5383 mono_arch_register_lowlevel_calls (void)
5387 /*========================= End of Function ========================*/
5389 /*------------------------------------------------------------------*/
5391 /* Name - mono_arch_patch_code */
5393 /* Function - Process the patch data created during the */
5394 /* instruction build process. This resolves jumps, */
5395 /* calls, variables etc. */
5397 /*------------------------------------------------------------------*/
5400 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5401 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5404 MonoJumpInfo *patch_info;
5406 mono_error_init (error);
5408 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5409 unsigned char *ip = patch_info->ip.i + code;
5410 gconstpointer target = NULL;
5412 target = mono_resolve_patch_target (method, domain, code,
5413 patch_info, run_cctors, error);
5414 return_if_nok (error);
5416 switch (patch_info->type) {
5417 case MONO_PATCH_INFO_IP:
5418 case MONO_PATCH_INFO_LDSTR:
5419 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5420 case MONO_PATCH_INFO_LDTOKEN:
5421 case MONO_PATCH_INFO_EXC:
5422 s390_patch_addr (ip, (guint64) target);
5424 case MONO_PATCH_INFO_METHOD:
5425 case MONO_PATCH_INFO_INTERNAL_METHOD:
5426 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5427 case MONO_PATCH_INFO_RGCTX_FETCH:
5428 case MONO_PATCH_INFO_ABS: {
5429 S390_EMIT_CALL (ip, target);
5432 case MONO_PATCH_INFO_SWITCH:
5433 /*----------------------------------*/
5434 /* ip points at the basr r13,0/j +4 */
5435 /* instruction the vtable value */
5436 /* follows this (i.e. ip+6) */
5437 /*----------------------------------*/
5438 S390_EMIT_LOAD (ip, target);
5440 case MONO_PATCH_INFO_METHODCONST:
5441 case MONO_PATCH_INFO_CLASS:
5442 case MONO_PATCH_INFO_IMAGE:
5443 case MONO_PATCH_INFO_FIELD:
5444 case MONO_PATCH_INFO_IID:
5445 case MONO_PATCH_INFO_EXC_NAME:
5446 target = S390_RELATIVE(target, ip);
5447 s390_patch_rel (ip, (guint64) target);
5449 case MONO_PATCH_INFO_R4:
5450 case MONO_PATCH_INFO_R8:
5451 case MONO_PATCH_INFO_METHOD_REL:
5452 g_assert_not_reached ();
5455 target = S390_RELATIVE(target, ip);
5457 s390_patch_rel (ip, (guint64) target);
5462 /*========================= End of Function ========================*/
5464 /*------------------------------------------------------------------*/
5466 /* Name - emit_load_volatile_arguments */
5468 /* Function - Emit the instructions to reload parameter regist- */
5469 /* registers for use with "tail" operations. */
5471 /* The register loading operations performed here */
5472 /* are the mirror of the store operations performed */
5473 /* in mono_arch_emit_prolog and need to be kept in */
5474 /* synchronization with it. */
5476 /*------------------------------------------------------------------*/
5479 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5482 MonoMethod *method = cfg->method;
5483 MonoMethodSignature *sig = mono_method_signature(method);
5487 cinfo = get_call_info (NULL, NULL, sig);
5489 if (cinfo->struct_ret) {
5490 ArgInfo *ainfo = &cinfo->ret;
5491 inst = cfg->vret_addr;
5492 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5495 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5496 ArgInfo *ainfo = cinfo->args + i;
5497 inst = cfg->args [pos];
5499 if (inst->opcode == OP_REGVAR) {
5500 if (ainfo->regtype == RegTypeGeneral)
5501 s390_lgr (code, ainfo->reg, inst->dreg);
5502 else if (ainfo->regtype == RegTypeFP) {
5503 if (inst->dreg != ainfo->reg) {
5504 if (ainfo->size == 4) {
5505 s390_ldebr (code, ainfo->reg, inst->dreg);
5507 s390_ldr (code, ainfo->reg, inst->dreg);
5511 else if (ainfo->regtype == RegTypeBase) {
5513 g_assert_not_reached ();
5515 if (ainfo->regtype == RegTypeGeneral) {
5516 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5517 g_assert_not_reached();
5518 switch (ainfo->size) {
5520 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5523 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5526 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5529 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5532 } else if (ainfo->regtype == RegTypeBase) {
5533 } else if (ainfo->regtype == RegTypeFP) {
5534 if (ainfo->size == 8)
5535 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5536 else if (ainfo->size == 4)
5537 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5539 g_assert_not_reached ();
5540 } else if (ainfo->regtype == RegTypeStructByVal) {
5541 if (ainfo->reg != STK_BASE) {
5542 switch (ainfo->size) {
5544 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5547 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5550 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5553 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5557 } else if (ainfo->regtype == RegTypeStructByAddr) {
5558 if (ainfo->reg != STK_BASE) {
5559 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5562 g_assert_not_reached ();
5570 /*========================= End of Function ========================*/
5572 /*------------------------------------------------------------------*/
5574 /* Name - mono_arch_emit_prolog */
5576 /* Function - Create the instruction sequence for a function */
5579 /*------------------------------------------------------------------*/
5582 mono_arch_emit_prolog (MonoCompile *cfg)
5584 MonoMethod *method = cfg->method;
5586 MonoMethodSignature *sig;
5588 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5597 cfg->code_size = 512;
5599 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5601 cfg->code_size += 256;
5602 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5603 cfg->code_size += 256;
5605 if (method->save_lmf)
5606 cfg->code_size += 200;
5608 cfg->native_code = code = g_malloc (cfg->code_size);
5610 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5611 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5612 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5613 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5614 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5616 if (cfg->arch.bkchain_reg != -1)
5617 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5619 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5620 cfg->used_int_regs |= 1 << 11;
5623 alloc_size = cfg->stack_offset;
5625 cfg->stack_usage = cfa_offset = alloc_size;
5626 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5627 s390_lgr (code, s390_r11, STK_BASE);
5628 if (s390_is_imm16 (alloc_size)) {
5629 s390_aghi (code, STK_BASE, -alloc_size);
5630 } else if (s390_is_imm32 (alloc_size)) {
5631 s390_agfi (code, STK_BASE, -alloc_size);
5633 int stackSize = alloc_size;
5634 while (stackSize > INT_MAX) {
5635 s390_agfi (code, STK_BASE, -INT_MAX);
5636 stackSize -= INT_MAX;
5638 s390_agfi (code, STK_BASE, -stackSize);
5640 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5642 if (cfg->frame_reg != STK_BASE)
5643 s390_lgr (code, s390_r11, STK_BASE);
5645 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5647 /* store runtime generic context */
5648 if (cfg->rgctx_var) {
5649 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5651 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5652 cfg->rgctx_var->inst_basereg,
5653 cfg->rgctx_var->inst_offset);
5656 /* compute max_offset in order to use short forward jumps
5657 * we always do it on s390 because the immediate displacement
5658 * for jumps is too small
5661 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5663 bb->max_offset = max_offset;
5665 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5668 MONO_BB_FOR_EACH_INS (bb, ins)
5669 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5672 /* load arguments allocated to register from the stack */
5673 sig = mono_method_signature (method);
5676 cinfo = get_call_info (cfg, cfg->mempool, sig);
5678 if (cinfo->struct_ret) {
5679 ArgInfo *ainfo = &cinfo->ret;
5680 inst = cfg->vret_addr;
5681 inst->backend.size = ainfo->vtsize;
5682 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5685 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5686 ArgInfo *ainfo = cinfo->args + i;
5687 inst = cfg->args [pos];
5689 if (inst->opcode == OP_VTARG_ADDR)
5690 inst = inst->inst_left;
5692 if (inst->opcode == OP_REGVAR) {
5693 if (ainfo->regtype == RegTypeGeneral)
5694 s390_lgr (code, inst->dreg, ainfo->reg);
5695 else if (ainfo->regtype == RegTypeFP) {
5696 if (inst->dreg != ainfo->reg) {
5697 if (ainfo->size == 4) {
5698 s390_ledbr (code, inst->dreg, ainfo->reg);
5700 s390_ldr (code, inst->dreg, ainfo->reg);
5704 else if (ainfo->regtype == RegTypeBase) {
5705 s390_lgr (code, s390_r13, STK_BASE);
5706 s390_aghi (code, s390_r13, alloc_size);
5707 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5709 g_assert_not_reached ();
5711 if (cfg->verbose_level > 2)
5712 g_print ("Argument %d assigned to register %s\n",
5713 pos, mono_arch_regname (inst->dreg));
5715 if (ainfo->regtype == RegTypeGeneral) {
5716 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5717 g_assert_not_reached();
5718 switch (ainfo->size) {
5720 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5723 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5726 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5729 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5732 } else if (ainfo->regtype == RegTypeBase) {
5733 } else if (ainfo->regtype == RegTypeFP) {
5734 if (ainfo->size == 8)
5735 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5736 else if (ainfo->size == 4)
5737 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5739 g_assert_not_reached ();
5740 } else if (ainfo->regtype == RegTypeStructByVal) {
5741 int doffset = inst->inst_offset;
5743 if (ainfo->reg != STK_BASE)
5747 s390_lgr (code, s390_r13, STK_BASE);
5748 s390_aghi (code, s390_r13, alloc_size);
5751 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5752 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5757 if (ainfo->reg == STK_BASE)
5758 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5759 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5762 if (ainfo->reg == STK_BASE)
5763 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5764 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5767 if (ainfo->reg == STK_BASE)
5768 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5769 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5772 if (ainfo->reg == STK_BASE)
5773 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5774 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5777 } else if (ainfo->regtype == RegTypeStructByAddr) {
5778 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5779 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5781 g_assert_not_reached ();
5786 if (method->save_lmf) {
5787 /*---------------------------------------------------------------*/
5788 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5789 /*---------------------------------------------------------------*/
5790 lmfOffset = alloc_size - sizeof(MonoLMF);
5792 s390_lgr (code, s390_r13, cfg->frame_reg);
5793 s390_aghi (code, s390_r13, lmfOffset);
5795 /*---------------------------------------------------------------*/
5796 /* Preserve the parameter registers while we fix up the lmf */
5797 /*---------------------------------------------------------------*/
5798 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5799 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5801 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5802 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5803 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5804 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5805 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5807 /*---------------------------------------------------------------*/
5808 /* On return from this call r2 have the address of the &lmf */
5809 /*---------------------------------------------------------------*/
5810 if (lmf_addr_tls_offset == -1) {
5811 mono_add_patch_info (cfg, code - cfg->native_code,
5812 MONO_PATCH_INFO_INTERNAL_METHOD,
5813 (gpointer)"mono_get_lmf_addr");
5814 S390_CALL_TEMPLATE(code, s390_r1);
5816 /*-------------------------------------------------------*/
5817 /* Get LMF by getting value from thread level storage */
5818 /*-------------------------------------------------------*/
5819 s390_ear (code, s390_r1, 0);
5820 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5821 s390_ear (code, s390_r1, 1);
5822 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5825 /*---------------------------------------------------------------*/
5826 /* Set lmf.lmf_addr = jit_tls->lmf */
5827 /*---------------------------------------------------------------*/
5828 s390_stg (code, s390_r2, 0, s390_r13,
5829 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5830 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5832 /*---------------------------------------------------------------*/
5833 /* Get current lmf */
5834 /*---------------------------------------------------------------*/
5835 s390_lg (code, s390_r0, 0, s390_r2, 0);
5837 /*---------------------------------------------------------------*/
5838 /* Set our lmf as the current lmf */
5839 /*---------------------------------------------------------------*/
5840 s390_stg (code, s390_r13, 0, s390_r2, 0);
5842 /*---------------------------------------------------------------*/
5843 /* Have our lmf.previous_lmf point to the last lmf */
5844 /*---------------------------------------------------------------*/
5845 s390_stg (code, s390_r0, 0, s390_r13,
5846 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5847 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5849 /*---------------------------------------------------------------*/
5850 /* save method info */
5851 /*---------------------------------------------------------------*/
5852 S390_SET (code, s390_r1, method);
5853 s390_stg (code, s390_r1, 0, s390_r13,
5854 G_STRUCT_OFFSET(MonoLMF, method));
5855 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5857 /*---------------------------------------------------------------*/
5858 /* save the current IP */
5859 /*---------------------------------------------------------------*/
5860 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5861 s390_basr (code, s390_r1, 0);
5862 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5863 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5866 /*---------------------------------------------------------------*/
5867 /* Save general and floating point registers */
5868 /*---------------------------------------------------------------*/
5869 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5870 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5871 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5872 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5873 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5883 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5884 for (i = 0; i < 16; i++) {
5885 s390_std (code, i, 0, s390_r13,
5886 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5887 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5888 fpOffset += sizeof(double);
5891 /*---------------------------------------------------------------*/
5892 /* Restore the parameter registers now that we've set up the lmf */
5893 /*---------------------------------------------------------------*/
5894 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5895 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5898 if (cfg->method->save_lmf)
5899 argsClobbered = TRUE;
5902 argsClobbered = TRUE;
5903 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5906 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5907 argsClobbered = TRUE;
5910 * Optimize the common case of the first bblock making a call with the same
5911 * arguments as the method. This works because the arguments are still in their
5912 * original argument registers.
5914 if (!argsClobbered) {
5915 MonoBasicBlock *first_bb = cfg->bb_entry;
5917 int filter = FILTER_IL_SEQ_POINT;
5919 next = mono_bb_first_inst (first_bb, filter);
5920 if (!next && first_bb->next_bb) {
5921 first_bb = first_bb->next_bb;
5922 next = mono_bb_first_inst (first_bb, filter);
5925 if (first_bb->in_count > 1)
5928 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5929 ArgInfo *ainfo = cinfo->args + i;
5930 gboolean match = FALSE;
5932 inst = cfg->args [i];
5933 if (inst->opcode != OP_REGVAR) {
5934 switch (ainfo->regtype) {
5935 case RegTypeGeneral: {
5936 if (((next->opcode == OP_LOAD_MEMBASE) ||
5937 (next->opcode == OP_LOADI4_MEMBASE)) &&
5938 next->inst_basereg == inst->inst_basereg &&
5939 next->inst_offset == inst->inst_offset) {
5940 if (next->dreg == ainfo->reg) {
5944 next->opcode = OP_MOVE;
5945 next->sreg1 = ainfo->reg;
5946 /* Only continue if the instruction doesn't change argument regs */
5947 if (next->dreg == ainfo->reg)
5957 /* Argument allocated to (non-volatile) register */
5958 switch (ainfo->regtype) {
5959 case RegTypeGeneral:
5960 if (next->opcode == OP_MOVE &&
5961 next->sreg1 == inst->dreg &&
5962 next->dreg == ainfo->reg) {
5973 next = mono_inst_next (next, filter);
5980 cfg->code_len = code - cfg->native_code;
5981 g_assert (cfg->code_len < cfg->code_size);
5986 /*========================= End of Function ========================*/
5988 /*------------------------------------------------------------------*/
5990 /* Name - mono_arch_emit_epilog */
5992 /* Function - Emit the instructions for a function epilog. */
5994 /*------------------------------------------------------------------*/
5997 mono_arch_emit_epilog (MonoCompile *cfg)
5999 MonoMethod *method = cfg->method;
6002 int max_epilog_size = 96;
6004 if (cfg->method->save_lmf)
6005 max_epilog_size += 128;
6007 if (mono_jit_trace_calls != NULL)
6008 max_epilog_size += 128;
6009 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6010 max_epilog_size += 128;
6012 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6013 cfg->code_size *= 2;
6014 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6015 cfg->stat_code_reallocs++;
6018 code = cfg->native_code + cfg->code_len;
6020 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6021 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6025 if (method->save_lmf)
6026 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6028 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6029 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6031 code = backUpStackPtr(cfg, code);
6033 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6034 s390_br (code, s390_r14);
6036 cfg->code_len = code - cfg->native_code;
6038 g_assert (cfg->code_len < cfg->code_size);
6042 /*========================= End of Function ========================*/
6044 /*------------------------------------------------------------------*/
6046 /* Name - mono_arch_emit_exceptions */
6048 /* Function - Emit the blocks to handle exception conditions. */
6050 /*------------------------------------------------------------------*/
6053 mono_arch_emit_exceptions (MonoCompile *cfg)
6055 MonoJumpInfo *patch_info;
6061 MonoClass *exc_classes [MAX_EXC];
6062 guint8 *exc_throw_start [MAX_EXC];
6064 for (patch_info = cfg->patch_info;
6066 patch_info = patch_info->next) {
6067 if (patch_info->type == MONO_PATCH_INFO_EXC)
6071 code_size = exc_count * 48;
6073 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6074 cfg->code_size *= 2;
6075 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6076 cfg->stat_code_reallocs++;
6079 code = cfg->native_code + cfg->code_len;
6081 /*---------------------------------------------------------------------*/
6082 /* Add code to raise exceptions */
6083 /*---------------------------------------------------------------------*/
6084 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6085 switch (patch_info->type) {
6086 case MONO_PATCH_INFO_EXC: {
6087 guint8 *ip = patch_info->ip.i + cfg->native_code;
6088 MonoClass *exc_class;
6091 /*-----------------------------------------------------*/
6092 /* Patch the branch in epilog to come here */
6093 /*-----------------------------------------------------*/
6094 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6096 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6098 patch_info->data.name);
6099 throw_ip = patch_info->ip.i;
6101 for (iExc = 0; iExc < nThrows; ++iExc)
6102 if (exc_classes [iExc] == exc_class)
6105 if (iExc < nThrows) {
6106 s390_jcl (code, S390_CC_UN,
6107 (guint64) exc_throw_start [iExc]);
6108 patch_info->type = MONO_PATCH_INFO_NONE;
6111 if (nThrows < MAX_EXC) {
6112 exc_classes [nThrows] = exc_class;
6113 exc_throw_start [nThrows] = code;
6116 /*---------------------------------------------*/
6117 /* Patch the parameter passed to the handler */
6118 /*---------------------------------------------*/
6119 S390_SET (code, s390_r2, exc_class->type_token);
6120 /*---------------------------------------------*/
6121 /* Load return address & parameter register */
6122 /*---------------------------------------------*/
6123 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6124 cfg->native_code + 8), code));
6125 /*---------------------------------------------*/
6126 /* Reuse the current patch to set the jump */
6127 /*---------------------------------------------*/
6128 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6129 patch_info->data.name = "mono_arch_throw_corlib_exception";
6130 patch_info->ip.i = code - cfg->native_code;
6131 S390_BR_TEMPLATE (code, s390_r1);
6141 cfg->code_len = code - cfg->native_code;
6143 g_assert (cfg->code_len < cfg->code_size);
6147 /*========================= End of Function ========================*/
6149 /*------------------------------------------------------------------*/
6151 /* Name - mono_arch_finish_init */
6153 /* Function - Setup the JIT's Thread Level Specific Data. */
6155 /*------------------------------------------------------------------*/
6158 mono_arch_finish_init (void)
6160 appdomain_tls_offset = mono_domain_get_tls_offset();
6161 lmf_tls_offset = mono_get_lmf_tls_offset();
6162 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6165 /*========================= End of Function ========================*/
6167 /*------------------------------------------------------------------*/
6169 /* Name - mono_arch_free_jit_tls_data */
6171 /* Function - Free tls data. */
6173 /*------------------------------------------------------------------*/
6176 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6180 /*========================= End of Function ========================*/
6182 /*------------------------------------------------------------------*/
6184 /* Name - mono_arch_emit_inst_for_method */
6186 /*------------------------------------------------------------------*/
6189 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6194 /*========================= End of Function ========================*/
6196 /*------------------------------------------------------------------*/
6198 /* Name - mono_arch_decompose_opts */
6200 /* Function - Decompose opcode into a System z opcode. */
6202 /*------------------------------------------------------------------*/
6205 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6208 * Have to rename these to avoid being decomposed normally, since the normal
6209 * decomposition does not work on S390.
6211 switch (ins->opcode) {
6213 ins->opcode = OP_S390_ISUB_OVF;
6215 case OP_ISUB_OVF_UN:
6216 ins->opcode = OP_S390_ISUB_OVF_UN;
6219 ins->opcode = OP_S390_IADD_OVF;
6221 case OP_IADD_OVF_UN:
6222 ins->opcode = OP_S390_IADD_OVF_UN;
6225 ins->opcode = OP_S390_LADD_OVF;
6227 case OP_LADD_OVF_UN:
6228 ins->opcode = OP_S390_LADD_OVF_UN;
6231 ins->opcode = OP_S390_LSUB_OVF;
6233 case OP_LSUB_OVF_UN:
6234 ins->opcode = OP_S390_LSUB_OVF_UN;
6241 /*========================= End of Function ========================*/
6243 /*------------------------------------------------------------------*/
6245 /* Name - mono_arch_print_tree */
6247 /* Function - Print platform-specific opcode details. */
6249 /* Returns - 1 - opcode details have been printed */
6250 /* 0 - opcode details have not been printed */
6252 /*------------------------------------------------------------------*/
6255 mono_arch_print_tree (MonoInst *tree, int arity)
6259 switch (tree->opcode) {
6260 case OP_S390_LOADARG:
6261 case OP_S390_ARGREG:
6262 case OP_S390_ARGPTR:
6263 printf ("[0x%lx(%s)]", tree->inst_offset,
6264 mono_arch_regname (tree->inst_basereg));
6267 case OP_S390_STKARG:
6268 printf ("[0x%lx(previous_frame)]",
6273 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6274 tree->inst_offset, tree->backend.size,
6275 mono_arch_regname(tree->dreg),
6277 mono_arch_regname(tree->sreg1));
6280 case OP_S390_SETF4RET:
6281 printf ("[f%s,f%s]",
6282 mono_arch_regname (tree->dreg),
6283 mono_arch_regname (tree->sreg1));
6287 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6289 mono_arch_regname (tree->sreg1));
6292 case OP_S390_BKCHAIN:
6293 printf ("[previous_frame(%s)]",
6294 mono_arch_regname (tree->sreg1));
6302 /*========================= End of Function ========================*/
6304 /*------------------------------------------------------------------*/
6306 /* Name - mono_arch_regalloc_cost */
6308 /* Function - Determine the cost, in the number of memory */
6309 /* references, of the action of allocating the var- */
6310 /* iable VMV into a register during global register */
6313 /* Returns - Cost */
6315 /*------------------------------------------------------------------*/
6318 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6324 /*========================= End of Function ========================*/
6326 /*------------------------------------------------------------------*/
6328 /* Name - mono_arch_flush_register_windows */
6334 /*------------------------------------------------------------------*/
6337 mono_arch_flush_register_windows (void)
6341 /*========================= End of Function ========================*/
6343 /*------------------------------------------------------------------*/
6345 /* Name - mono_arch_is_inst_imm */
6347 /* Function - Determine if operand qualifies as an immediate */
6348 /* value. For s390 this is a value -32768-32768 */
6350 /* Returns - True|False - is [not] immediate value. */
6352 /*------------------------------------------------------------------*/
6355 mono_arch_is_inst_imm (gint64 imm)
6357 return s390_is_imm32 (imm);
6360 /*========================= End of Function ========================*/
6362 /*------------------------------------------------------------------*/
6364 /* Name - mono_arch_get_patch_offset */
6366 /* Function - Dummy entry point until s390x supports aot. */
6368 /* Returns - Offset for patch. */
6370 /*------------------------------------------------------------------*/
6373 mono_arch_get_patch_offset (guint8 *code)
6378 /*========================= End of Function ========================*/
6380 /*------------------------------------------------------------------*/
6382 /* Name - mono_arch_context_get_int_reg. */
6386 /* Returns - Return a register from the context. */
6388 /*------------------------------------------------------------------*/
6391 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6393 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6396 /*========================= End of Function ========================*/
6398 /*------------------------------------------------------------------*/
6400 /* Name - mono_arch_context_set_int_reg. */
6402 /* Function - Set a value in a specified register. */
6404 /*------------------------------------------------------------------*/
6407 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6409 ctx->uc_mcontext.gregs[reg] = val;
6412 /*========================= End of Function ========================*/
6414 /*------------------------------------------------------------------*/
6416 /* Name - mono_arch_get_this_arg_from_call. */
6420 /*------------------------------------------------------------------*/
6423 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6425 return (gpointer) regs [s390_r2];
6428 /*========================= End of Function ========================*/
6430 /*------------------------------------------------------------------*/
6432 /* Name - mono_arch_install_handler_block_guard */
6436 /*------------------------------------------------------------------*/
6439 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6440 MonoContext *ctx, gpointer new_value)
6443 gpointer *sp, old_value;
6446 offset = clause->exvar_offset;
6449 bp = MONO_CONTEXT_GET_BP (ctx);
6450 sp = *(gpointer*)(bp + offset);
6453 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6461 /*========================= End of Function ========================*/
6463 /*------------------------------------------------------------------*/
6465 /* Name - get_delegate_invoke_impl. */
6469 /*------------------------------------------------------------------*/
6472 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6474 guint8 *code, *start;
6479 start = code = mono_global_codeman_reserve (size);
6481 /* Replace the this argument with the target */
6482 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6483 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6484 s390_br (code, s390_r1);
6485 g_assert ((code - start) <= size);
6487 mono_arch_flush_icache (start, size);
6491 size = 32 + param_count * 8;
6492 start = code = mono_global_codeman_reserve (size);
6494 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6495 /* slide down the arguments */
6496 for (i = 0; i < param_count; ++i) {
6497 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6499 s390_br (code, s390_r1);
6501 g_assert ((code - start) <= size);
6503 mono_arch_flush_icache (start, size);
6506 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6509 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6511 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6512 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6519 /*========================= End of Function ========================*/
6521 /*------------------------------------------------------------------*/
6523 /* Name - mono_arch_get_delegate_invoke_impls. */
6527 /*------------------------------------------------------------------*/
6530 mono_arch_get_delegate_invoke_impls (void)
6533 MonoTrampInfo *info;
6536 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6537 res = g_slist_prepend (res, info);
6539 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6540 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6541 res = g_slist_prepend (res, info);
6547 /*========================= End of Function ========================*/
6549 /*------------------------------------------------------------------*/
6551 /* Name - mono_arch_get_delegate_invoke_impl. */
6555 /*------------------------------------------------------------------*/
6558 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6560 guint8 *code, *start;
6562 /* FIXME: Support more cases */
6563 if (MONO_TYPE_ISSTRUCT (sig->ret))
6567 static guint8* cached = NULL;
6572 if (mono_aot_only) {
6573 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6575 MonoTrampInfo *info;
6576 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6577 mono_tramp_info_register (info, NULL);
6580 mono_memory_barrier ();
6584 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6587 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6589 for (i = 0; i < sig->param_count; ++i)
6590 if (!mono_is_regsize_var (sig->params [i]))
6594 code = cache [sig->param_count];
6598 if (mono_aot_only) {
6599 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6600 start = mono_aot_get_trampoline (name);
6603 MonoTrampInfo *info;
6604 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6605 mono_tramp_info_register (info, NULL);
6608 mono_memory_barrier ();
6610 cache [sig->param_count] = start;
6615 /*========================= End of Function ========================*/
6617 /*------------------------------------------------------------------*/
6619 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6623 /*------------------------------------------------------------------*/
6626 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6627 int offset, gboolean load_imt_reg)
6629 guint8 *code, *start;
6632 start = code = mono_global_codeman_reserve (size);
6635 * Replace the "this" argument with the target
6637 s390_lgr (code, s390_r1, s390_r2);
6638 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6641 * Load the IMT register, if needed
6644 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6650 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6652 s390_agfi(code, s390_r1, offset);
6654 s390_lg (code, s390_r1, 0, s390_r1, 0);
6655 s390_br (code, s390_r1);
6660 /*========================= End of Function ========================*/
6662 /*------------------------------------------------------------------*/
6664 /* Name - mono_arch_build_imt_thunk. */
6668 /*------------------------------------------------------------------*/
6671 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
6672 MonoIMTCheckItem **imt_entries, int count,
6673 gpointer fail_tramp)
6677 guchar *code, *start;
6680 for (i = 0; i < count; ++i) {
6681 MonoIMTCheckItem *item = imt_entries [i];
6682 if (item->is_equals) {
6683 if (item->check_target_idx) {
6684 if (!item->compare_done)
6685 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6686 if (item->has_target_code)
6687 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6689 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6693 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6695 if (!item->has_target_code)
6696 item->chunk_size += LOAD_SIZE;
6698 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6699 #if ENABLE_WRONG_METHOD_CHECK
6700 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6705 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6706 imt_entries [item->check_target_idx]->compare_done = TRUE;
6708 size += item->chunk_size;
6712 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6714 code = mono_domain_code_reserve (domain, size);
6718 for (i = 0; i < count; ++i) {
6719 MonoIMTCheckItem *item = imt_entries [i];
6720 item->code_target = (guint8 *) code;
6721 if (item->is_equals) {
6722 if (item->check_target_idx) {
6723 if (!item->compare_done) {
6724 S390_SET (code, s390_r0, item->key);
6725 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6727 item->jmp_code = (guint8*) code;
6728 s390_jcl (code, S390_CC_NE, 0);
6730 if (item->has_target_code) {
6731 S390_SET (code, s390_r1, item->value.target_code);
6733 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6734 s390_lg (code, s390_r1, 0, s390_r1, 0);
6736 s390_br (code, s390_r1);
6741 S390_SET (code, s390_r0, item->key);
6742 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6743 item->jmp_code = (guint8*) code;
6744 s390_jcl (code, S390_CC_NE, 0);
6745 if (item->has_target_code) {
6746 S390_SET (code, s390_r1, item->value.target_code);
6749 S390_SET (code, s390_r1,
6750 (&(vtable->vtable [item->value.vtable_slot])));
6751 s390_lg (code, s390_r1, 0, s390_r1, 0);
6753 s390_br (code, s390_r1);
6754 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6755 s390_patch_rel(item->jmp_code+2, target);
6756 S390_SET (code, s390_r1, fail_tramp);
6757 s390_br (code, s390_r1);
6758 item->jmp_code = NULL;
6760 /* enable the commented code to assert on wrong method */
6761 #if ENABLE_WRONG_METHOD_CHECK
6762 g_assert_not_reached ();
6764 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6765 s390_lg (code, s390_r1, 0, s390_r1, 0);
6766 s390_br (code, s390_r1);
6770 S390_SET (code, s390_r0, item->key);
6771 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6772 item->jmp_code = (guint8 *) code;
6773 s390_jcl (code, S390_CC_GE, 0);
6777 * patch the branches to get to the target items
6779 for (i = 0; i < count; ++i) {
6780 MonoIMTCheckItem *item = imt_entries [i];
6781 if (item->jmp_code) {
6782 if (item->check_target_idx) {
6784 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6786 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6791 mono_arch_flush_icache ((guint8*)start, (code - start));
6792 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6795 mono_stats.imt_thunks_size += (code - start);
6797 g_assert (code - start <= size);
6799 snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6800 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6805 /*========================= End of Function ========================*/
6807 /*------------------------------------------------------------------*/
6809 /* Name - mono_arch_find_imt_method. */
6811 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6812 /* found in the save area. */
6814 /*------------------------------------------------------------------*/
6817 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6819 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6822 /*========================= End of Function ========================*/
6824 /*------------------------------------------------------------------*/
6826 /* Name - mono_arch_find_static_call_vtable */
6828 /* Function - Find the static call vtable. */
6830 /*------------------------------------------------------------------*/
6833 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6835 mgreg_t *r = (mgreg_t*)regs;
6837 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6840 /*========================= End of Function ========================*/
6842 /*------------------------------------------------------------------*/
6844 /* Name - mono_arch_get_cie_program */
6846 /* Function - Find the static call vtable. */
6848 /*------------------------------------------------------------------*/
6851 mono_arch_get_cie_program (void)
6855 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6860 /*========================= End of Function ========================*/
6862 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6864 /*------------------------------------------------------------------*/
6866 /* Name - mono_arch_set_breakpoint. */
6868 /* Function - Set a breakpoint at the native code corresponding */
6869 /* to JI at NATIVE_OFFSET. The location should */
6870 /* contain code emitted by OP_SEQ_POINT. */
6872 /*------------------------------------------------------------------*/
6875 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6879 breakpointCode.pTrigger = bp_trigger_page;
6880 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6881 code += BREAKPOINT_SIZE;
6884 /*========================= End of Function ========================*/
6886 /*------------------------------------------------------------------*/
6888 /* Name - mono_arch_clear_breakpoint. */
6890 /* Function - Clear the breakpoint at IP. */
6892 /*------------------------------------------------------------------*/
6895 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6900 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6904 /*========================= End of Function ========================*/
6906 /*------------------------------------------------------------------*/
6908 /* Name - mono_arch_is_breakpoint_event. */
6912 /*------------------------------------------------------------------*/
6915 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6917 siginfo_t* sinfo = (siginfo_t*) info;
6920 * Sometimes the address is off by 4
6922 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6928 /*========================= End of Function ========================*/
6930 /*------------------------------------------------------------------*/
6932 /* Name - mono_arch_skip_breakpoint. */
6934 /* Function - Modify the CTX so the IP is placed after the */
6935 /* breakpoint instruction, so when we resume, the */
6936 /* instruction is not executed again. */
6938 /*------------------------------------------------------------------*/
6941 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6943 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6946 /*========================= End of Function ========================*/
6948 /*------------------------------------------------------------------*/
6950 /* Name - mono_arch_start_single_stepping. */
6952 /* Function - Start single stepping. */
6954 /*------------------------------------------------------------------*/
6957 mono_arch_start_single_stepping (void)
6959 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6962 /*========================= End of Function ========================*/
6964 /*------------------------------------------------------------------*/
6966 /* Name - mono_arch_stop_single_stepping. */
6968 /* Function - Stop single stepping. */
6970 /*------------------------------------------------------------------*/
6973 mono_arch_stop_single_stepping (void)
6975 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6978 /*========================= End of Function ========================*/
6980 /*------------------------------------------------------------------*/
6982 /* Name - mono_arch_is_single_step_event. */
6984 /* Function - Return whether the machine state in sigctx cor- */
6985 /* responds to a single step event. */
6987 /*------------------------------------------------------------------*/
6990 mono_arch_is_single_step_event (void *info, void *sigctx)
6992 siginfo_t* sinfo = (siginfo_t*) info;
6995 * Sometimes the address is off by 4
6997 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7003 /*========================= End of Function ========================*/
7005 /*------------------------------------------------------------------*/
7007 /* Name - mono_arch_skip_single_step. */
7009 /* Function - Modify the ctx so the IP is placed after the */
7010 /* single step trigger instruction, so that the */
7011 /* instruction is not executed again. */
7013 /*------------------------------------------------------------------*/
7016 mono_arch_skip_single_step (MonoContext *ctx)
7018 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7021 /*========================= End of Function ========================*/
7023 /*------------------------------------------------------------------*/
7025 /* Name - mono_arch_create_seq_point_info. */
7027 /* Function - Return a pointer to a data struction which is */
7028 /* used by the sequence point implementation in */
7031 /*------------------------------------------------------------------*/
7034 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7040 /*========================= End of Function ========================*/
7042 /*------------------------------------------------------------------*/
7044 /* Name - mono_arch_init_lmf_ext. */
7048 /*------------------------------------------------------------------*/
7051 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7053 ext->lmf.previous_lmf = prev_lmf;
7054 /* Mark that this is a MonoLMFExt */
7055 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7056 ext->lmf.ebp = (gssize)ext;
7059 /*========================= End of Function ========================*/
7063 /*------------------------------------------------------------------*/
7065 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7067 /* Function - If this CPU supports vector operations then it */
7068 /* supports the equivalent of SSE1-4. */
7070 /*------------------------------------------------------------------*/
7073 mono_arch_cpu_enumerate_simd_versions (void)
7075 guint32 sseOpts = 0;
7078 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7079 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7080 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7081 SIMD_VERSION_SSE4a);
7086 /*========================= End of Function ========================*/
7088 /*------------------------------------------------------------------*/
7090 /* Name - mono_arch_opcode_supported. */
7092 /* Function - Check if a given return code is supported. */
7094 /*------------------------------------------------------------------*/
7097 mono_arch_opcode_supported (int opcode)
7100 case OP_ATOMIC_ADD_I4:
7101 case OP_ATOMIC_ADD_I8:
7102 case OP_ATOMIC_EXCHANGE_I4:
7103 case OP_ATOMIC_EXCHANGE_I8:
7110 /*========================= End of Function ========================*/