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-error.h>
268 #include <mono/utils/mono-error-internals.h>
269 #include <mono/utils/mono-math.h>
270 #include <mono/utils/mono-mmap.h>
271 #include <mono/utils/mono-hwcap.h>
272 #include <mono/utils/mono-threads.h>
274 #include "mini-s390x.h"
275 #include "cpu-s390x.h"
276 #include "support-s390x.h"
277 #include "jit-icalls.h"
282 /*========================= End of Includes ========================*/
284 /*------------------------------------------------------------------*/
285 /* T y p e d e f s */
286 /*------------------------------------------------------------------*/
298 /*------------------------------------------------------------------*/
299 /* Used by the instrument_emit_epilog */
300 /*------------------------------------------------------------------*/
311 typedef struct InstList InstList;
325 RegTypeStructByValInFP,
327 RegTypeStructByAddrOnStack
331 gint32 offset; /* offset from caller's stack */
332 gint32 offparm; /* offset from callee's stack */
333 guint16 vtsize; /* in param area */
336 guint32 size; /* Size of structure used by RegTypeStructByVal */
337 gint32 type; /* Data type of argument */
353 gint64 gr[5]; /* R2-R6 */
354 gdouble fp[3]; /* F0-F2 */
355 } __attribute__ ((packed)) RegParm;
363 } __attribute__ ((packed)) breakpoint_t;
365 /*========================= End of Typedefs ========================*/
367 /*------------------------------------------------------------------*/
368 /* P r o t o t y p e s */
369 /*------------------------------------------------------------------*/
371 static void indent (int);
372 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
373 static void decodeParm (MonoType *, void *, int);
374 static void enter_method (MonoMethod *, RegParm *, char *);
375 static void leave_method (MonoMethod *, ...);
376 static inline void add_general (guint *, size_data *, ArgInfo *);
377 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
378 static inline void add_float (guint *, size_data *, ArgInfo *);
379 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
380 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
381 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
382 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
384 /*========================= End of Prototypes ======================*/
386 /*------------------------------------------------------------------*/
387 /* G l o b a l V a r i a b l e s */
388 /*------------------------------------------------------------------*/
390 int mono_exc_esp_offset = 0;
392 __thread int indent_level = 0;
394 static gint appdomain_tls_offset = -1,
396 lmf_addr_tls_offset = -1;
398 pthread_key_t lmf_addr_key;
400 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)
772 char *str = mono_string_to_utf8_checked(s, &error);
773 if (is_ok (&error)) {
774 printf("[STRING:%p:%s], ", s, str);
777 mono_error_cleanup (&error);
778 printf("[STRING:%p:], ", s);
783 decodeParm(MonoType *type, void *curParm, int size)
788 printf("[BYREF:%p], ", *((char **) curParm));
790 simpleType = mini_get_underlying_type(type)->type;
792 switch (simpleType) {
794 printf ("[INTPTR:%p], ", *((int **) curParm));
797 printf ("[UINTPTR:%p], ", *((int **) curParm));
799 case MONO_TYPE_BOOLEAN :
800 printf ("[BOOL:%ld], ", *((gint64 *) curParm));
802 case MONO_TYPE_CHAR :
803 printf ("[CHAR:%c], ", *((int *) curParm));
806 printf ("[INT1:%ld], ", *((gint64 *) curParm));
809 printf ("[INT2:%ld], ", *((gint64 *) curParm));
812 printf ("[INT4:%ld], ", *((gint64 *) curParm));
815 printf ("[UINT1:%lu], ", *((guint64 *) curParm));
818 printf ("[UINT2:%lu], ", *((guint64 *) curParm));
821 printf ("[UINT4:%lu], ", *((guint64 *) curParm));
824 printf ("[UINT8:%lu], ", *((guint64 *) curParm));
826 case MONO_TYPE_STRING : {
827 MonoString *s = *((MonoString **) curParm);
829 g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
830 decodeParmString (s);
832 printf("[STRING:null], ");
836 case MONO_TYPE_CLASS :
837 case MONO_TYPE_OBJECT : {
838 MonoObject *obj = *((MonoObject **) curParm);
840 if ((obj) && (obj->vtable)) {
841 printf("[CLASS/OBJ:");
842 klass = obj->vtable->klass;
843 printf("%p [%p] ",obj,curParm);
844 if (klass == mono_defaults.string_class) {
845 decodeParmString ((MonoString *)obj);
846 } else if (klass == mono_defaults.int32_class) {
847 printf("[INT32:%p:%d]",
848 obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
851 klass->name_space, klass->name, obj);
854 printf("[OBJECT:null], ");
859 printf("[PTR:%p], ", *((gpointer **) (curParm)));
861 case MONO_TYPE_FNPTR :
862 printf("[FNPTR:%p], ", *((gpointer **) (curParm)));
864 case MONO_TYPE_ARRAY :
865 printf("[ARRAY:%p], ", *((gpointer **) (curParm)));
867 case MONO_TYPE_SZARRAY :
868 printf("[SZARRAY:%p], ", *((gpointer **) (curParm)));
871 printf("[INT8:%ld], ", *((gint64 *) (curParm)));
874 printf("[FLOAT4:%g], ", *((float *) (curParm)));
877 printf("[FLOAT8:%g], ", *((double *) (curParm)));
879 case MONO_TYPE_VALUETYPE : {
881 MonoMarshalType *info;
883 if (type->data.klass->enumtype) {
884 simpleType = mono_class_enum_basetype (type->data.klass)->type;
885 printf("{VALUETYPE} - ");
889 info = mono_marshal_load_type_info (type->data.klass);
891 if ((info->native_size == sizeof(float)) &&
892 (info->num_fields == 1) &&
893 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
894 printf("[FLOAT4:%f], ", *((float *) (curParm)));
898 if ((info->native_size == sizeof(double)) &&
899 (info->num_fields == 1) &&
900 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
901 printf("[FLOAT8:%g], ", *((double *) (curParm)));
905 printf("[VALUETYPE:");
906 for (i = 0; i < size; i++)
907 printf("%02x,", *((guint8 *)curParm+i));
911 case MONO_TYPE_TYPEDBYREF: {
913 printf("[TYPEDBYREF:");
914 for (i = 0; i < size; i++)
915 printf("%02x,", *((guint8 *)curParm+i));
920 printf("[%s], ",cvtMonoType(simpleType));
925 /*========================= End of Function ========================*/
927 /*------------------------------------------------------------------*/
929 /* Name - enter_method */
931 /* Function - Perform tracing of the entry to the current */
934 /*------------------------------------------------------------------*/
937 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
939 int i, oParm = 0, iParm = 0;
942 MonoMethodSignature *sig;
949 fname = mono_method_full_name (method, TRUE);
951 printf ("ENTER: %s ", fname);
954 ip = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
955 printf ("ip: %p sp: %p - ", (gpointer) ip, sp);
960 sig = mono_method_signature (method);
962 cinfo = get_call_info (NULL, NULL, sig);
964 if (cinfo->struct_ret) {
965 printf ("[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
970 gpointer *this_arg = (gpointer *) rParm->gr[iParm];
971 obj = (MonoObject *) this_arg;
972 switch(method->klass->this_arg.type) {
973 case MONO_TYPE_VALUETYPE:
975 guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
976 printf("this:[value:%p:%016lx], ", this_arg, *value);
978 printf ("this:[NULL], ");
980 case MONO_TYPE_STRING:
983 klass = obj->vtable->klass;
984 if (klass == mono_defaults.string_class) {
986 decodeParmString((MonoString *)obj);
988 printf ("this:%p[%s.%s], ",
989 obj, klass->name_space, klass->name);
992 printf("vtable:[NULL], ");
994 printf ("this:[NULL], ");
997 printf("this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1002 for (i = 0; i < sig->param_count; ++i) {
1003 ainfo = &cinfo->args[i + oParm];
1004 switch (ainfo->regtype) {
1005 case RegTypeGeneral :
1006 decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1009 decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1012 decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1014 case RegTypeStructByVal :
1015 if (ainfo->reg != STK_BASE) {
1016 int offset = sizeof(glong) - ainfo->size;
1017 curParm = &(rParm->gr[ainfo->reg-2])+offset;
1020 curParm = sp+ainfo->offset;
1022 if (retFitsInReg (ainfo->vtsize))
1023 decodeParm(sig->params[i],
1027 decodeParm(sig->params[i],
1028 *((char **) curParm),
1031 case RegTypeStructByAddr :
1032 if (ainfo->reg != STK_BASE)
1033 curParm = &(rParm->gr[ainfo->reg-2]);
1035 curParm = sp+ainfo->offset;
1037 decodeParm(sig->params[i],
1038 *((char **) curParm),
1050 /*========================= End of Function ========================*/
1052 /*------------------------------------------------------------------*/
1054 /* Name - leave_method */
1058 /*------------------------------------------------------------------*/
1061 leave_method (MonoMethod *method, ...)
1068 va_start(ap, method);
1070 fname = mono_method_full_name (method, TRUE);
1072 printf ("LEAVE: %s", fname);
1075 type = mono_method_signature (method)->ret;
1078 switch (type->type) {
1079 case MONO_TYPE_VOID:
1081 case MONO_TYPE_BOOLEAN: {
1082 int val = va_arg (ap, int);
1084 printf ("[TRUE:%d]", val);
1090 case MONO_TYPE_CHAR: {
1091 int val = va_arg (ap, int);
1092 printf ("[CHAR:%d]", val);
1095 case MONO_TYPE_I1: {
1096 int val = va_arg (ap, int);
1097 printf ("[INT1:%d]", val);
1100 case MONO_TYPE_U1: {
1101 int val = va_arg (ap, int);
1102 printf ("[UINT1:%d]", val);
1105 case MONO_TYPE_I2: {
1106 int val = va_arg (ap, int);
1107 printf ("[INT2:%d]", val);
1110 case MONO_TYPE_U2: {
1111 int val = va_arg (ap, int);
1112 printf ("[UINT2:%d]", val);
1115 case MONO_TYPE_I4: {
1116 int val = va_arg (ap, int);
1117 printf ("[INT4:%d]", val);
1120 case MONO_TYPE_U4: {
1121 int val = va_arg (ap, int);
1122 printf ("[UINT4:%d]", val);
1126 gint64 val = va_arg (ap, gint64);
1127 printf ("[INT:%ld]", val);
1132 gint64 val = va_arg (ap, gint64);
1133 printf ("[UINT:%lu]", val);
1137 case MONO_TYPE_STRING: {
1138 MonoString *s = va_arg (ap, MonoString *);
1141 g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1142 decodeParmString (s);
1144 printf ("[STRING:null], ");
1147 case MONO_TYPE_CLASS:
1148 case MONO_TYPE_OBJECT: {
1149 MonoObject *o = va_arg (ap, MonoObject *);
1151 if ((o) && (o->vtable)) {
1152 if (o->vtable->klass == mono_defaults.boolean_class) {
1153 printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1154 } else if (o->vtable->klass == mono_defaults.int32_class) {
1155 printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1156 } else if (o->vtable->klass == mono_defaults.int64_class) {
1157 printf ("[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1159 printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1161 printf ("[OBJECT:%p]", o);
1166 case MONO_TYPE_FNPTR:
1167 case MONO_TYPE_ARRAY:
1168 case MONO_TYPE_SZARRAY: {
1169 gpointer p = va_arg (ap, gpointer);
1170 printf ("[result=%p]", p);
1173 case MONO_TYPE_I8: {
1174 gint64 l = va_arg (ap, gint64);
1175 printf ("[LONG:%ld]", l);
1178 case MONO_TYPE_U8: {
1179 guint64 l = va_arg (ap, guint64);
1180 printf ("[ULONG:%lu]", l);
1183 case MONO_TYPE_R4: {
1184 double f = va_arg (ap, double);
1185 printf ("[FLOAT4:%g]\n", f);
1188 case MONO_TYPE_R8: {
1189 double f = va_arg (ap, double);
1190 printf ("[FLOAT8:%g]\n", f);
1193 case MONO_TYPE_VALUETYPE: {
1194 MonoMarshalType *info;
1195 if (type->data.klass->enumtype) {
1196 type = mono_class_enum_basetype (type->data.klass);
1201 info = mono_marshal_load_type_info (type->data.klass);
1203 if ((info->native_size == sizeof(float)) &&
1204 (info->num_fields == 1) &&
1205 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1206 double f = va_arg (ap, double);
1207 printf("[FLOAT4:%g]\n", (double) f);
1211 if ((info->native_size == sizeof(double)) &&
1212 (info->num_fields == 1) &&
1213 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1214 double f = va_arg (ap, double);
1215 printf("[FLOAT8:%g]\n", f);
1219 size = mono_type_size (type, &align);
1222 guint32 p = va_arg (ap, guint32);
1223 printf ("[%02x]\n",p);
1227 guint32 p = va_arg (ap, guint32);
1228 printf ("[%04x]\n",p);
1232 guint32 p = va_arg (ap, guint32);
1233 printf ("[%08x]\n",p);
1237 guint64 p = va_arg (ap, guint64);
1238 printf ("[%016lx]\n",p);
1242 gpointer p = va_arg (ap, gpointer);
1243 printf ("[VALUETYPE] %p\n",p);
1249 case MONO_TYPE_TYPEDBYREF: {
1250 guint8 *p = va_arg (ap, gpointer);
1252 size = mono_type_size (type, &align);
1259 for (j = 0; p && j < size; j++)
1260 printf ("%02x,", p [j]);
1264 printf ("[TYPEDBYREF]\n");
1268 case MONO_TYPE_GENERICINST: {
1269 printf("[GENERICINST]\n");
1272 case MONO_TYPE_MVAR: {
1276 case MONO_TYPE_CMOD_REQD: {
1277 printf("[CMOD_REQD]\n");
1280 case MONO_TYPE_CMOD_OPT: {
1281 printf("[CMOD_OPT]\n");
1284 case MONO_TYPE_INTERNAL: {
1285 printf("[INTERNAL]\n");
1289 printf ("(unknown return type %x)",
1290 mono_method_signature (method)->ret->type);
1293 ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1294 printf (" ip: %p\n", (gpointer) ip);
1297 /*========================= End of Function ========================*/
1299 /*------------------------------------------------------------------*/
1301 /* Name - mono_arch_cpu_init */
1303 /* Function - Perform CPU specific initialization to execute */
1306 /*------------------------------------------------------------------*/
1309 mono_arch_cpu_init (void)
1313 /*========================= End of Function ========================*/
1315 /*------------------------------------------------------------------*/
1317 /* Name - mono_arch_init. */
1319 /* Function - Initialize architecture specific code. */
1321 /*------------------------------------------------------------------*/
1324 mono_arch_init (void)
1328 mono_set_partial_sharing_supported (FALSE);
1329 mono_os_mutex_init_recursive (&mini_arch_mutex);
1331 ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1332 bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ);
1333 mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1335 code = (guint8 *) &breakpointCode;
1336 s390_basr(code, s390_r13, 0);
1338 s390_llong(code, 0);
1339 s390_lg(code, s390_r13, 0, s390_r13, 4);
1340 s390_lg(code, s390_r0, 0, s390_r13, 0);
1343 /*========================= End of Function ========================*/
1345 /*------------------------------------------------------------------*/
1347 /* Name - mono_arch_cleanup. */
1349 /* Function - Cleanup architecture specific code . */
1351 /*------------------------------------------------------------------*/
1354 mono_arch_cleanup (void)
1356 if (ss_trigger_page)
1357 mono_vfree (ss_trigger_page, mono_pagesize ());
1358 if (bp_trigger_page)
1359 mono_vfree (bp_trigger_page, mono_pagesize ());
1360 mono_os_mutex_destroy (&mini_arch_mutex);
1363 /*========================= End of Function ========================*/
1365 /*------------------------------------------------------------------*/
1367 /* Name - mono_arch_cpu_optimizations */
1369 /* Function - Returns the optimizations supported on this CPU */
1371 /*------------------------------------------------------------------*/
1374 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1378 /*----------------------------------------------------------*/
1379 /* No s390-specific optimizations yet */
1380 /*----------------------------------------------------------*/
1381 *exclude_mask = MONO_OPT_LINEARS;
1385 /*========================= End of Function ========================*/
1387 /*------------------------------------------------------------------*/
1389 /* Name - mono_arch_get_allocatable_int_vars */
1393 /*------------------------------------------------------------------*/
1396 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1401 for (i = 0; i < cfg->num_varinfo; i++) {
1402 MonoInst *ins = cfg->varinfo [i];
1403 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1406 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1409 if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1410 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1413 /* we can only allocate 32 bit values */
1414 if (mono_is_regsize_var(ins->inst_vtype)) {
1415 g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1416 g_assert (i == vmv->idx);
1417 vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1424 /*========================= End of Function ========================*/
1426 /*------------------------------------------------------------------*/
1428 /* Name - mono_arch_global_int_regs */
1430 /* Function - Return a list of usable integer registers. */
1432 /*------------------------------------------------------------------*/
1435 mono_arch_get_global_int_regs (MonoCompile *cfg)
1438 MonoMethodHeader *header;
1441 header = cfg->header;
1442 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1443 cfg->frame_reg = s390_r11;
1446 /* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1448 for (i = 8; i < top; ++i) {
1449 if (cfg->frame_reg != i)
1450 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1456 /*========================= End of Function ========================*/
1458 /*------------------------------------------------------------------*/
1460 /* Name - mono_arch_flush_icache */
1462 /* Function - Flush the CPU icache. */
1464 /*------------------------------------------------------------------*/
1467 mono_arch_flush_icache (guint8 *code, gint size)
1471 /*========================= End of Function ========================*/
1473 /*------------------------------------------------------------------*/
1475 /* Name - add_general */
1477 /* Function - Determine code and stack size incremements for a */
1480 /*------------------------------------------------------------------*/
1483 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1485 if (*gr > S390_LAST_ARG_REG) {
1486 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1487 ainfo->offset = sz->stack_size;
1488 ainfo->reg = STK_BASE;
1489 ainfo->regtype = RegTypeBase;
1490 sz->stack_size += sizeof(long);
1491 sz->local_size += sizeof(long);
1492 sz->offStruct += sizeof(long);
1493 sz->code_size += 12;
1501 /*========================= End of Function ========================*/
1503 /*------------------------------------------------------------------*/
1505 /* Name - add_stackParm */
1507 /* Function - Determine code and stack size incremements for a */
1510 /*------------------------------------------------------------------*/
1513 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1515 if (*gr > S390_LAST_ARG_REG) {
1516 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1517 ainfo->reg = STK_BASE;
1518 ainfo->offset = sz->stack_size;
1519 ainfo->regtype = RegTypeStructByAddrOnStack;
1520 sz->stack_size += sizeof (gpointer);
1521 sz->parm_size += sizeof(gpointer);
1522 sz->offStruct += sizeof(gpointer);
1525 ainfo->offset = sz->stack_size;
1526 ainfo->regtype = RegTypeStructByAddr;
1529 ainfo->offparm = sz->offset;
1530 sz->offset = S390_ALIGN(sz->offset+size, sizeof(long));
1532 ainfo->vtsize = size;
1533 sz->parm_size += size;
1536 /*========================= End of Function ========================*/
1538 /*------------------------------------------------------------------*/
1540 /* Name - add_float */
1542 /* Function - Determine code and stack size incremements for a */
1543 /* float parameter. */
1545 /*------------------------------------------------------------------*/
1548 add_float (guint *fr, size_data *sz, ArgInfo *ainfo)
1550 if ((*fr) <= S390_LAST_FPARG_REG) {
1551 ainfo->regtype = RegTypeFP;
1557 ainfo->offset = sz->stack_size;
1558 ainfo->reg = STK_BASE;
1559 ainfo->regtype = RegTypeBase;
1561 sz->stack_size += sizeof(double);
1562 sz->local_size += sizeof(double);
1563 sz->offStruct += sizeof(double);
1567 /*========================= End of Function ========================*/
1569 /*------------------------------------------------------------------*/
1571 /* Name - get_call_info */
1573 /* Function - Determine the amount of space required for code */
1574 /* and stack. In addition determine starting points */
1575 /* for stack-based parameters, and area for struct- */
1576 /* ures being returned on the stack. */
1578 /*------------------------------------------------------------------*/
1581 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1583 guint i, fr, gr, size, pstart;
1584 int nParm = sig->hasthis + sig->param_count;
1586 guint32 simpleType, align;
1587 gboolean is_pinvoke = sig->pinvoke;
1592 cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1594 cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1599 cinfo->struct_ret = 0;
1603 sz->offStruct = S390_MINIMAL_STACK_SIZE;
1604 sz->stack_size = S390_MINIMAL_STACK_SIZE;
1611 /*----------------------------------------------------------*/
1612 /* We determine the size of the return code/stack in case we*/
1613 /* need to reserve a register to be used to address a stack */
1614 /* area that the callee will use. */
1615 /*----------------------------------------------------------*/
1617 ret_type = mini_get_underlying_type (sig->ret);
1618 simpleType = ret_type->type;
1620 switch (simpleType) {
1621 case MONO_TYPE_BOOLEAN:
1626 case MONO_TYPE_CHAR:
1631 case MONO_TYPE_CLASS:
1632 case MONO_TYPE_OBJECT:
1633 case MONO_TYPE_SZARRAY:
1634 case MONO_TYPE_ARRAY:
1636 case MONO_TYPE_FNPTR:
1637 case MONO_TYPE_STRING:
1638 cinfo->ret.reg = s390_r2;
1643 cinfo->ret.reg = s390_f0;
1648 cinfo->ret.reg = s390_r2;
1651 case MONO_TYPE_GENERICINST:
1652 if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1653 cinfo->ret.reg = s390_r2;
1658 case MONO_TYPE_VALUETYPE: {
1659 MonoClass *klass = mono_class_from_mono_type (sig->ret);
1660 if (klass->enumtype) {
1661 simpleType = mono_class_enum_basetype (klass)->type;
1664 size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1666 cinfo->struct_ret = 1;
1667 cinfo->ret.size = size;
1668 cinfo->ret.vtsize = size;
1671 case MONO_TYPE_TYPEDBYREF:
1672 size = sizeof (MonoTypedRef);
1673 cinfo->struct_ret = 1;
1674 cinfo->ret.size = size;
1675 cinfo->ret.vtsize = size;
1677 case MONO_TYPE_VOID:
1680 g_error ("Can't handle as return value 0x%x", sig->ret->type);
1686 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1687 * the first argument, allowing 'this' to be always passed in the first arg reg.
1688 * Also do this if the first argument is a reference type, since virtual calls
1689 * are sometimes made using calli without sig->hasthis set, like in the delegate
1692 if (cinfo->struct_ret && !is_pinvoke &&
1694 (sig->param_count > 0 &&
1695 MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1697 cinfo->args[nParm].size = sizeof (gpointer);
1698 add_general (&gr, sz, cinfo->args + nParm);
1700 cinfo->args[nParm].size = sizeof (gpointer);
1701 add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1705 cinfo->vret_arg_index = 1;
1706 cinfo->ret.reg = gr;
1711 cinfo->args[nParm].size = sizeof (gpointer);
1712 add_general (&gr, sz, cinfo->args + nParm);
1716 if (cinfo->struct_ret) {
1717 cinfo->ret.reg = gr;
1722 if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1723 gr = S390_LAST_ARG_REG + 1;
1724 fr = S390_LAST_FPARG_REG + 1;
1726 /* Emit the signature cookie just before the implicit arguments */
1727 add_general (&gr, sz, &cinfo->sigCookie);
1730 /*----------------------------------------------------------*/
1731 /* We determine the size of the parameter code and stack */
1732 /* requirements by checking the types and sizes of the */
1734 /*----------------------------------------------------------*/
1736 for (i = pstart; i < sig->param_count; ++i) {
1739 /*--------------------------------------------------*/
1740 /* Handle vararg type calls. All args are put on */
1742 /*--------------------------------------------------*/
1743 if ((sig->call_convention == MONO_CALL_VARARG) &&
1744 (i == sig->sentinelpos)) {
1745 gr = S390_LAST_ARG_REG + 1;
1746 fr = S390_LAST_FPARG_REG + 1;
1747 add_general (&gr, sz, &cinfo->sigCookie);
1750 if (sig->params [i]->byref) {
1751 add_general (&gr, sz, cinfo->args+nParm);
1752 cinfo->args[nParm].size = sizeof(gpointer);
1757 ptype = mini_get_underlying_type (sig->params [i]);
1758 simpleType = ptype->type;
1759 cinfo->args[nParm].type = simpleType;
1760 switch (simpleType) {
1761 case MONO_TYPE_BOOLEAN:
1764 cinfo->args[nParm].size = sizeof(char);
1765 add_general (&gr, sz, cinfo->args+nParm);
1770 case MONO_TYPE_CHAR:
1771 cinfo->args[nParm].size = sizeof(short);
1772 add_general (&gr, sz, cinfo->args+nParm);
1777 cinfo->args[nParm].size = sizeof(int);
1778 add_general (&gr, sz, cinfo->args+nParm);
1784 case MONO_TYPE_FNPTR:
1785 case MONO_TYPE_CLASS:
1786 case MONO_TYPE_OBJECT:
1787 case MONO_TYPE_STRING:
1788 case MONO_TYPE_SZARRAY:
1789 case MONO_TYPE_ARRAY:
1790 cinfo->args[nParm].size = sizeof(gpointer);
1791 add_general (&gr, sz, cinfo->args+nParm);
1796 cinfo->args[nParm].size = sizeof(long long);
1797 add_general (&gr, sz, cinfo->args+nParm);
1801 cinfo->args[nParm].size = sizeof(float);
1802 add_float (&fr, sz, cinfo->args+nParm);
1806 cinfo->args[nParm].size = sizeof(double);
1807 add_float (&fr, sz, cinfo->args+nParm);
1810 case MONO_TYPE_GENERICINST:
1811 if (!mono_type_generic_inst_is_valuetype (ptype)) {
1812 cinfo->args[nParm].size = sizeof(gpointer);
1813 add_general (&gr, sz, cinfo->args+nParm);
1818 case MONO_TYPE_VALUETYPE: {
1819 MonoMarshalType *info;
1820 MonoClass *klass = mono_class_from_mono_type (ptype);
1823 size = mono_class_native_size(klass, NULL);
1825 size = mono_class_value_size(klass, NULL);
1827 if (simpleType != MONO_TYPE_GENERICINST) {
1828 info = mono_marshal_load_type_info(klass);
1830 if ((info->native_size == sizeof(float)) &&
1831 (info->num_fields == 1) &&
1832 (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1833 cinfo->args[nParm].size = sizeof(float);
1834 add_float(&fr, sz, cinfo->args+nParm);
1839 if ((info->native_size == sizeof(double)) &&
1840 (info->num_fields == 1) &&
1841 (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1842 cinfo->args[nParm].size = sizeof(double);
1843 add_float(&fr, sz, cinfo->args+nParm);
1849 cinfo->args[nParm].vtsize = 0;
1850 cinfo->args[nParm].size = 0;
1853 /*----------------------------------*/
1854 /* On S/390, structures of size 1, */
1855 /* 2, 4, and 8 bytes are passed in */
1856 /* (a) register(s). */
1857 /*----------------------------------*/
1863 add_general(&gr, sz, cinfo->args+nParm);
1864 cinfo->args[nParm].size = size;
1865 cinfo->args[nParm].regtype = RegTypeStructByVal;
1867 sz->local_size += sizeof(long);
1870 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1875 case MONO_TYPE_TYPEDBYREF: {
1876 int size = sizeof (MonoTypedRef);
1878 cinfo->args[nParm].vtsize = 0;
1879 cinfo->args[nParm].size = 0;
1882 /*----------------------------------*/
1883 /* On S/390, structures of size 1, */
1884 /* 2, 4, and 8 bytes are passed in */
1885 /* (a) register(s). */
1886 /*----------------------------------*/
1892 add_general(&gr, sz, cinfo->args+nParm);
1893 cinfo->args[nParm].size = size;
1894 cinfo->args[nParm].regtype = RegTypeStructByVal;
1896 sz->local_size += sizeof(long);
1899 add_stackParm(&gr, sz, cinfo->args+nParm, size);
1905 g_error ("Can't trampoline 0x%x", ptype);
1909 /*----------------------------------------------------------*/
1910 /* Handle the case where there are no implicit arguments */
1911 /*----------------------------------------------------------*/
1912 if ((sig->call_convention == MONO_CALL_VARARG) &&
1915 (sig->param_count == sig->sentinelpos)) {
1916 gr = S390_LAST_ARG_REG + 1;
1917 fr = S390_LAST_FPARG_REG + 1;
1918 add_general (&gr, sz, &cinfo->sigCookie);
1921 /*----------------------------------------------------------*/
1922 /* If we are passing a structure back then if it won't be */
1923 /* in a register(s) then we make room at the end of the */
1924 /* parameters that may have been placed on the stack */
1925 /*----------------------------------------------------------*/
1926 if (cinfo->struct_ret) {
1927 cinfo->ret.offset = sz->stack_size;
1928 switch (cinfo->ret.size) {
1936 sz->stack_size += S390_ALIGN(cinfo->ret.size, align);
1941 sz->stack_size = sz->stack_size + sz->local_size + sz->parm_size +
1943 sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long));
1948 /*========================= End of Function ========================*/
1950 /*------------------------------------------------------------------*/
1952 /* Name - mono_arch_allocate_vars */
1954 /* Function - Set var information according to the calling */
1955 /* convention for S/390. The local var stuff should */
1956 /* most likely be split in another method. */
1958 /* Parameter - @m - Compile unit. */
1960 /*------------------------------------------------------------------*/
1963 mono_arch_allocate_vars (MonoCompile *cfg)
1965 MonoMethodSignature *sig;
1966 MonoMethodHeader *header;
1969 int iParm, iVar, offset, align, size, curinst;
1970 int frame_reg = STK_BASE;
1973 header = cfg->header;
1975 cfg->flags |= MONO_CFG_HAS_SPILLUP;
1977 /*---------------------------------------------------------*/
1978 /* We use the frame register also for any method that has */
1979 /* filter clauses. This way, when the handlers are called, */
1980 /* the code will reference local variables using the frame */
1981 /* reg instead of the stack pointer: if we had to restore */
1982 /* the stack pointer, we'd corrupt the method frames that */
1983 /* are already on the stack (since filters get called */
1984 /* before stack unwinding happens) when the filter code */
1985 /* would call any method. */
1986 /*---------------------------------------------------------*/
1987 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1988 frame_reg = s390_r11;
1990 cfg->frame_reg = frame_reg;
1992 cfg->arch.bkchain_reg = -1;
1994 if (frame_reg != STK_BASE)
1995 cfg->used_int_regs |= (1 << frame_reg);
1997 if (cfg->uses_rgctx_reg)
1998 cfg->used_int_regs |= (1 << MONO_ARCH_IMT_REG);
2000 sig = mono_method_signature (cfg->method);
2002 cinfo = get_call_info (cfg, cfg->mempool, sig);
2004 if (!cinfo->struct_ret) {
2005 switch (mini_get_underlying_type (sig->ret)->type) {
2006 case MONO_TYPE_VOID:
2009 cfg->ret->opcode = OP_REGVAR;
2010 cfg->ret->dreg = s390_r2;
2015 /*--------------------------------------------------------------*/
2016 /* local vars are at a positive offset from the stack pointer */
2017 /* also note that if the function uses alloca, we use s390_r11 */
2018 /* to point at the local variables. */
2019 /* add parameter area size for called functions */
2020 /*--------------------------------------------------------------*/
2021 if (cfg->param_area == 0)
2022 offset = S390_MINIMAL_STACK_SIZE;
2024 offset = cfg->param_area;
2026 cfg->sig_cookie = 0;
2028 if (cinfo->struct_ret) {
2029 inst = cfg->vret_addr;
2030 offset = S390_ALIGN(offset, sizeof(gpointer));
2031 inst->inst_offset = offset;
2032 inst->opcode = OP_REGOFFSET;
2033 inst->inst_basereg = frame_reg;
2034 offset += sizeof(gpointer);
2035 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2036 printf ("vret_addr =");
2037 mono_print_ins (cfg->vret_addr);
2042 inst = cfg->args [0];
2043 if (inst->opcode != OP_REGVAR) {
2044 inst->opcode = OP_REGOFFSET;
2045 inst->inst_basereg = frame_reg;
2046 offset = S390_ALIGN(offset, sizeof(gpointer));
2047 inst->inst_offset = offset;
2048 offset += sizeof (gpointer);
2055 eArg = sig->param_count + sArg;
2057 if (sig->call_convention == MONO_CALL_VARARG)
2058 cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2060 for (iParm = sArg; iParm < eArg; ++iParm) {
2061 inst = cfg->args [curinst];
2062 if (inst->opcode != OP_REGVAR) {
2063 switch (cinfo->args[iParm].regtype) {
2064 case RegTypeStructByAddr : {
2067 size = sizeof (gpointer);
2069 inst->opcode = OP_REGOFFSET;
2070 inst->inst_basereg = frame_reg;
2071 offset = S390_ALIGN (offset, sizeof (gpointer));
2072 inst->inst_offset = offset;
2074 /* Add a level of indirection */
2075 MONO_INST_NEW (cfg, indir, 0);
2077 inst->opcode = OP_VTARG_ADDR;
2078 inst->inst_left = indir;
2081 case RegTypeStructByAddrOnStack : {
2084 size = sizeof (gpointer);
2086 /* Similar to the == STK_BASE case below */
2087 cfg->arch.bkchain_reg = s390_r12;
2088 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2090 inst->opcode = OP_REGOFFSET;
2091 inst->dreg = mono_alloc_preg (cfg);
2092 inst->inst_basereg = cfg->arch.bkchain_reg;
2093 inst->inst_offset = cinfo->args [iParm].offset;
2095 /* Add a level of indirection */
2096 MONO_INST_NEW (cfg, indir, 0);
2098 inst->opcode = OP_VTARG_ADDR;
2099 inst->inst_left = indir;
2102 case RegTypeStructByVal :
2103 size = cinfo->args[iParm].size;
2104 offset = S390_ALIGN(offset, size);
2105 inst->opcode = OP_REGOFFSET;
2106 inst->inst_basereg = frame_reg;
2107 inst->inst_offset = offset;
2110 if (cinfo->args [iParm].reg == STK_BASE) {
2112 * These arguments are in the previous frame, so we can't
2113 * compute their offset from the current frame pointer right
2114 * now, since cfg->stack_offset is not yet known, so dedicate a
2115 * register holding the previous frame pointer.
2117 cfg->arch.bkchain_reg = s390_r12;
2118 cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2120 inst->opcode = OP_REGOFFSET;
2121 inst->inst_basereg = cfg->arch.bkchain_reg;
2122 size = (cinfo->args[iParm].size < 8
2123 ? 8 - cinfo->args[iParm].size
2125 inst->inst_offset = cinfo->args [iParm].offset + size;
2126 size = sizeof (long);
2128 inst->opcode = OP_REGOFFSET;
2129 inst->inst_basereg = frame_reg;
2130 size = (cinfo->args[iParm].size < 8
2133 offset = S390_ALIGN(offset, size);
2134 if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2135 inst->inst_offset = offset;
2137 inst->inst_offset = offset + (8 - size);
2142 if ((sig->call_convention == MONO_CALL_VARARG) &&
2143 (cinfo->args[iParm].regtype != RegTypeGeneral) &&
2144 (iParm < sig->sentinelpos))
2145 cfg->sig_cookie += size;
2146 printf("%s %4d cookine %x\n",__FUNCTION__,__LINE__,cfg->sig_cookie);
2149 offset += MAX(size, 8);
2154 cfg->locals_min_stack_offset = offset;
2156 curinst = cfg->locals_start;
2157 for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2158 inst = cfg->varinfo [iVar];
2159 if ((inst->flags & MONO_INST_IS_DEAD) ||
2160 (inst->opcode == OP_REGVAR))
2163 /*--------------------------------------------------*/
2164 /* inst->backend.is_pinvoke indicates native sized */
2165 /* value typs this is used by the pinvoke wrappers */
2166 /* when they call functions returning structure */
2167 /*--------------------------------------------------*/
2168 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2169 size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2170 (guint32 *) &align);
2172 size = mono_type_size (inst->inst_vtype, &align);
2174 offset = S390_ALIGN(offset, align);
2175 inst->inst_offset = offset;
2176 inst->opcode = OP_REGOFFSET;
2177 inst->inst_basereg = frame_reg;
2179 DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2180 iVar, inst->inst_offset, size));
2183 cfg->locals_max_stack_offset = offset;
2185 /*------------------------------------------------------*/
2186 /* Allow space for the trace method stack area if needed*/
2187 /*------------------------------------------------------*/
2188 if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method))
2189 || (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE))
2190 offset += S390_TRACE_STACK_SIZE;
2192 /*------------------------------------------------------*/
2193 /* Reserve space to save LMF and caller saved registers */
2194 /*------------------------------------------------------*/
2195 if (cfg->method->save_lmf)
2196 offset += sizeof (MonoLMF);
2198 /*------------------------------------------------------*/
2199 /* align the offset */
2200 /*------------------------------------------------------*/
2201 cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2203 /*------------------------------------------------------*/
2204 /* Fix offsets for args whose value is in parent frame */
2205 /*------------------------------------------------------*/
2206 for (iParm = sArg; iParm < eArg; ++iParm) {
2207 inst = cfg->args [iParm];
2209 if (inst->opcode == OP_S390_STKARG) {
2210 inst->opcode = OP_REGOFFSET;
2211 inst->inst_offset += cfg->stack_offset;
2216 /*========================= End of Function ========================*/
2218 /*------------------------------------------------------------------*/
2220 /* Name - mono_arch_create_vars */
2222 /*------------------------------------------------------------------*/
2225 mono_arch_create_vars (MonoCompile *cfg)
2227 MonoMethodSignature *sig;
2230 sig = mono_method_signature (cfg->method);
2232 cinfo = get_call_info (cfg, cfg->mempool, sig);
2234 if (cinfo->struct_ret) {
2235 cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2236 if (G_UNLIKELY (cfg->verbose_level > 1)) {
2237 printf ("vret_addr = ");
2238 mono_print_ins (cfg->vret_addr);
2243 /*========================= End of Function ========================*/
2245 /*------------------------------------------------------------------*/
2247 /* Name - add_outarg_reg2. */
2249 /*------------------------------------------------------------------*/
2252 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2257 case RegTypeGeneral:
2258 MONO_INST_NEW (cfg, ins, OP_MOVE);
2259 ins->dreg = mono_alloc_ireg (cfg);
2260 ins->sreg1 = tree->dreg;
2261 MONO_ADD_INS (cfg->cbb, ins);
2262 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2265 MONO_INST_NEW (cfg, ins, OP_FMOVE);
2266 ins->dreg = mono_alloc_freg (cfg);
2267 ins->sreg1 = tree->dreg;
2268 MONO_ADD_INS (cfg->cbb, ins);
2269 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2272 MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2273 ins->dreg = mono_alloc_freg (cfg);
2274 ins->sreg1 = tree->dreg;
2275 MONO_ADD_INS (cfg->cbb, ins);
2276 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2279 g_assert_not_reached ();
2283 /*========================= End of Function ========================*/
2285 /*------------------------------------------------------------------*/
2287 /* Name - emit_sig_cookie. */
2289 /*------------------------------------------------------------------*/
2292 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2294 MonoMethodSignature *tmpSig;
2297 cfg->disable_aot = TRUE;
2299 /*----------------------------------------------------------*/
2300 /* mono_ArgIterator_Setup assumes the signature cookie is */
2301 /* passed first and all the arguments which were before it */
2302 /* passed on the stack after the signature. So compensate */
2303 /* by passing a different signature. */
2304 /*----------------------------------------------------------*/
2305 tmpSig = mono_metadata_signature_dup (call->signature);
2306 tmpSig->param_count -= call->signature->sentinelpos;
2307 tmpSig->sentinelpos = 0;
2308 if (tmpSig->param_count > 0)
2309 memcpy (tmpSig->params,
2310 call->signature->params + call->signature->sentinelpos,
2311 tmpSig->param_count * sizeof(MonoType *));
2313 MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2314 sig_arg->dreg = mono_alloc_ireg (cfg);
2315 sig_arg->inst_p0 = tmpSig;
2316 MONO_ADD_INS (cfg->cbb, sig_arg);
2318 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2319 cinfo->sigCookie.offset, sig_arg->dreg);
2322 /*========================= End of Function ========================*/
2324 /*------------------------------------------------------------------*/
2326 /* Name - mono_arch_emit_call */
2328 /*------------------------------------------------------------------*/
2331 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2334 MonoMethodSignature *sig;
2336 int i, n, lParamArea;
2338 ArgInfo *ainfo = NULL;
2340 MonoMethodHeader *header;
2343 sig = call->signature;
2344 n = sig->param_count + sig->hasthis;
2345 DEBUG (g_print ("Call requires: %d parameters\n",n));
2347 cinfo = get_call_info (cfg, cfg->mempool, sig);
2349 stackSize = cinfo->sz.stack_size + cinfo->sz.local_size +
2350 cinfo->sz.parm_size + cinfo->sz.offset;
2351 call->stack_usage = MAX(stackSize, call->stack_usage);
2352 lParamArea = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2353 cfg->param_area = MAX(((signed) cfg->param_area), lParamArea);
2354 cfg->flags |= MONO_CFG_HAS_CALLS;
2356 if (cinfo->struct_ret) {
2357 MONO_INST_NEW (cfg, ins, OP_MOVE);
2358 ins->sreg1 = call->vret_var->dreg;
2359 ins->dreg = mono_alloc_preg (cfg);
2360 MONO_ADD_INS (cfg->cbb, ins);
2361 mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2364 header = cfg->header;
2365 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2370 for (i = 0; i < n; ++i) {
2373 ainfo = cinfo->args + i;
2374 if (i >= sig->hasthis)
2375 t = sig->params [i - sig->hasthis];
2377 t = &mono_defaults.int_class->byval_arg;
2378 t = mini_get_underlying_type (t);
2380 in = call->args [i];
2382 if ((sig->call_convention == MONO_CALL_VARARG) &&
2384 (i == sig->sentinelpos)) {
2385 emit_sig_cookie (cfg, call, cinfo);
2388 switch (ainfo->regtype) {
2389 case RegTypeGeneral:
2390 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2393 if (MONO_TYPE_ISSTRUCT (t)) {
2394 /* Valuetype passed in one fp register */
2395 ainfo->regtype = RegTypeStructByValInFP;
2398 if (ainfo->size == 4)
2399 ainfo->regtype = RegTypeFPR4;
2400 add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2403 case RegTypeStructByVal:
2404 case RegTypeStructByAddr:
2405 case RegTypeStructByAddrOnStack: {
2409 if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2410 size = sizeof (MonoTypedRef);
2411 align = sizeof (gpointer);
2415 size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2418 * Other backends use mono_type_stack_size (), but that
2419 * aligns the size to 8, which is larger than the size of
2420 * the source, leading to reads of invalid memory if the
2421 * source is at the end of address space.
2423 size = mono_class_value_size (in->klass, &align);
2426 g_assert (in->klass);
2428 ainfo->offparm += cinfo->sz.offStruct;
2430 MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2431 ins->sreg1 = in->dreg;
2432 ins->klass = in->klass;
2433 ins->backend.size = ainfo->size;
2434 ins->inst_p0 = call;
2435 ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2436 memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2438 MONO_ADD_INS (cfg->cbb, ins);
2440 if (ainfo->regtype == RegTypeStructByAddr) {
2442 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2443 * use the normal OUTARG opcodes to pass the address of the location to
2446 int treg = mono_alloc_preg (cfg);
2447 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2448 frmReg, ainfo->offparm);
2449 mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2450 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2451 /* The address of the valuetype is passed on the stack */
2452 int treg = mono_alloc_preg (cfg);
2453 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2454 frmReg, ainfo->offparm);
2455 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2456 ainfo->reg, ainfo->offset, treg);
2458 if (cfg->compute_gc_maps) {
2461 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2467 if (!t->byref && t->type == MONO_TYPE_R4) {
2468 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2469 STK_BASE, ainfo->offset + 4,
2471 } else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2472 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2473 STK_BASE, ainfo->offset,
2476 MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2477 ins->inst_destbasereg = STK_BASE;
2478 ins->inst_offset = ainfo->offset;
2479 ins->sreg1 = in->dreg;
2482 /* This is needed by MonoTypedRef->value to point to the correct data */
2483 if ((sig->call_convention == MONO_CALL_VARARG) &&
2484 (i >= sig->sentinelpos)) {
2485 switch (ainfo->size) {
2487 ins->opcode = OP_STOREI1_MEMBASE_REG;
2490 ins->opcode = OP_STOREI2_MEMBASE_REG;
2493 ins->opcode = OP_STOREI4_MEMBASE_REG;
2501 MONO_ADD_INS (cfg->cbb, ins);
2505 g_assert_not_reached ();
2511 * Handle the case where there are no implicit arguments
2513 if ((sig->call_convention == MONO_CALL_VARARG) &&
2515 (i == sig->sentinelpos)) {
2516 emit_sig_cookie (cfg, call, cinfo);
2520 /*========================= End of Function ========================*/
2522 /*------------------------------------------------------------------*/
2524 /* Name - mono_arch_emit_outarg_vt */
2526 /*------------------------------------------------------------------*/
2529 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2531 MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2532 ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2533 int size = ins->backend.size;
2535 if (ainfo->regtype == RegTypeStructByVal) {
2537 arg->ins.sreg1 = ainfo->reg;
2538 arg->ins.opcode = OP_OUTARG_VT;
2539 arg->size = ainfo->size;
2540 arg->offset = ainfo->offset;
2541 arg->offPrm = ainfo->offparm + cinfo->sz.offStruct;
2543 if (ainfo->reg != STK_BASE) {
2544 MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2546 MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2549 } else if (ainfo->regtype == RegTypeStructByValInFP) {
2550 int dreg = mono_alloc_freg (cfg);
2552 if (ainfo->size == 4) {
2553 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2554 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2556 g_assert (ainfo->size == 8);
2558 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2561 mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2564 MonoMethodHeader *header;
2567 header = mono_method_get_header_checked (cfg->method, &error);
2568 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2569 if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2574 MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2575 src->dreg, 0, size);
2577 if (cfg->compute_gc_maps) {
2580 EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2585 /*========================= End of Function ========================*/
2587 /*------------------------------------------------------------------*/
2589 /* Name - mono_arch_emit_setret */
2591 /*------------------------------------------------------------------*/
2594 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2596 MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2599 if (ret->type == MONO_TYPE_R4) {
2600 MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2602 } else if (ret->type == MONO_TYPE_R8) {
2603 MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2608 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2611 /*========================= End of Function ========================*/
2613 /*------------------------------------------------------------------*/
2615 /* Name - mono_arch_instrument_mem_needs */
2617 /* Function - Allow tracing to work with this interface (with */
2618 /* an optional argument). */
2620 /*------------------------------------------------------------------*/
2623 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2625 /* no stack room needed now (may be needed for FASTCALL-trace support) */
2627 /* split prolog-epilog requirements? */
2628 *code = 50; /* max bytes needed: check this number */
2631 /*========================= End of Function ========================*/
2633 /*------------------------------------------------------------------*/
2635 /* Name - mono_arch_instrument_prolog */
2637 /* Function - Create an "instrumented" prolog. */
2639 /*------------------------------------------------------------------*/
2642 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2643 gboolean enable_arguments)
2650 parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2651 if (cfg->method->save_lmf)
2652 parmOffset -= sizeof(MonoLMF);
2653 fpOffset = parmOffset + (5*sizeof(gpointer));
2656 s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2657 s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2658 s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2659 s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2660 s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2661 S390_SET (code, s390_r1, func);
2662 S390_SET (code, s390_r2, cfg->method);
2663 s390_lay (code, s390_r3, 0, STK_BASE, parmOffset);
2664 s390_lgr (code, s390_r4, STK_BASE);
2665 s390_aghi (code, s390_r4, cfg->stack_usage);
2666 s390_basr (code, s390_r14, s390_r1);
2667 s390_ldy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2668 s390_ldy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2669 s390_ldy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2670 s390_ldy (code, s390_f0, 0, STK_BASE, fpOffset);
2671 s390_lmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2676 /*========================= End of Function ========================*/
2678 /*------------------------------------------------------------------*/
2680 /* Name - mono_arch_instrument_epilog */
2682 /* Function - Create an epilog that will handle the returned */
2683 /* values used in instrumentation. */
2685 /*------------------------------------------------------------------*/
2688 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2691 int save_mode = SAVE_NONE,
2694 MonoMethod *method = cfg->method;
2695 int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2697 offset = code - cfg->native_code;
2698 /*-----------------------------------------*/
2699 /* We need about 128 bytes of instructions */
2700 /*-----------------------------------------*/
2701 if (offset > (cfg->code_size - 128)) {
2702 cfg->code_size *= 2;
2703 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2704 code = cfg->native_code + offset;
2707 saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2708 if (method->save_lmf)
2709 saveOffset -= sizeof(MonoLMF);
2713 case MONO_TYPE_VOID:
2714 /* special case string .ctor icall */
2715 if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2716 save_mode = SAVE_ONE;
2718 save_mode = SAVE_NONE;
2722 save_mode = SAVE_ONE;
2725 save_mode = SAVE_R4;
2728 save_mode = SAVE_R8;
2730 case MONO_TYPE_VALUETYPE:
2731 if (mono_method_signature (method)->ret->data.klass->enumtype) {
2732 rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2735 save_mode = SAVE_STRUCT;
2738 save_mode = SAVE_ONE;
2742 switch (save_mode) {
2744 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2745 if (enable_arguments) {
2746 s390_lgr (code, s390_r3, s390_r2);
2750 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2751 if (enable_arguments) {
2752 s390_ldebr (code, s390_f0, s390_f0);
2756 s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2759 s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2760 if (enable_arguments) {
2761 s390_lg (code, s390_r3, 0, cfg->frame_reg,
2762 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2770 S390_SET (code, s390_r1, func);
2771 S390_SET (code, s390_r2, cfg->method);
2772 s390_basr (code, s390_r14, s390_r1);
2774 switch (save_mode) {
2776 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2780 s390_ld (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2783 s390_lg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2793 /*========================= End of Function ========================*/
2795 /*------------------------------------------------------------------*/
2797 /* Name - mono_arch_peephole_pass_1 */
2799 /* Function - Form a peephole pass at the code looking for */
2800 /* simple optimizations. */
2802 /*------------------------------------------------------------------*/
2805 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2809 /*========================= End of Function ========================*/
2811 /*------------------------------------------------------------------*/
2813 /* Name - mono_arch_peephole_pass_2 */
2815 /* Function - Form a peephole pass at the code looking for */
2816 /* simple optimizations. */
2818 /*------------------------------------------------------------------*/
2821 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2825 MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2826 mono_peephole_ins (bb, ins);
2830 /*========================= End of Function ========================*/
2832 /*------------------------------------------------------------------*/
2834 /* Name - mono_arch_lowering_pass. */
2836 /*------------------------------------------------------------------*/
2839 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
2841 MonoInst *ins, *next;
2843 MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
2844 switch (ins->opcode) {
2849 case OP_IDIV_UN_IMM:
2850 case OP_IREM_UN_IMM:
2855 case OP_LOCALLOC_IMM:
2856 mono_decompose_op_imm (cfg, bb, ins);
2859 if (!s390_is_imm16 (ins->inst_imm))
2860 /* This is created by the memcpy code which ignores is_inst_imm */
2861 mono_decompose_op_imm (cfg, bb, ins);
2868 bb->max_vreg = cfg->next_vreg;
2871 /*========================= End of Function ========================*/
2873 /*------------------------------------------------------------------*/
2875 /* Name - emit_float_to_int */
2877 /* Function - Create instructions which will convert a floating */
2878 /* point value to integer. */
2880 /*------------------------------------------------------------------*/
2883 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
2885 /* sreg is a float, dreg is an integer reg. */
2887 s390_cgdbr (code, dreg, 5, sreg);
2890 s390_ltgr (code, dreg, dreg);
2892 s390_oill (code, dreg, 0x80);
2893 s390_lghi (code, s390_r0, 0xff);
2894 s390_ngr (code, dreg, s390_r0);
2897 s390_ltgr (code, dreg, dreg);
2899 s390_oill (code, dreg, 0x8000);
2900 s390_llill(code, s390_r0, 0xffff);
2901 s390_ngr (code, dreg, s390_r0);
2906 S390_SET (code, s390_r13, 0x41e0000000000000llu);
2907 s390_ldgr (code, s390_f14, s390_r13);
2908 s390_ldr (code, s390_f15, sreg);
2909 s390_cdbr (code, s390_f15, s390_f14);
2910 s390_jl (code, 0); CODEPTR (code, o[0]);
2911 S390_SET (code, s390_r13, 0x41f0000000000000llu);
2912 s390_ldgr (code, s390_f14, s390_r13);
2913 s390_sdbr (code, s390_f15, s390_f14);
2914 s390_cfdbr (code, dreg, 7, s390_f15);
2916 PTRSLOT (code, o[0]);
2917 s390_cfdbr (code, dreg, 5, sreg);
2920 s390_lghi (code, s390_r0, 0xff);
2921 s390_ngr (code, dreg, s390_r0);
2924 s390_llill(code, s390_r0, 0xffff);
2925 s390_ngr (code, dreg, s390_r0);
2932 /*========================= End of Function ========================*/
2934 /*------------------------------------------------------------------*/
2936 /* Name - gboolean_is_unsigned. */
2938 /* Function - Return TRUE if next opcode is checking for un- */
2941 /*------------------------------------------------------------------*/
2944 gboolean is_unsigned (MonoInst *next)
2947 (((next->opcode >= OP_IBNE_UN) &&
2948 (next->opcode <= OP_IBLT_UN)) ||
2949 ((next->opcode >= OP_LBNE_UN) &&
2950 (next->opcode <= OP_LBLT_UN)) ||
2951 ((next->opcode >= OP_COND_EXC_NE_UN) &&
2952 (next->opcode <= OP_COND_EXC_LT_UN)) ||
2953 ((next->opcode >= OP_COND_EXC_INE_UN) &&
2954 (next->opcode <= OP_COND_EXC_ILT_UN)) ||
2955 ((next->opcode == OP_CLT_UN) ||
2956 (next->opcode == OP_CGT_UN)) ||
2957 ((next->opcode == OP_ICLT_UN) ||
2958 (next->opcode == OP_ICGT_UN) ||
2959 (next->opcode == OP_LCLT_UN) ||
2960 (next->opcode == OP_LCGT_UN))))
2966 /*========================= End of Function ========================*/
2968 /*------------------------------------------------------------------*/
2970 /* Name - mono_arch_output_basic_block */
2972 /* Function - Perform the "real" work of emitting instructions */
2973 /* that will do the work of in the basic block. */
2975 /*------------------------------------------------------------------*/
2978 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
2983 guint8 *code = cfg->native_code + cfg->code_len;
2984 guint last_offset = 0;
2987 /* we don't align basic blocks of loops on s390 */
2989 if (cfg->verbose_level > 2)
2990 g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
2992 if ((cfg->prof_options & MONO_PROFILE_COVERAGE) && cfg->coverage_info) {
2993 MonoProfileCoverageInfo *cov = cfg->coverage_info;
2994 g_assert (!mono_compile_aot);
2995 cov->data [bb->dfn].cil_code = bb->cil_code;
2996 /* This is not thread save, but good enough */
2997 S390_SET (code, s390_r1, &cov->data [bb->dfn].count);
2998 s390_alsi (code, 0, s390_r1, 1);
3001 MONO_BB_FOR_EACH_INS (bb, ins) {
3002 offset = code - cfg->native_code;
3004 max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3006 if (offset > (cfg->code_size - max_len - 16)) {
3007 cfg->code_size *= 2;
3008 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3009 code = cfg->native_code + offset;
3012 mono_debug_record_line_number (cfg, ins, offset);
3014 switch (ins->opcode) {
3015 case OP_STOREI1_MEMBASE_IMM: {
3016 s390_lghi (code, s390_r0, ins->inst_imm);
3017 S390_LONG (code, stcy, stc, s390_r0, 0,
3018 ins->inst_destbasereg, ins->inst_offset);
3021 case OP_STOREI2_MEMBASE_IMM: {
3022 s390_lghi (code, s390_r0, ins->inst_imm);
3023 S390_LONG (code, sthy, sth, s390_r0, 0,
3024 ins->inst_destbasereg, ins->inst_offset);
3027 case OP_STOREI4_MEMBASE_IMM: {
3028 s390_lgfi (code, s390_r0, ins->inst_imm);
3029 S390_LONG (code, sty, st, s390_r0, 0,
3030 ins->inst_destbasereg, ins->inst_offset);
3033 case OP_STORE_MEMBASE_IMM:
3034 case OP_STOREI8_MEMBASE_IMM: {
3035 S390_SET (code, s390_r0, ins->inst_imm);
3036 S390_LONG (code, stg, stg, s390_r0, 0,
3037 ins->inst_destbasereg, ins->inst_offset);
3040 case OP_STOREI1_MEMBASE_REG: {
3041 S390_LONG (code, stcy, stc, ins->sreg1, 0,
3042 ins->inst_destbasereg, ins->inst_offset);
3045 case OP_STOREI2_MEMBASE_REG: {
3046 S390_LONG (code, sthy, sth, ins->sreg1, 0,
3047 ins->inst_destbasereg, ins->inst_offset);
3050 case OP_STOREI4_MEMBASE_REG: {
3051 S390_LONG (code, sty, st, ins->sreg1, 0,
3052 ins->inst_destbasereg, ins->inst_offset);
3055 case OP_STORE_MEMBASE_REG:
3056 case OP_STOREI8_MEMBASE_REG: {
3057 S390_LONG (code, stg, stg, ins->sreg1, 0,
3058 ins->inst_destbasereg, ins->inst_offset);
3062 g_assert_not_reached ();
3064 case OP_LOAD_MEMBASE:
3065 case OP_LOADI8_MEMBASE: {
3066 S390_LONG (code, lg, lg, ins->dreg, 0,
3067 ins->inst_basereg, ins->inst_offset);
3070 case OP_LOADI4_MEMBASE: {
3071 S390_LONG (code, lgf, lgf, ins->dreg, 0,
3072 ins->inst_basereg, ins->inst_offset);
3075 case OP_LOADU4_MEMBASE: {
3076 S390_LONG (code, llgf, llgf, ins->dreg, 0,
3077 ins->inst_basereg, ins->inst_offset);
3080 case OP_LOADU1_MEMBASE: {
3081 S390_LONG (code, llgc, llgc, ins->dreg, 0,
3082 ins->inst_basereg, ins->inst_offset);
3085 case OP_LOADI1_MEMBASE: {
3086 S390_LONG (code, lgb, lgb, ins->dreg, 0,
3087 ins->inst_basereg, ins->inst_offset);
3090 case OP_LOADU2_MEMBASE: {
3091 S390_LONG (code, llgh, llgh, ins->dreg, 0,
3092 ins->inst_basereg, ins->inst_offset);
3095 case OP_LOADI2_MEMBASE: {
3096 S390_LONG (code, lgh, lgh, ins->dreg, 0,
3097 ins->inst_basereg, ins->inst_offset);
3100 case OP_LCONV_TO_I1: {
3101 s390_lgbr (code, ins->dreg, ins->sreg1);
3104 case OP_LCONV_TO_I2: {
3105 s390_lghr (code, ins->dreg, ins->sreg1);
3108 case OP_LCONV_TO_U1: {
3109 s390_llgcr (code, ins->dreg, ins->sreg1);
3112 case OP_LCONV_TO_U2: {
3113 s390_llghr (code, ins->dreg, ins->sreg1);
3116 case OP_ICONV_TO_I1: {
3117 s390_lgbr (code, ins->dreg, ins->sreg1);
3120 case OP_ICONV_TO_I2: {
3121 s390_lghr (code, ins->dreg, ins->sreg1);
3124 case OP_ICONV_TO_U1: {
3125 s390_llgcr (code, ins->dreg, ins->sreg1);
3128 case OP_ICONV_TO_U2: {
3129 s390_llghr (code, ins->dreg, ins->sreg1);
3134 if (is_unsigned (ins->next))
3135 s390_clgr (code, ins->sreg1, ins->sreg2);
3137 s390_cgr (code, ins->sreg1, ins->sreg2);
3141 if (is_unsigned (ins->next))
3142 s390_clr (code, ins->sreg1, ins->sreg2);
3144 s390_cr (code, ins->sreg1, ins->sreg2);
3147 case OP_COMPARE_IMM:
3148 case OP_LCOMPARE_IMM: {
3149 S390_SET (code, s390_r0, ins->inst_imm);
3150 if (is_unsigned (ins->next))
3151 s390_clgr (code, ins->sreg1, s390_r0);
3153 s390_cgr (code, ins->sreg1, s390_r0);
3156 case OP_ICOMPARE_IMM: {
3157 S390_SET (code, s390_r0, ins->inst_imm);
3158 if (is_unsigned (ins->next))
3159 s390_clr (code, ins->sreg1, s390_r0);
3161 s390_cr (code, ins->sreg1, s390_r0);
3165 mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3167 S390_CALL_TEMPLATE (code, s390_r14);
3172 s390_agr (code, ins->dreg, src2);
3177 s390_agr (code, ins->dreg, src2);
3182 s390_alcgr (code, ins->dreg, src2);
3186 if (ins->dreg != ins->sreg1) {
3187 s390_lgr (code, ins->dreg, ins->sreg1);
3189 if (s390_is_imm16 (ins->inst_imm)) {
3190 s390_aghi (code, ins->dreg, ins->inst_imm);
3191 } else if (s390_is_imm32 (ins->inst_imm)) {
3192 s390_agfi (code, ins->dreg, ins->inst_imm);
3194 S390_SET (code, s390_r0, ins->inst_imm);
3195 s390_agr (code, ins->dreg, s390_r0);
3200 if (ins->dreg != ins->sreg1) {
3201 s390_lgr (code, ins->dreg, ins->sreg1);
3203 g_assert (s390_is_imm16 (ins->inst_imm));
3204 s390_aghi (code, ins->dreg, ins->inst_imm);
3208 if (ins->dreg != ins->sreg1) {
3209 s390_lgr (code, ins->dreg, ins->sreg1);
3211 if (s390_is_imm16 (ins->inst_imm)) {
3212 s390_lghi (code, s390_r0, ins->inst_imm);
3213 s390_alcgr (code, ins->dreg, s390_r0);
3215 S390_SET (code, s390_r0, ins->inst_imm);
3216 s390_alcgr (code, ins->dreg, s390_r0);
3221 case OP_S390_IADD_OVF: {
3223 s390_ar (code, ins->dreg, src2);
3224 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3225 s390_lgfr (code, ins->dreg, ins->dreg);
3228 case OP_IADD_OVF_UN:
3229 case OP_S390_IADD_OVF_UN: {
3231 s390_algr (code, ins->dreg, src2);
3232 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3233 s390_llgfr (code, ins->dreg, ins->dreg);
3236 case OP_ADD_OVF_CARRY: {
3238 s390_lghi (code, s390_r0, 0);
3239 s390_lgr (code, s390_r1, s390_r0);
3240 s390_alcgr (code, s390_r0, s390_r1);
3241 s390_agr (code, ins->dreg, src2);
3242 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3243 s390_agr (code, ins->dreg, s390_r0);
3244 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3247 case OP_ADD_OVF_UN_CARRY: {
3249 s390_alcgr (code, ins->dreg, src2);
3250 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3255 s390_sgr (code, ins->dreg, src2);
3260 s390_sgr (code, ins->dreg, src2);
3265 s390_slbgr(code, ins->dreg, src2);
3269 if (ins->dreg != ins->sreg1) {
3270 s390_lgr (code, ins->dreg, ins->sreg1);
3272 if (s390_is_imm16 (-ins->inst_imm)) {
3273 s390_aghi (code, ins->dreg, -ins->inst_imm);
3274 } else if (s390_is_imm32 (-ins->inst_imm)) {
3275 s390_slgfi (code, ins->dreg, ins->inst_imm);
3277 S390_SET (code, s390_r0, ins->inst_imm);
3278 s390_slgr (code, ins->dreg, s390_r0);
3283 if (ins->dreg != ins->sreg1) {
3284 s390_lgr (code, ins->dreg, ins->sreg1);
3286 if (s390_is_imm16 (-ins->inst_imm)) {
3287 s390_aghi (code, ins->dreg, -ins->inst_imm);
3288 } else if (s390_is_imm32 (-ins->inst_imm)) {
3289 s390_slgfi (code, ins->dreg, ins->inst_imm);
3291 S390_SET (code, s390_r0, ins->inst_imm);
3292 s390_slgr (code, ins->dreg, s390_r0);
3297 if (ins->dreg != ins->sreg1) {
3298 s390_lgr (code, ins->dreg, ins->sreg1);
3300 if (s390_is_imm16 (-ins->inst_imm)) {
3301 s390_lghi (code, s390_r0, ins->inst_imm);
3302 s390_slbgr (code, ins->dreg, s390_r0);
3304 S390_SET (code, s390_r0, ins->inst_imm);
3305 s390_slbgr(code, ins->dreg, s390_r0);
3309 case OP_SUB_OVF_CARRY: {
3311 s390_lghi (code, s390_r0, 0);
3312 s390_lgr (code, s390_r1, s390_r0);
3313 s390_slbgr (code, s390_r0, s390_r1);
3314 s390_sgr (code, ins->dreg, src2);
3315 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3316 s390_agr (code, ins->dreg, s390_r0);
3317 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3320 case OP_SUB_OVF_UN_CARRY: {
3322 s390_slbgr (code, ins->dreg, src2);
3323 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3327 if (ins->sreg1 == ins->dreg) {
3328 s390_ngr (code, ins->dreg, ins->sreg2);
3331 if (ins->sreg2 == ins->dreg) {
3332 s390_ngr (code, ins->dreg, ins->sreg1);
3335 s390_lgr (code, ins->dreg, ins->sreg1);
3336 s390_ngr (code, ins->dreg, ins->sreg2);
3342 if (ins->dreg != ins->sreg1) {
3343 s390_lgr (code, ins->dreg, ins->sreg1);
3345 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3346 s390_ngr (code, ins->dreg, s390_r0);
3350 s390_lgr (code, s390_r1, ins->sreg1);
3351 s390_dsgr (code, s390_r0, ins->sreg2);
3352 s390_lgr (code, ins->dreg, s390_r1);
3356 s390_lgr (code, s390_r1, ins->sreg1);
3357 s390_lghi (code, s390_r0, 0);
3358 s390_dlgr (code, s390_r0, ins->sreg2);
3359 s390_lgr (code, ins->dreg, s390_r1);
3363 s390_lgr (code, s390_r1, ins->sreg1);
3364 s390_dsgr (code, s390_r0, ins->sreg2);
3365 s390_lgr (code, ins->dreg, s390_r0);
3369 if (s390_is_imm16 (ins->inst_imm)) {
3370 s390_lghi (code, s390_r13, ins->inst_imm);
3372 s390_lgfi (code, s390_r13, ins->inst_imm);
3374 s390_lgr (code, s390_r0, ins->sreg1);
3375 s390_dsgr (code, s390_r0, s390_r13);
3376 s390_lgfr (code, ins->dreg, s390_r0);
3380 s390_lgr (code, s390_r1, ins->sreg1);
3381 s390_lghi (code, s390_r0, 0);
3382 s390_dlgr (code, s390_r0, ins->sreg2);
3383 s390_lgr (code, ins->dreg, s390_r0);
3387 if (ins->sreg1 == ins->dreg) {
3388 s390_ogr (code, ins->dreg, ins->sreg2);
3391 if (ins->sreg2 == ins->dreg) {
3392 s390_ogr (code, ins->dreg, ins->sreg1);
3395 s390_lgr (code, ins->dreg, ins->sreg1);
3396 s390_ogr (code, ins->dreg, ins->sreg2);
3402 if (ins->dreg != ins->sreg1) {
3403 s390_lgr (code, ins->dreg, ins->sreg1);
3405 S390_SET_MASK(code, s390_r0, ins->inst_imm);
3406 s390_ogr (code, ins->dreg, s390_r0);
3410 if (ins->sreg1 == ins->dreg) {
3411 s390_xgr (code, ins->dreg, ins->sreg2);
3414 if (ins->sreg2 == ins->dreg) {
3415 s390_xgr (code, ins->dreg, ins->sreg1);
3418 s390_lgr (code, ins->dreg, ins->sreg1);
3419 s390_xgr (code, ins->dreg, ins->sreg2);
3425 if (ins->dreg != ins->sreg1) {
3426 s390_lgr (code, ins->dreg, ins->sreg1);
3428 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3429 s390_xgr (code, ins->dreg, s390_r0);
3434 s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3439 if (ins->sreg1 != ins->dreg) {
3440 s390_lgr (code, ins->dreg, ins->sreg1);
3442 s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3447 s390_srag (code, ins->dreg, ins->dreg, src2, 0);
3452 if (ins->sreg1 != ins->dreg) {
3453 s390_lgr (code, ins->dreg, ins->sreg1);
3455 s390_srag (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3459 case OP_LSHR_UN_IMM: {
3460 if (ins->sreg1 != ins->dreg) {
3461 s390_lgr (code, ins->dreg, ins->sreg1);
3463 s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3468 s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3472 if (ins->sreg1 != ins->dreg) {
3473 s390_lgr (code, ins->dreg, ins->sreg1);
3475 s390_lghi (code, s390_r0, -1);
3476 s390_xgr (code, ins->dreg, s390_r0);
3480 s390_lcgr (code, ins->dreg, ins->sreg1);
3485 s390_msgr (code, ins->dreg, src2);
3490 if (ins->dreg != ins->sreg1) {
3491 s390_lgr (code, ins->dreg, ins->sreg1);
3493 if (s390_is_imm16 (ins->inst_imm)) {
3494 s390_lghi (code, s390_r13, ins->inst_imm);
3495 } else if (s390_is_imm32 (ins->inst_imm)) {
3496 s390_lgfi (code, s390_r13, ins->inst_imm);
3498 S390_SET (code, s390_r13, ins->inst_imm);
3500 s390_msgr (code, ins->dreg, s390_r13);
3505 s390_ltgr (code, s390_r1, ins->sreg1);
3506 s390_jz (code, 0); CODEPTR(code, o[0]);
3507 s390_ltgr (code, s390_r0, ins->sreg2);
3509 s390_lghi (code, s390_r1, 0);
3510 s390_j (code, 0); CODEPTR(code, o[1]);
3511 s390_xgr (code, s390_r0, s390_r1);
3512 s390_msgr (code, s390_r1, ins->sreg2);
3513 s390_xgr (code, s390_r0, s390_r1);
3514 s390_srlg (code, s390_r0, s390_r0, 0, 63);
3515 s390_ltgr (code, s390_r0, s390_r0);
3516 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3517 PTRSLOT (code, o[0]);
3518 PTRSLOT (code, o[1]);
3519 s390_lgr (code, ins->dreg, s390_r1);
3522 case OP_LMUL_OVF_UN: {
3523 s390_lghi (code, s390_r0, 0);
3524 s390_lgr (code, s390_r1, ins->sreg1);
3525 s390_mlgr (code, s390_r0, ins->sreg2);
3526 s390_ltgr (code, s390_r0, s390_r0);
3527 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3528 s390_lgr (code, ins->dreg, s390_r1);
3532 g_assert_not_reached ();
3534 s390_algr (code, ins->dreg, src2);
3539 s390_agr (code, ins->dreg, src2);
3543 g_assert_not_reached ();
3545 s390_alcgr (code, ins->dreg, src2);
3549 if (ins->dreg != ins->sreg1) {
3550 s390_lgfr (code, ins->dreg, ins->sreg1);
3552 if (s390_is_imm16 (ins->inst_imm)) {
3553 s390_aghi (code, ins->dreg, ins->inst_imm);
3555 s390_afi (code, ins->dreg, ins->inst_imm);
3560 if (ins->dreg != ins->sreg1) {
3561 s390_lgfr (code, ins->dreg, ins->sreg1);
3563 if (s390_is_imm16 (ins->inst_imm)) {
3564 s390_lghi (code, s390_r0, ins->inst_imm);
3565 s390_alcgr (code, ins->dreg, s390_r0);
3567 S390_SET (code, s390_r0, ins->inst_imm);
3568 s390_alcgr (code, ins->dreg, s390_r0);
3573 case OP_S390_LADD_OVF: {
3575 s390_agr (code, ins->dreg, src2);
3576 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3579 case OP_LADD_OVF_UN:
3580 case OP_S390_LADD_OVF_UN: {
3582 s390_algr (code, ins->dreg, src2);
3583 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3587 CHECK_SRCDST_NCOM_I;
3588 s390_slgr (code, ins->dreg, src2);
3592 CHECK_SRCDST_NCOM_I;
3593 s390_sgr (code, ins->dreg, src2);
3597 CHECK_SRCDST_NCOM_I;
3598 s390_slbgr (code, ins->dreg, src2);
3602 if (ins->dreg != ins->sreg1) {
3603 s390_lgfr (code, ins->dreg, ins->sreg1);
3605 if (s390_is_imm16 (-ins->inst_imm)) {
3606 s390_aghi (code, ins->dreg, -ins->inst_imm);
3608 s390_agfi (code, ins->dreg, -ins->inst_imm);
3613 S390_SET (code, s390_r0, ins->inst_imm);
3614 s390_slgfr (code, ins->dreg, s390_r0);
3618 case OP_S390_ISUB_OVF: {
3620 s390_sr (code, ins->dreg, src2);
3621 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3622 s390_lgfr (code, ins->dreg, ins->dreg);
3625 case OP_ISUB_OVF_UN:
3626 case OP_S390_ISUB_OVF_UN: {
3628 s390_slr (code, ins->dreg, src2);
3629 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3630 s390_llgfr(code, ins->dreg, ins->dreg);
3634 case OP_S390_LSUB_OVF: {
3636 s390_sgr (code, ins->dreg, src2);
3637 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3640 case OP_LSUB_OVF_UN:
3641 case OP_S390_LSUB_OVF_UN: {
3643 s390_slgr (code, ins->dreg, src2);
3644 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3648 CHECK_SRCDST_NCOM_I;
3649 s390_ngr (code, ins->dreg, src2);
3653 if (ins->dreg != ins->sreg1) {
3654 s390_lgfr (code, ins->dreg, ins->sreg1);
3656 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3657 s390_ngr (code, ins->dreg, s390_r0);
3661 s390_lgfr (code, s390_r0, ins->sreg1);
3662 s390_srda (code, s390_r0, 0, 32);
3663 s390_dr (code, s390_r0, ins->sreg2);
3664 s390_lgfr (code, ins->dreg, s390_r1);
3668 s390_lgfr (code, s390_r0, ins->sreg1);
3669 s390_srdl (code, s390_r0, 0, 32);
3670 s390_dlr (code, s390_r0, ins->sreg2);
3671 s390_lgfr (code, ins->dreg, s390_r1);
3675 if (s390_is_imm16 (ins->inst_imm)) {
3676 s390_lghi (code, s390_r13, ins->inst_imm);
3678 s390_lgfi (code, s390_r13, ins->inst_imm);
3680 s390_lgfr (code, s390_r0, ins->sreg1);
3681 s390_srda (code, s390_r0, 0, 32);
3682 s390_dr (code, s390_r0, ins->sreg2);
3683 s390_lgfr (code, ins->dreg, s390_r1);
3687 s390_lgfr (code, s390_r0, ins->sreg1);
3688 s390_srda (code, s390_r0, 0, 32);
3689 s390_dr (code, s390_r0, ins->sreg2);
3690 s390_lgfr (code, ins->dreg, s390_r0);
3693 s390_lgfr (code, s390_r0, ins->sreg1);
3694 s390_srdl (code, s390_r0, 0, 32);
3695 s390_dlr (code, s390_r0, ins->sreg2);
3696 s390_lgfr (code, ins->dreg, s390_r0);
3700 if (s390_is_imm16 (ins->inst_imm)) {
3701 s390_lghi (code, s390_r13, ins->inst_imm);
3703 s390_lgfi (code, s390_r13, ins->inst_imm);
3705 s390_lgfr (code, s390_r0, ins->sreg1);
3706 s390_srda (code, s390_r0, 0, 32);
3707 s390_dr (code, s390_r0, ins->sreg2);
3708 s390_lgfr (code, ins->dreg, s390_r0);
3713 s390_ogr (code, ins->dreg, src2);
3717 if (ins->dreg != ins->sreg1) {
3718 s390_lgfr (code, ins->dreg, ins->sreg1);
3720 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3721 s390_ogr (code, ins->dreg, s390_r0);
3726 s390_xgr (code, ins->dreg, src2);
3730 if (ins->dreg != ins->sreg1) {
3731 s390_lgfr (code, ins->dreg, ins->sreg1);
3733 S390_SET_MASK (code, s390_r0, ins->inst_imm);
3734 s390_xgr (code, ins->dreg, s390_r0);
3739 s390_sll (code, ins->dreg, src2, 0);
3743 if (ins->sreg1 != ins->dreg) {
3744 s390_lgfr (code, ins->dreg, ins->sreg1);
3746 s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3751 s390_sra (code, ins->dreg, src2, 0);
3755 if (ins->sreg1 != ins->dreg) {
3756 s390_lgfr (code, ins->dreg, ins->sreg1);
3758 s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3761 case OP_ISHR_UN_IMM: {
3762 if (ins->sreg1 != ins->dreg) {
3763 s390_lgfr (code, ins->dreg, ins->sreg1);
3765 s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
3770 s390_srl (code, ins->dreg, src2, 0);
3774 if (ins->sreg1 != ins->dreg) {
3775 s390_lgfr (code, ins->dreg, ins->sreg1);
3777 s390_lghi (code, s390_r0, -1);
3778 s390_xgr (code, ins->dreg, s390_r0);
3782 s390_lcgr (code, ins->dreg, ins->sreg1);
3787 s390_msr (code, ins->dreg, src2);
3791 if (ins->dreg != ins->sreg1) {
3792 s390_lgfr (code, ins->dreg, ins->sreg1);
3794 if (s390_is_imm16 (ins->inst_imm)) {
3795 s390_lghi (code, s390_r0, ins->inst_imm);
3797 s390_lgfi (code, s390_r0, ins->inst_imm);
3799 s390_msr (code, ins->dreg, s390_r0);
3804 s390_ltr (code, s390_r1, ins->sreg1);
3805 s390_jz (code, 0); CODEPTR(code, o[0]);
3806 s390_ltr (code, s390_r0, ins->sreg2);
3808 s390_lhi (code, s390_r1, 0);
3809 s390_j (code, 0); CODEPTR(code, o[1]);
3810 s390_xr (code, s390_r0, s390_r1);
3811 s390_msr (code, s390_r1, ins->sreg2);
3812 s390_xr (code, s390_r0, s390_r1);
3813 s390_srl (code, s390_r0, 0, 31);
3814 s390_ltr (code, s390_r0, s390_r0);
3815 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3816 PTRSLOT (code, o[0]);
3817 PTRSLOT (code, o[1]);
3818 s390_lgfr (code, ins->dreg, s390_r1);
3821 case OP_IMUL_OVF_UN: {
3822 s390_lhi (code, s390_r0, 0);
3823 s390_lr (code, s390_r1, ins->sreg1);
3824 s390_mlr (code, s390_r0, ins->sreg2);
3825 s390_ltr (code, s390_r0, s390_r0);
3826 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3827 s390_lgfr (code, ins->dreg, s390_r1);
3832 S390_SET (code, ins->dreg, ins->inst_c0);
3836 mono_add_patch_info (cfg, code - cfg->native_code,
3837 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3838 S390_LOAD_TEMPLATE (code, ins->dreg);
3841 case OP_JUMP_TABLE: {
3842 mono_add_patch_info (cfg, code - cfg->native_code,
3843 (MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
3844 S390_LOAD_TEMPLATE (code, ins->dreg);
3848 if (ins->dreg != ins->sreg1) {
3849 s390_lgr (code, ins->dreg, ins->sreg1);
3853 case OP_LCONV_TO_I8:
3855 s390_lgfr (code, ins->dreg, ins->sreg1);
3857 case OP_LCONV_TO_I4:
3858 s390_lgfr (code, ins->dreg, ins->sreg1);
3861 case OP_LCONV_TO_U8:
3862 case OP_LCONV_TO_U4:
3864 s390_llgfr (code, ins->dreg, ins->sreg1);
3866 case OP_LCONV_TO_OVF_U4:
3867 S390_SET (code, s390_r0, 4294967295);
3868 s390_clgr (code, ins->sreg1, s390_r0);
3869 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3870 s390_ltgr (code, ins->sreg1, ins->sreg1);
3871 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3872 s390_llgfr(code, ins->dreg, ins->sreg1);
3874 case OP_LCONV_TO_OVF_I4_UN:
3875 S390_SET (code, s390_r0, 2147483647);
3876 s390_cgr (code, ins->sreg1, s390_r0);
3877 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
3878 s390_ltgr (code, ins->sreg1, ins->sreg1);
3879 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
3880 s390_lgfr (code, ins->dreg, ins->sreg1);
3883 if (ins->dreg != ins->sreg1) {
3884 s390_ldr (code, ins->dreg, ins->sreg1);
3887 case OP_MOVE_F_TO_I8:
3888 s390_lgdr (code, ins->dreg, ins->sreg1);
3890 case OP_MOVE_I8_TO_F:
3891 s390_ldgr (code, ins->dreg, ins->sreg1);
3893 case OP_MOVE_F_TO_I4:
3894 s390_ledbr (code, s390_f0, ins->sreg1);
3895 s390_lgdr (code, ins->dreg, s390_f0);
3896 s390_srag (code, ins->dreg, ins->dreg, 0, 32);
3898 case OP_MOVE_I4_TO_F:
3899 s390_slag (code, s390_r0, ins->sreg1, 0, 32);
3900 s390_ldgr (code, ins->dreg, s390_r0);
3901 s390_ldebr (code, ins->dreg, ins->dreg);
3903 case OP_FCONV_TO_R4:
3904 s390_ledbr (code, ins->dreg, ins->sreg1);
3905 s390_ldebr (code, ins->dreg, ins->dreg);
3907 case OP_S390_SETF4RET:
3908 s390_ledbr (code, ins->dreg, ins->sreg1);
3911 if (s390_is_imm16 (ins->inst_offset)) {
3912 s390_lghi (code, s390_r13, ins->inst_offset);
3913 } else if (s390_is_imm32 (ins->inst_offset)) {
3914 s390_lgfi (code, s390_r13, ins->inst_offset);
3916 S390_SET (code, s390_r13, ins->inst_offset);
3918 s390_ear (code, s390_r1, 0);
3919 s390_sllg(code, s390_r1, s390_r1, 0, 32);
3920 s390_ear (code, s390_r1, 1);
3921 s390_lg (code, ins->dreg, s390_r13, s390_r1, 0);
3925 if (cfg->method->save_lmf)
3926 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
3928 if (cfg->flags & MONO_CFG_HAS_TAIL) {
3929 code = emit_load_volatile_arguments (code, cfg);
3932 code = backUpStackPtr(cfg, code);
3933 s390_lg (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
3934 mono_add_patch_info (cfg, code - cfg->native_code,
3935 MONO_PATCH_INFO_METHOD_JUMP,
3937 s390_jcl (code, S390_CC_UN, 0);
3940 case OP_CHECK_THIS: {
3941 /* ensure ins->sreg1 is not NULL */
3942 s390_lg (code, s390_r0, 0, ins->sreg1, 0);
3943 s390_ltgr (code, s390_r0, s390_r0);
3944 // EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
3948 int offset = cfg->sig_cookie + cfg->stack_usage;
3950 if (s390_is_imm16 (offset)) {
3951 s390_lghi (code, s390_r0, offset);
3952 } else if (s390_is_imm32 (offset)) {
3953 s390_lgfi (code, s390_r0, offset);
3955 S390_SET (code, s390_r0, offset);
3957 s390_agr (code, s390_r0, cfg->frame_reg);
3958 s390_stg (code, s390_r0, 0, ins->sreg1, 0);
3962 call = (MonoCallInst*)ins;
3963 if (ins->flags & MONO_INST_HAS_METHOD)
3964 mono_add_patch_info (cfg, code-cfg->native_code,
3965 MONO_PATCH_INFO_METHOD,
3968 mono_add_patch_info (cfg, code-cfg->native_code,
3969 MONO_PATCH_INFO_ABS,
3971 S390_CALL_TEMPLATE (code, s390_r14);
3972 if (call->signature->ret->type == MONO_TYPE_R4)
3973 s390_ldebr (code, s390_f0, s390_f0);
3981 call = (MonoCallInst*)ins;
3982 if (ins->flags & MONO_INST_HAS_METHOD)
3983 mono_add_patch_info (cfg, code-cfg->native_code,
3984 MONO_PATCH_INFO_METHOD,
3987 mono_add_patch_info (cfg, code-cfg->native_code,
3988 MONO_PATCH_INFO_ABS,
3990 S390_CALL_TEMPLATE (code, s390_r14);
3993 case OP_FCALL_REG: {
3994 call = (MonoCallInst*)ins;
3995 s390_lgr (code, s390_r1, ins->sreg1);
3996 s390_basr (code, s390_r14, s390_r1);
3997 if (call->signature->ret->type == MONO_TYPE_R4)
3998 s390_ldebr (code, s390_f0, s390_f0);
4004 case OP_VOIDCALL_REG:
4006 s390_lgr (code, s390_r1, ins->sreg1);
4007 s390_basr (code, s390_r14, s390_r1);
4010 case OP_FCALL_MEMBASE: {
4011 call = (MonoCallInst*)ins;
4012 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4013 s390_basr (code, s390_r14, s390_r1);
4014 if (call->signature->ret->type == MONO_TYPE_R4)
4015 s390_ldebr (code, s390_f0, s390_f0);
4018 case OP_LCALL_MEMBASE:
4019 case OP_VCALL_MEMBASE:
4020 case OP_VCALL2_MEMBASE:
4021 case OP_VOIDCALL_MEMBASE:
4022 case OP_CALL_MEMBASE: {
4023 s390_lg (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4024 s390_basr (code, s390_r14, s390_r1);
4031 if (cfg->param_area == 0)
4032 alloca_skip = S390_MINIMAL_STACK_SIZE;
4034 alloca_skip = cfg->param_area;
4036 area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4037 s390_lgr (code, s390_r1, ins->sreg1);
4038 if (ins->flags & MONO_INST_INIT)
4039 s390_lgr (code, s390_r0, ins->sreg1);
4040 s390_aghi (code, s390_r1, 14);
4041 s390_srlg (code, s390_r1, s390_r1, 0, 3);
4042 s390_sllg (code, s390_r1, s390_r1, 0, 3);
4043 if (cfg->method->save_lmf) {
4044 /*----------------------------------*/
4045 /* we have to adjust lmf ebp value */
4046 /*----------------------------------*/
4047 int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4049 s390_lgr (code, s390_r13, cfg->frame_reg);
4050 if (s390_is_imm16(lmfOffset)) {
4051 s390_aghi (code, s390_r13, lmfOffset);
4052 } else if (s390_is_imm32(lmfOffset)) {
4053 s390_agfi (code, s390_r13, lmfOffset);
4055 S390_SET (code, s390_r13, lmfOffset);
4057 s390_lgr (code, s390_r14, STK_BASE);
4058 s390_sgr (code, s390_r14, s390_r1);
4059 s390_stg (code, s390_r14, 0, s390_r13,
4060 G_STRUCT_OFFSET(MonoLMF, ebp));
4062 s390_lg (code, s390_r13, 0, STK_BASE, 0);
4063 s390_sgr (code, STK_BASE, s390_r1);
4064 s390_stg (code, s390_r13, 0, STK_BASE, 0);
4065 s390_la (code, ins->dreg, 0, STK_BASE, area_offset);
4066 s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4067 s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4068 if (ins->flags & MONO_INST_INIT) {
4069 s390_lgr (code, s390_r1, s390_r0);
4070 s390_lgr (code, s390_r0, ins->dreg);
4071 s390_lgr (code, s390_r14, s390_r12);
4072 s390_lghi (code, s390_r13, 0);
4073 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4075 s390_lgr (code, s390_r12, s390_r14);
4080 s390_lgr (code, s390_r2, ins->sreg1);
4081 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4082 (gpointer) "mono_arch_throw_exception");
4083 S390_CALL_TEMPLATE(code, s390_r14);
4087 s390_lgr (code, s390_r2, ins->sreg1);
4088 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4089 (gpointer) "mono_arch_rethrow_exception");
4090 S390_CALL_TEMPLATE(code, s390_r14);
4093 case OP_START_HANDLER: {
4094 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4096 S390_LONG (code, stg, stg, s390_r14, 0,
4097 spvar->inst_basereg,
4098 spvar->inst_offset);
4101 case OP_ENDFILTER: {
4102 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4104 if (ins->sreg1 != s390_r2)
4105 s390_lgr(code, s390_r2, ins->sreg1);
4106 S390_LONG (code, lg, lg, s390_r14, 0,
4107 spvar->inst_basereg,
4108 spvar->inst_offset);
4109 s390_br (code, s390_r14);
4112 case OP_ENDFINALLY: {
4113 MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4115 S390_LONG (code, lg, lg, s390_r14, 0,
4116 spvar->inst_basereg,
4117 spvar->inst_offset);
4118 s390_br (code, s390_r14);
4121 case OP_CALL_HANDLER: {
4122 mono_add_patch_info (cfg, code-cfg->native_code,
4123 MONO_PATCH_INFO_BB, ins->inst_target_bb);
4124 s390_brasl (code, s390_r14, 0);
4125 mono_cfg_add_try_hole (cfg, ins->inst_eh_block, code, bb);
4129 ins->inst_c0 = code - cfg->native_code;
4132 case OP_RELAXED_NOP:
4135 case OP_DUMMY_STORE:
4136 case OP_NOT_REACHED:
4140 case OP_IL_SEQ_POINT:
4141 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4143 case OP_SEQ_POINT: {
4146 if (cfg->compile_aot)
4150 * Read from the single stepping trigger page. This will cause a
4151 * SIGSEGV when single stepping is enabled.
4152 * We do this _before_ the breakpoint, so single stepping after
4153 * a breakpoint is hit will step to the next IL offset.
4155 if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4156 breakpointCode.pTrigger = ss_trigger_page;
4157 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4158 code += BREAKPOINT_SIZE;
4161 mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4164 * A placeholder for a possible breakpoint inserted by
4165 * mono_arch_set_breakpoint ().
4167 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4171 * Add an additional nop so skipping the bp doesn't cause the ip to point
4172 * to another IL offset.
4178 case OP_GENERIC_CLASS_INIT: {
4179 static int byte_offset = -1;
4180 static guint8 bitmask;
4183 g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4185 if (byte_offset < 0)
4186 mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4188 s390_tm (code, ins->sreg1, byte_offset, bitmask);
4189 s390_jo (code, 0); CODEPTR(code, jump);
4191 mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4192 "mono_generic_class_init");
4193 S390_CALL_TEMPLATE(code, s390_r14);
4195 PTRSLOT (code, jump);
4197 ins->flags |= MONO_INST_GC_CALLSITE;
4198 ins->backend.pc_offset = code - cfg->native_code;
4202 EMIT_UNCOND_BRANCH(ins);
4205 s390_br (code, ins->sreg1);
4211 s390_lghi(code, ins->dreg, 1);
4213 s390_lghi(code, ins->dreg, 0);
4219 s390_lghi(code, ins->dreg, 1);
4221 s390_lghi(code, ins->dreg, 0);
4227 s390_lghi(code, ins->dreg, 1);
4229 s390_lghi(code, ins->dreg, 0);
4235 s390_lghi(code, ins->dreg, 1);
4237 s390_lghi(code, ins->dreg, 0);
4243 s390_lghi(code, ins->dreg, 1);
4245 s390_lghi(code, ins->dreg, 0);
4248 case OP_COND_EXC_EQ:
4249 case OP_COND_EXC_IEQ:
4250 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4252 case OP_COND_EXC_NE_UN:
4253 case OP_COND_EXC_INE_UN:
4254 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4256 case OP_COND_EXC_LT:
4257 case OP_COND_EXC_ILT:
4258 case OP_COND_EXC_LT_UN:
4259 case OP_COND_EXC_ILT_UN:
4260 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4262 case OP_COND_EXC_GT:
4263 case OP_COND_EXC_IGT:
4264 case OP_COND_EXC_GT_UN:
4265 case OP_COND_EXC_IGT_UN:
4266 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4268 case OP_COND_EXC_GE:
4269 case OP_COND_EXC_IGE:
4270 case OP_COND_EXC_GE_UN:
4271 case OP_COND_EXC_IGE_UN:
4272 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4274 case OP_COND_EXC_LE:
4275 case OP_COND_EXC_ILE:
4276 case OP_COND_EXC_LE_UN:
4277 case OP_COND_EXC_ILE_UN:
4278 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4280 case OP_COND_EXC_OV:
4281 case OP_COND_EXC_IOV:
4282 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4284 case OP_COND_EXC_NO:
4285 case OP_COND_EXC_INO:
4286 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4289 case OP_COND_EXC_IC:
4290 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4292 case OP_COND_EXC_NC:
4293 case OP_COND_EXC_INC:
4294 EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4298 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4302 EMIT_COND_BRANCH (ins, S390_CC_NE);
4308 EMIT_COND_BRANCH (ins, S390_CC_LT);
4314 EMIT_COND_BRANCH (ins, S390_CC_GT);
4320 EMIT_COND_BRANCH (ins, S390_CC_GE);
4326 EMIT_COND_BRANCH (ins, S390_CC_LE);
4329 /* floating point opcodes */
4331 if (*((double *) ins->inst_p0) == 0) {
4332 s390_lzdr (code, ins->dreg);
4334 S390_SET (code, s390_r13, ins->inst_p0);
4335 s390_ld (code, ins->dreg, 0, s390_r13, 0);
4340 if (*((float *) ins->inst_p0) == 0) {
4341 s390_lzdr (code, ins->dreg);
4343 S390_SET (code, s390_r13, ins->inst_p0);
4344 s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4348 case OP_STORER8_MEMBASE_REG: {
4349 S390_LONG (code, stdy, std, ins->sreg1, 0,
4350 ins->inst_destbasereg, ins->inst_offset);
4353 case OP_LOADR8_MEMBASE: {
4354 S390_LONG (code, ldy, ld, ins->dreg, 0,
4355 ins->inst_basereg, ins->inst_offset);
4358 case OP_STORER4_MEMBASE_REG: {
4359 s390_ledbr (code, s390_f15, ins->sreg1);
4360 S390_LONG (code, stey, ste, s390_f15, 0,
4361 ins->inst_destbasereg, ins->inst_offset);
4364 case OP_LOADR4_MEMBASE: {
4365 S390_LONG (code, ley, le, s390_f15, 0,
4366 ins->inst_basereg, ins->inst_offset);
4367 s390_ldebr (code, ins->dreg, s390_f15);
4370 case OP_ICONV_TO_R_UN: {
4371 if (mono_hwcap_s390x_has_fpe) {
4372 s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4374 s390_llgfr (code, s390_r0, ins->sreg1);
4375 s390_cdgbr (code, ins->dreg, s390_r0);
4379 case OP_LCONV_TO_R_UN: {
4380 if (mono_hwcap_s390x_has_fpe) {
4381 s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4384 s390_cxgbr (code, s390_f12, ins->sreg1);
4385 s390_ltgr (code, ins->sreg1, ins->sreg1);
4386 s390_jnl (code, 0); CODEPTR(code, jump);
4387 S390_SET (code, s390_r13, 0x403f000000000000llu);
4388 s390_lgdr (code, s390_f13, s390_r13);
4389 s390_lzdr (code, s390_f15);
4390 s390_axbr (code, s390_f12, s390_f13);
4391 PTRSLOT(code, jump);
4392 s390_ldxbr (code, s390_f13, s390_f12);
4393 s390_ldr (code, ins->dreg, s390_f13);
4397 case OP_LCONV_TO_R4:
4398 case OP_ICONV_TO_R4: {
4399 s390_cegbr (code, ins->dreg, ins->sreg1);
4400 s390_ldebr (code, ins->dreg, ins->dreg);
4403 case OP_LCONV_TO_R8:
4404 case OP_ICONV_TO_R8: {
4405 s390_cdgbr (code, ins->dreg, ins->sreg1);
4408 case OP_FCONV_TO_I1:
4409 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4410 s390_ltgr (code, ins->dreg, ins->dreg);
4412 s390_oill (code, ins->dreg, 0x80);
4413 s390_lghi (code, s390_r0, 0xff);
4414 s390_ngr (code, ins->dreg, s390_r0);
4416 case OP_FCONV_TO_U1:
4417 if (mono_hwcap_s390x_has_fpe) {
4418 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4419 s390_lghi (code, s390_r0, 0xff);
4420 s390_ngr (code, ins->dreg, s390_r0);
4422 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4425 case OP_FCONV_TO_I2:
4426 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4427 s390_ltgr (code, ins->dreg, ins->dreg);
4429 s390_oill (code, ins->dreg, 0x8000);
4430 s390_llill (code, s390_r0, 0xffff);
4431 s390_ngr (code, ins->dreg, s390_r0);
4433 case OP_FCONV_TO_U2:
4434 if (mono_hwcap_s390x_has_fpe) {
4435 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4436 s390_llill (code, s390_r0, 0xffff);
4437 s390_ngr (code, ins->dreg, s390_r0);
4439 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4442 case OP_FCONV_TO_I4:
4444 s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4446 case OP_FCONV_TO_U4:
4448 if (mono_hwcap_s390x_has_fpe) {
4449 s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4451 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4454 case OP_FCONV_TO_I8:
4455 s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4457 case OP_FCONV_TO_U8:
4458 if (mono_hwcap_s390x_has_fpe) {
4459 s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4461 code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4464 case OP_LCONV_TO_OVF_I: {
4465 /* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4467 s390_ltgr (code, ins->sreg2, ins->sreg2);
4468 s390_jnl (code, 0); CODEPTR(code, o[0]);
4469 s390_ltgr (code, ins->sreg1, ins->sreg1);
4470 s390_jnl (code, 0); CODEPTR(code, o[1]);
4471 s390_lhi (code, s390_r13, -1);
4472 s390_cgr (code, ins->sreg1, s390_r13);
4473 s390_jnz (code, 0); CODEPTR(code, o[2]);
4474 if (ins->dreg != ins->sreg2)
4475 s390_lgr (code, ins->dreg, ins->sreg2);
4476 s390_j (code, 0); CODEPTR(code, o[3]);
4477 PTRSLOT(code, o[0]);
4478 s390_jz (code, 0); CODEPTR(code, o[4]);
4479 PTRSLOT(code, o[1]);
4480 PTRSLOT(code, o[2]);
4481 mono_add_patch_info (cfg, code - cfg->native_code,
4482 MONO_PATCH_INFO_EXC, "OverflowException");
4483 s390_brasl (code, s390_r14, 0);
4484 PTRSLOT(code, o[3]);
4485 PTRSLOT(code, o[4]);
4489 s390_lpdbr (code, ins->dreg, ins->sreg1);
4493 s390_sqdbr (code, ins->dreg, ins->sreg1);
4498 s390_adbr (code, ins->dreg, src2);
4502 CHECK_SRCDST_NCOM_F;
4503 s390_sdbr (code, ins->dreg, src2);
4508 s390_mdbr (code, ins->dreg, src2);
4512 CHECK_SRCDST_NCOM_F;
4513 s390_ddbr (code, ins->dreg, src2);
4517 s390_lcdbr (code, ins->dreg, ins->sreg1);
4521 CHECK_SRCDST_NCOM_F;
4522 s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4526 s390_cdbr (code, ins->sreg1, ins->sreg2);
4530 s390_cdbr (code, ins->sreg1, ins->sreg2);
4531 s390_lghi (code, ins->dreg, 1);
4533 s390_lghi (code, ins->dreg, 0);
4537 s390_cdbr (code, ins->sreg1, ins->sreg2);
4538 s390_lghi (code, ins->dreg, 1);
4540 s390_lghi (code, ins->dreg, 0);
4544 s390_cdbr (code, ins->sreg1, ins->sreg2);
4545 s390_lghi (code, ins->dreg, 1);
4547 s390_lghi (code, ins->dreg, 0);
4551 s390_cdbr (code, ins->sreg1, ins->sreg2);
4552 s390_lghi (code, ins->dreg, 1);
4554 s390_lghi (code, ins->dreg, 0);
4558 s390_cdbr (code, ins->sreg1, ins->sreg2);
4559 s390_lghi (code, ins->dreg, 1);
4561 s390_lghi (code, ins->dreg, 0);
4566 s390_jo (code, 0); CODEPTR(code, o);
4567 EMIT_COND_BRANCH (ins, S390_CC_EQ);
4572 EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4576 s390_jo (code, 0); CODEPTR(code, o);
4577 EMIT_COND_BRANCH (ins, S390_CC_LT);
4582 EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4586 s390_jo (code, 0); CODEPTR(code, o);
4587 EMIT_COND_BRANCH (ins, S390_CC_GT);
4592 EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4596 s390_jo (code, 0); CODEPTR(code, o);
4597 EMIT_COND_BRANCH (ins, S390_CC_GE);
4602 EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4606 s390_jo (code, 0); CODEPTR(code, o);
4607 EMIT_COND_BRANCH (ins, S390_CC_LE);
4612 EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
4616 s390_lhi (code, s390_r13, 0x7f);
4617 s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
4618 s390_jz (code, 0); CODEPTR(code, o);
4619 mono_add_patch_info (cfg, code - cfg->native_code,
4620 MONO_PATCH_INFO_EXC, "OverflowException");
4621 s390_brasl (code, s390_r14,0);
4625 case OP_S390_MOVE: {
4626 if (ins->backend.size > 0) {
4627 if (ins->backend.size <= 256) {
4628 s390_mvc (code, ins->backend.size, ins->dreg,
4629 ins->inst_offset, ins->sreg1, ins->inst_imm);
4631 s390_lgr (code, s390_r0, ins->dreg);
4632 if (ins->inst_offset > 0) {
4633 if (s390_is_imm16 (ins->inst_offset)) {
4634 s390_aghi (code, s390_r0, ins->inst_offset);
4635 } else if (s390_is_imm32 (ins->inst_offset)) {
4636 s390_agfi (code, s390_r0, ins->inst_offset);
4638 S390_SET (code, s390_r13, ins->inst_offset);
4639 s390_agr (code, s390_r0, s390_r13);
4642 s390_lgr (code, s390_r12, ins->sreg1);
4643 if (ins->inst_imm > 0) {
4644 if (s390_is_imm16 (ins->inst_imm)) {
4645 s390_aghi (code, s390_r12, ins->inst_imm);
4646 } else if (s390_is_imm32 (ins->inst_imm)) {
4647 s390_agfi (code, s390_r12, ins->inst_imm);
4649 S390_SET (code, s390_r13, ins->inst_imm);
4650 s390_agr (code, s390_r12, s390_r13);
4653 if (s390_is_imm16 (ins->backend.size)) {
4654 s390_lghi (code, s390_r1, ins->backend.size);
4655 } else if (s390_is_imm32 (ins->inst_offset)) {
4656 s390_agfi (code, s390_r1, ins->backend.size);
4658 S390_SET (code, s390_r13, ins->backend.size);
4659 s390_agr (code, s390_r1, s390_r13);
4661 s390_lgr (code, s390_r13, s390_r1);
4662 s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4668 case OP_ATOMIC_ADD_I8: {
4669 s390_lgr (code, s390_r1, ins->sreg2);
4670 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4671 s390_agr (code, s390_r1, s390_r0);
4672 s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4673 s390_jnz (code, -10);
4674 s390_lgr (code, ins->dreg, s390_r1);
4677 case OP_ATOMIC_EXCHANGE_I8: {
4678 s390_lg (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4679 s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4680 s390_jnz (code, -6);
4681 s390_lgr (code, ins->dreg, s390_r0);
4684 case OP_ATOMIC_ADD_I4: {
4685 s390_lgfr(code, s390_r1, ins->sreg2);
4686 s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4687 s390_agr (code, s390_r1, s390_r0);
4688 s390_cs (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
4689 s390_jnz (code, -9);
4690 s390_lgfr(code, ins->dreg, s390_r1);
4693 case OP_ATOMIC_EXCHANGE_I4: {
4694 s390_l (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
4695 s390_cs (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
4696 s390_jnz (code, -4);
4697 s390_lgfr(code, ins->dreg, s390_r0);
4700 case OP_S390_BKCHAIN: {
4701 s390_lgr (code, ins->dreg, ins->sreg1);
4702 if (s390_is_imm16 (cfg->stack_offset)) {
4703 s390_aghi (code, ins->dreg, cfg->stack_offset);
4704 } else if (s390_is_imm32 (cfg->stack_offset)) {
4705 s390_agfi (code, ins->dreg, cfg->stack_offset);
4707 S390_SET (code, s390_r13, cfg->stack_offset);
4708 s390_agr (code, ins->dreg, s390_r13);
4712 case OP_MEMORY_BARRIER:
4715 case OP_GC_SAFE_POINT: {
4718 g_assert (mono_threads_is_coop_enabled ());
4720 s390_chi (code, ins->sreg1, 1);
4721 s390_je (code, 0); CODEPTR(code, br);
4722 mono_add_patch_info (cfg, code- cfg->native_code, MONO_PATCH_INFO_ABS,
4723 mono_threads_state_poll);
4724 S390_CALL_TEMPLATE (code, s390_r14);
4728 case OP_GC_LIVENESS_DEF:
4729 case OP_GC_LIVENESS_USE:
4730 case OP_GC_PARAM_SLOT_LIVENESS_DEF:
4731 ins->backend.pc_offset = code - cfg->native_code;
4733 case OP_GC_SPILL_SLOT_LIVENESS_DEF:
4734 ins->backend.pc_offset = code - cfg->native_code;
4735 bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
4737 #ifdef MONO_ARCH_SIMD_INTRINSICS
4739 s390x_addps (code, ins->sreg1, ins->sreg2);
4742 s390x_divps (code, ins->sreg1, ins->sreg2);
4745 s390x_mulps (code, ins->sreg1, ins->sreg2);
4748 s390x_subps (code, ins->sreg1, ins->sreg2);
4751 s390x_maxps (code, ins->sreg1, ins->sreg2);
4754 s390x_minps (code, ins->sreg1, ins->sreg2);
4757 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4758 s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4761 s390x_andps (code, ins->sreg1, ins->sreg2);
4764 s390x_andnps (code, ins->sreg1, ins->sreg2);
4767 s390x_orps (code, ins->sreg1, ins->sreg2);
4770 s390x_xorps (code, ins->sreg1, ins->sreg2);
4773 s390x_sqrtps (code, ins->dreg, ins->sreg1);
4776 s390x_rsqrtps (code, ins->dreg, ins->sreg1);
4779 s390x_rcpps (code, ins->dreg, ins->sreg1);
4782 s390x_addsubps (code, ins->sreg1, ins->sreg2);
4785 s390x_haddps (code, ins->sreg1, ins->sreg2);
4788 s390x_hsubps (code, ins->sreg1, ins->sreg2);
4791 s390x_movshdup (code, ins->dreg, ins->sreg1);
4794 s390x_movsldup (code, ins->dreg, ins->sreg1);
4797 case OP_PSHUFLEW_HIGH:
4798 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4799 s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4801 case OP_PSHUFLEW_LOW:
4802 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4803 s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4806 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4807 s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
4810 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
4811 s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4814 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
4815 s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4819 s390x_addpd (code, ins->sreg1, ins->sreg2);
4822 s390x_divpd (code, ins->sreg1, ins->sreg2);
4825 s390x_mulpd (code, ins->sreg1, ins->sreg2);
4828 s390x_subpd (code, ins->sreg1, ins->sreg2);
4831 s390x_maxpd (code, ins->sreg1, ins->sreg2);
4834 s390x_minpd (code, ins->sreg1, ins->sreg2);
4837 g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
4838 s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
4841 s390x_andpd (code, ins->sreg1, ins->sreg2);
4844 s390x_andnpd (code, ins->sreg1, ins->sreg2);
4847 s390x_orpd (code, ins->sreg1, ins->sreg2);
4850 s390x_xorpd (code, ins->sreg1, ins->sreg2);
4853 s390x_sqrtpd (code, ins->dreg, ins->sreg1);
4856 s390x_addsubpd (code, ins->sreg1, ins->sreg2);
4859 s390x_haddpd (code, ins->sreg1, ins->sreg2);
4862 s390x_hsubpd (code, ins->sreg1, ins->sreg2);
4865 s390x_movddup (code, ins->dreg, ins->sreg1);
4868 case OP_EXTRACT_MASK:
4869 s390x_pmovmskb (code, ins->dreg, ins->sreg1);
4873 s390x_pand (code, ins->sreg1, ins->sreg2);
4876 s390x_por (code, ins->sreg1, ins->sreg2);
4879 s390x_pxor (code, ins->sreg1, ins->sreg2);
4883 s390x_paddb (code, ins->sreg1, ins->sreg2);
4886 s390x_paddw (code, ins->sreg1, ins->sreg2);
4889 s390x_paddd (code, ins->sreg1, ins->sreg2);
4892 s390x_paddq (code, ins->sreg1, ins->sreg2);
4896 s390x_psubb (code, ins->sreg1, ins->sreg2);
4899 s390x_psubw (code, ins->sreg1, ins->sreg2);
4902 s390x_psubd (code, ins->sreg1, ins->sreg2);
4905 s390x_psubq (code, ins->sreg1, ins->sreg2);
4909 s390x_pmaxub (code, ins->sreg1, ins->sreg2);
4912 s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
4915 s390x_pmaxud (code, ins->sreg1, ins->sreg2);
4919 s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
4922 s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
4925 s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
4929 s390x_pavgb (code, ins->sreg1, ins->sreg2);
4932 s390x_pavgw (code, ins->sreg1, ins->sreg2);
4936 s390x_pminub (code, ins->sreg1, ins->sreg2);
4939 s390x_pminuw (code, ins->sreg1, ins->sreg2);
4942 s390x_pminud (code, ins->sreg1, ins->sreg2);
4946 s390x_pminsb (code, ins->sreg1, ins->sreg2);
4949 s390x_pminsw (code, ins->sreg1, ins->sreg2);
4952 s390x_pminsd (code, ins->sreg1, ins->sreg2);
4956 s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
4959 s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
4962 s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
4965 s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
4969 s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
4972 s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
4975 s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
4978 s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
4981 case OP_PSUM_ABS_DIFF:
4982 s390x_psadbw (code, ins->sreg1, ins->sreg2);
4985 case OP_UNPACK_LOWB:
4986 s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
4988 case OP_UNPACK_LOWW:
4989 s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
4991 case OP_UNPACK_LOWD:
4992 s390x_punpckldq (code, ins->sreg1, ins->sreg2);
4994 case OP_UNPACK_LOWQ:
4995 s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
4997 case OP_UNPACK_LOWPS:
4998 s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5000 case OP_UNPACK_LOWPD:
5001 s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5004 case OP_UNPACK_HIGHB:
5005 s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5007 case OP_UNPACK_HIGHW:
5008 s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5010 case OP_UNPACK_HIGHD:
5011 s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5013 case OP_UNPACK_HIGHQ:
5014 s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5016 case OP_UNPACK_HIGHPS:
5017 s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5019 case OP_UNPACK_HIGHPD:
5020 s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5024 s390x_packsswb (code, ins->sreg1, ins->sreg2);
5027 s390x_packssdw (code, ins->sreg1, ins->sreg2);
5030 s390x_packuswb (code, ins->sreg1, ins->sreg2);
5033 s390x_packusdw (code, ins->sreg1, ins->sreg2);
5036 case OP_PADDB_SAT_UN:
5037 s390x_paddusb (code, ins->sreg1, ins->sreg2);
5039 case OP_PSUBB_SAT_UN:
5040 s390x_psubusb (code, ins->sreg1, ins->sreg2);
5042 case OP_PADDW_SAT_UN:
5043 s390x_paddusw (code, ins->sreg1, ins->sreg2);
5045 case OP_PSUBW_SAT_UN:
5046 s390x_psubusw (code, ins->sreg1, ins->sreg2);
5050 s390x_paddsb (code, ins->sreg1, ins->sreg2);
5053 s390x_psubsb (code, ins->sreg1, ins->sreg2);
5056 s390x_paddsw (code, ins->sreg1, ins->sreg2);
5059 s390x_psubsw (code, ins->sreg1, ins->sreg2);
5063 s390x_pmullw (code, ins->sreg1, ins->sreg2);
5066 s390x_pmulld (code, ins->sreg1, ins->sreg2);
5069 s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5071 case OP_PMULW_HIGH_UN:
5072 s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5075 s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5079 s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5082 s390x_psrlw (code, ins->dreg, ins->sreg2);
5086 s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5089 s390x_psraw (code, ins->dreg, ins->sreg2);
5093 s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5096 s390x_psllw (code, ins->dreg, ins->sreg2);
5100 s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5103 s390x_psrld (code, ins->dreg, ins->sreg2);
5107 s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5110 s390x_psrad (code, ins->dreg, ins->sreg2);
5114 s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5117 s390x_pslld (code, ins->dreg, ins->sreg2);
5121 s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5124 s390x_psrlq (code, ins->dreg, ins->sreg2);
5127 /*TODO: This is appart of the sse spec but not added
5129 s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5132 s390x_psraq (code, ins->dreg, ins->sreg2);
5137 s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5140 s390x_psllq (code, ins->dreg, ins->sreg2);
5143 s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5146 s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5149 s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5152 s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5155 s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5158 s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5161 s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5164 s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5168 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5171 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5175 amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5176 amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5178 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5183 amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5185 amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5186 amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5190 /*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5192 amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5193 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5194 amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5198 amd64_movhlps (code, ins->dreg, ins->sreg1);
5200 s390x_movsd (code, ins->dreg, ins->sreg1);
5203 s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5205 case OP_EXTRACTX_U2:
5206 s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5208 case OP_INSERTX_U1_SLOW:
5209 /*sreg1 is the extracted ireg (scratch)
5210 /sreg2 is the to be inserted ireg (scratch)
5211 /dreg is the xreg to receive the value*/
5213 /*clear the bits from the extracted word*/
5214 amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5215 /*shift the value to insert if needed*/
5216 if (ins->inst_c0 & 1)
5217 amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5218 /*join them together*/
5219 amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5220 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5222 case OP_INSERTX_I4_SLOW:
5223 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5224 amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5225 s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5227 case OP_INSERTX_I8_SLOW:
5228 amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5230 amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5232 s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5235 case OP_INSERTX_R4_SLOW:
5236 switch (ins->inst_c0) {
5239 s390x_movss (code, ins->dreg, ins->sreg2);
5241 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5244 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5246 s390x_movss (code, ins->dreg, ins->sreg2);
5248 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5249 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5252 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5254 s390x_movss (code, ins->dreg, ins->sreg2);
5256 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5257 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5260 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5262 s390x_movss (code, ins->dreg, ins->sreg2);
5264 s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5265 s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5269 case OP_INSERTX_R8_SLOW:
5271 amd64_movlhps (code, ins->dreg, ins->sreg2);
5273 s390x_movsd (code, ins->dreg, ins->sreg2);
5275 case OP_STOREX_MEMBASE_REG:
5276 case OP_STOREX_MEMBASE:
5277 s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5279 case OP_LOADX_MEMBASE:
5280 s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5282 case OP_LOADX_ALIGNED_MEMBASE:
5283 s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5285 case OP_STOREX_ALIGNED_MEMBASE_REG:
5286 s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5288 case OP_STOREX_NTA_MEMBASE_REG:
5289 s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5291 case OP_PREFETCH_MEMBASE:
5292 s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5296 /*FIXME the peephole pass should have killed this*/
5297 if (ins->dreg != ins->sreg1)
5298 s390x_movaps (code, ins->dreg, ins->sreg1);
5301 s390x_pxor (code, ins->dreg, ins->dreg);
5303 case OP_ICONV_TO_R4_RAW:
5304 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5307 case OP_FCONV_TO_R8_X:
5308 s390x_movsd (code, ins->dreg, ins->sreg1);
5311 case OP_XCONV_R8_TO_I4:
5312 s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5313 switch (ins->backend.source_opcode) {
5314 case OP_FCONV_TO_I1:
5315 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5317 case OP_FCONV_TO_U1:
5318 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5320 case OP_FCONV_TO_I2:
5321 amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5323 case OP_FCONV_TO_U2:
5324 amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5330 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5331 s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5332 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5335 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5336 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5339 amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5340 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5344 s390x_movsd (code, ins->dreg, ins->sreg1);
5346 s390x_movsd (code, ins->dreg, ins->sreg1);
5347 s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5349 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5352 s390x_movsd (code, ins->dreg, ins->sreg1);
5353 s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5357 g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5358 g_assert_not_reached ();
5361 if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5362 g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5363 mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5364 g_assert_not_reached ();
5367 last_offset = offset;
5370 cfg->code_len = code - cfg->native_code;
5373 /*========================= End of Function ========================*/
5375 /*------------------------------------------------------------------*/
5377 /* Name - mono_arch_register_lowlevel_calls */
5379 /* Function - Register routines to help with --trace operation. */
5381 /*------------------------------------------------------------------*/
5384 mono_arch_register_lowlevel_calls (void)
5388 /*========================= End of Function ========================*/
5390 /*------------------------------------------------------------------*/
5392 /* Name - mono_arch_patch_code */
5394 /* Function - Process the patch data created during the */
5395 /* instruction build process. This resolves jumps, */
5396 /* calls, variables etc. */
5398 /*------------------------------------------------------------------*/
5401 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5402 guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5405 MonoJumpInfo *patch_info;
5407 mono_error_init (error);
5409 for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5410 unsigned char *ip = patch_info->ip.i + code;
5411 gconstpointer target = NULL;
5413 target = mono_resolve_patch_target (method, domain, code,
5414 patch_info, run_cctors, error);
5415 return_if_nok (error);
5417 switch (patch_info->type) {
5418 case MONO_PATCH_INFO_IP:
5419 case MONO_PATCH_INFO_LDSTR:
5420 case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5421 case MONO_PATCH_INFO_LDTOKEN:
5422 case MONO_PATCH_INFO_EXC:
5423 s390_patch_addr (ip, (guint64) target);
5425 case MONO_PATCH_INFO_METHOD:
5426 case MONO_PATCH_INFO_INTERNAL_METHOD:
5427 case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5428 case MONO_PATCH_INFO_RGCTX_FETCH:
5429 case MONO_PATCH_INFO_ABS: {
5430 S390_EMIT_CALL (ip, target);
5433 case MONO_PATCH_INFO_SWITCH:
5434 /*----------------------------------*/
5435 /* ip points at the basr r13,0/j +4 */
5436 /* instruction the vtable value */
5437 /* follows this (i.e. ip+6) */
5438 /*----------------------------------*/
5439 S390_EMIT_LOAD (ip, target);
5441 case MONO_PATCH_INFO_METHODCONST:
5442 case MONO_PATCH_INFO_CLASS:
5443 case MONO_PATCH_INFO_IMAGE:
5444 case MONO_PATCH_INFO_FIELD:
5445 case MONO_PATCH_INFO_IID:
5446 case MONO_PATCH_INFO_EXC_NAME:
5447 target = S390_RELATIVE(target, ip);
5448 s390_patch_rel (ip, (guint64) target);
5450 case MONO_PATCH_INFO_R4:
5451 case MONO_PATCH_INFO_R8:
5452 case MONO_PATCH_INFO_METHOD_REL:
5453 g_assert_not_reached ();
5456 target = S390_RELATIVE(target, ip);
5458 s390_patch_rel (ip, (guint64) target);
5463 /*========================= End of Function ========================*/
5465 /*------------------------------------------------------------------*/
5467 /* Name - emit_load_volatile_arguments */
5469 /* Function - Emit the instructions to reload parameter regist- */
5470 /* registers for use with "tail" operations. */
5472 /* The register loading operations performed here */
5473 /* are the mirror of the store operations performed */
5474 /* in mono_arch_emit_prolog and need to be kept in */
5475 /* synchronization with it. */
5477 /*------------------------------------------------------------------*/
5480 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5483 MonoMethod *method = cfg->method;
5484 MonoMethodSignature *sig = mono_method_signature(method);
5488 cinfo = get_call_info (NULL, NULL, sig);
5490 if (cinfo->struct_ret) {
5491 ArgInfo *ainfo = &cinfo->ret;
5492 inst = cfg->vret_addr;
5493 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5496 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5497 ArgInfo *ainfo = cinfo->args + i;
5498 inst = cfg->args [pos];
5500 if (inst->opcode == OP_REGVAR) {
5501 if (ainfo->regtype == RegTypeGeneral)
5502 s390_lgr (code, ainfo->reg, inst->dreg);
5503 else if (ainfo->regtype == RegTypeFP) {
5504 if (inst->dreg != ainfo->reg) {
5505 if (ainfo->size == 4) {
5506 s390_ldebr (code, ainfo->reg, inst->dreg);
5508 s390_ldr (code, ainfo->reg, inst->dreg);
5512 else if (ainfo->regtype == RegTypeBase) {
5514 g_assert_not_reached ();
5516 if (ainfo->regtype == RegTypeGeneral) {
5517 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5518 g_assert_not_reached();
5519 switch (ainfo->size) {
5521 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5524 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5527 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5530 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5533 } else if (ainfo->regtype == RegTypeBase) {
5534 } else if (ainfo->regtype == RegTypeFP) {
5535 if (ainfo->size == 8)
5536 s390_ld (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5537 else if (ainfo->size == 4)
5538 s390_le (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5540 g_assert_not_reached ();
5541 } else if (ainfo->regtype == RegTypeStructByVal) {
5542 if (ainfo->reg != STK_BASE) {
5543 switch (ainfo->size) {
5545 s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5548 s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5551 s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5554 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5558 } else if (ainfo->regtype == RegTypeStructByAddr) {
5559 if (ainfo->reg != STK_BASE) {
5560 s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5563 g_assert_not_reached ();
5571 /*========================= End of Function ========================*/
5573 /*------------------------------------------------------------------*/
5575 /* Name - mono_arch_emit_prolog */
5577 /* Function - Create the instruction sequence for a function */
5580 /*------------------------------------------------------------------*/
5583 mono_arch_emit_prolog (MonoCompile *cfg)
5585 MonoMethod *method = cfg->method;
5587 MonoMethodSignature *sig;
5589 long alloc_size, pos, max_offset, i, cfa_offset = 0;
5598 cfg->code_size = 512;
5600 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5602 cfg->code_size += 256;
5603 } else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5604 cfg->code_size += 256;
5606 if (method->save_lmf)
5607 cfg->code_size += 200;
5609 cfg->native_code = code = g_malloc (cfg->code_size);
5611 mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
5612 emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
5613 s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
5614 mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
5615 mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
5617 if (cfg->arch.bkchain_reg != -1)
5618 s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
5620 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
5621 cfg->used_int_regs |= 1 << 11;
5624 alloc_size = cfg->stack_offset;
5626 cfg->stack_usage = cfa_offset = alloc_size;
5627 mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
5628 s390_lgr (code, s390_r11, STK_BASE);
5629 if (s390_is_imm16 (alloc_size)) {
5630 s390_aghi (code, STK_BASE, -alloc_size);
5631 } else if (s390_is_imm32 (alloc_size)) {
5632 s390_agfi (code, STK_BASE, -alloc_size);
5634 int stackSize = alloc_size;
5635 while (stackSize > INT_MAX) {
5636 s390_agfi (code, STK_BASE, -INT_MAX);
5637 stackSize -= INT_MAX;
5639 s390_agfi (code, STK_BASE, -stackSize);
5641 s390_stg (code, s390_r11, 0, STK_BASE, 0);
5643 if (cfg->frame_reg != STK_BASE)
5644 s390_lgr (code, s390_r11, STK_BASE);
5646 mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
5648 /* store runtime generic context */
5649 if (cfg->rgctx_var) {
5650 g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
5652 s390_stg (code, MONO_ARCH_RGCTX_REG, 0,
5653 cfg->rgctx_var->inst_basereg,
5654 cfg->rgctx_var->inst_offset);
5657 /* compute max_offset in order to use short forward jumps
5658 * we always do it on s390 because the immediate displacement
5659 * for jumps is too small
5662 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
5664 bb->max_offset = max_offset;
5666 if (cfg->prof_options & MONO_PROFILE_COVERAGE)
5669 MONO_BB_FOR_EACH_INS (bb, ins)
5670 max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
5673 /* load arguments allocated to register from the stack */
5674 sig = mono_method_signature (method);
5677 cinfo = get_call_info (cfg, cfg->mempool, sig);
5679 if (cinfo->struct_ret) {
5680 ArgInfo *ainfo = &cinfo->ret;
5681 inst = cfg->vret_addr;
5682 inst->backend.size = ainfo->vtsize;
5683 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5686 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5687 ArgInfo *ainfo = cinfo->args + i;
5688 inst = cfg->args [pos];
5690 if (inst->opcode == OP_VTARG_ADDR)
5691 inst = inst->inst_left;
5693 if (inst->opcode == OP_REGVAR) {
5694 if (ainfo->regtype == RegTypeGeneral)
5695 s390_lgr (code, inst->dreg, ainfo->reg);
5696 else if (ainfo->regtype == RegTypeFP) {
5697 if (inst->dreg != ainfo->reg) {
5698 if (ainfo->size == 4) {
5699 s390_ledbr (code, inst->dreg, ainfo->reg);
5701 s390_ldr (code, inst->dreg, ainfo->reg);
5705 else if (ainfo->regtype == RegTypeBase) {
5706 s390_lgr (code, s390_r13, STK_BASE);
5707 s390_aghi (code, s390_r13, alloc_size);
5708 s390_lg (code, inst->dreg, 0, s390_r13, ainfo->offset);
5710 g_assert_not_reached ();
5712 if (cfg->verbose_level > 2)
5713 g_print ("Argument %d assigned to register %s\n",
5714 pos, mono_arch_regname (inst->dreg));
5716 if (ainfo->regtype == RegTypeGeneral) {
5717 if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5718 g_assert_not_reached();
5719 switch (ainfo->size) {
5721 s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5724 s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5727 s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5730 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5733 } else if (ainfo->regtype == RegTypeBase) {
5734 } else if (ainfo->regtype == RegTypeFP) {
5735 if (ainfo->size == 8)
5736 s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5737 else if (ainfo->size == 4)
5738 s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5740 g_assert_not_reached ();
5741 } else if (ainfo->regtype == RegTypeStructByVal) {
5742 int doffset = inst->inst_offset;
5744 if (ainfo->reg != STK_BASE)
5748 s390_lgr (code, s390_r13, STK_BASE);
5749 s390_aghi (code, s390_r13, alloc_size);
5752 size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
5753 ? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
5758 if (ainfo->reg == STK_BASE)
5759 s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
5760 s390_stc (code, reg, 0, inst->inst_basereg, doffset);
5763 if (ainfo->reg == STK_BASE)
5764 s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
5765 s390_sth (code, reg, 0, inst->inst_basereg, doffset);
5768 if (ainfo->reg == STK_BASE)
5769 s390_l (code, reg, 0, s390_r13, ainfo->offset+4);
5770 s390_st (code, reg, 0, inst->inst_basereg, doffset);
5773 if (ainfo->reg == STK_BASE)
5774 s390_lg (code, reg, 0, s390_r13, ainfo->offset);
5775 s390_stg (code, reg, 0, inst->inst_basereg, doffset);
5778 } else if (ainfo->regtype == RegTypeStructByAddr) {
5779 s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5780 } else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
5782 g_assert_not_reached ();
5787 if (method->save_lmf) {
5788 /*---------------------------------------------------------------*/
5789 /* build the MonoLMF structure on the stack - see mini-s390x.h */
5790 /*---------------------------------------------------------------*/
5791 lmfOffset = alloc_size - sizeof(MonoLMF);
5793 s390_lgr (code, s390_r13, cfg->frame_reg);
5794 s390_aghi (code, s390_r13, lmfOffset);
5796 /*---------------------------------------------------------------*/
5797 /* Preserve the parameter registers while we fix up the lmf */
5798 /*---------------------------------------------------------------*/
5799 s390_stmg (code, s390_r2, s390_r6, s390_r13,
5800 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5802 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
5803 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
5804 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
5805 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
5806 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
5808 /*---------------------------------------------------------------*/
5809 /* On return from this call r2 have the address of the &lmf */
5810 /*---------------------------------------------------------------*/
5811 if (lmf_addr_tls_offset == -1) {
5812 mono_add_patch_info (cfg, code - cfg->native_code,
5813 MONO_PATCH_INFO_INTERNAL_METHOD,
5814 (gpointer)"mono_get_lmf_addr");
5815 S390_CALL_TEMPLATE(code, s390_r1);
5817 /*-------------------------------------------------------*/
5818 /* Get LMF by getting value from thread level storage */
5819 /*-------------------------------------------------------*/
5820 s390_ear (code, s390_r1, 0);
5821 s390_sllg(code, s390_r1, s390_r1, 0, 32);
5822 s390_ear (code, s390_r1, 1);
5823 s390_lg (code, s390_r2, 0, s390_r1, lmf_addr_tls_offset);
5826 /*---------------------------------------------------------------*/
5827 /* Set lmf.lmf_addr = jit_tls->lmf */
5828 /*---------------------------------------------------------------*/
5829 s390_stg (code, s390_r2, 0, s390_r13,
5830 G_STRUCT_OFFSET(MonoLMF, lmf_addr));
5831 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
5833 /*---------------------------------------------------------------*/
5834 /* Get current lmf */
5835 /*---------------------------------------------------------------*/
5836 s390_lg (code, s390_r0, 0, s390_r2, 0);
5838 /*---------------------------------------------------------------*/
5839 /* Set our lmf as the current lmf */
5840 /*---------------------------------------------------------------*/
5841 s390_stg (code, s390_r13, 0, s390_r2, 0);
5843 /*---------------------------------------------------------------*/
5844 /* Have our lmf.previous_lmf point to the last lmf */
5845 /*---------------------------------------------------------------*/
5846 s390_stg (code, s390_r0, 0, s390_r13,
5847 G_STRUCT_OFFSET(MonoLMF, previous_lmf));
5848 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
5850 /*---------------------------------------------------------------*/
5851 /* save method info */
5852 /*---------------------------------------------------------------*/
5853 S390_SET (code, s390_r1, method);
5854 s390_stg (code, s390_r1, 0, s390_r13,
5855 G_STRUCT_OFFSET(MonoLMF, method));
5856 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
5858 /*---------------------------------------------------------------*/
5859 /* save the current IP */
5860 /*---------------------------------------------------------------*/
5861 s390_stg (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
5862 s390_basr (code, s390_r1, 0);
5863 s390_stg (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
5864 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
5865 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
5867 /*---------------------------------------------------------------*/
5868 /* Save general and floating point registers */
5869 /*---------------------------------------------------------------*/
5870 s390_stmg (code, s390_r2, s390_r12, s390_r13,
5871 G_STRUCT_OFFSET(MonoLMF, gregs[2]));
5872 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
5873 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
5874 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
5875 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
5876 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
5877 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
5878 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
5879 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
5880 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
5881 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
5882 mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
5884 fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
5885 for (i = 0; i < 16; i++) {
5886 s390_std (code, i, 0, s390_r13,
5887 G_STRUCT_OFFSET(MonoLMF, fregs[i]));
5888 mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
5889 fpOffset += sizeof(double);
5892 /*---------------------------------------------------------------*/
5893 /* Restore the parameter registers now that we've set up the lmf */
5894 /*---------------------------------------------------------------*/
5895 s390_lmg (code, s390_r2, s390_r6, s390_r13,
5896 G_STRUCT_OFFSET(MonoLMF, pregs[0]));
5899 if (cfg->method->save_lmf)
5900 argsClobbered = TRUE;
5903 argsClobbered = TRUE;
5904 code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
5907 if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
5908 argsClobbered = TRUE;
5911 * Optimize the common case of the first bblock making a call with the same
5912 * arguments as the method. This works because the arguments are still in their
5913 * original argument registers.
5915 if (!argsClobbered) {
5916 MonoBasicBlock *first_bb = cfg->bb_entry;
5918 int filter = FILTER_IL_SEQ_POINT;
5920 next = mono_bb_first_inst (first_bb, filter);
5921 if (!next && first_bb->next_bb) {
5922 first_bb = first_bb->next_bb;
5923 next = mono_bb_first_inst (first_bb, filter);
5926 if (first_bb->in_count > 1)
5929 for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
5930 ArgInfo *ainfo = cinfo->args + i;
5931 gboolean match = FALSE;
5933 inst = cfg->args [i];
5934 if (inst->opcode != OP_REGVAR) {
5935 switch (ainfo->regtype) {
5936 case RegTypeGeneral: {
5937 if (((next->opcode == OP_LOAD_MEMBASE) ||
5938 (next->opcode == OP_LOADI4_MEMBASE)) &&
5939 next->inst_basereg == inst->inst_basereg &&
5940 next->inst_offset == inst->inst_offset) {
5941 if (next->dreg == ainfo->reg) {
5945 next->opcode = OP_MOVE;
5946 next->sreg1 = ainfo->reg;
5947 /* Only continue if the instruction doesn't change argument regs */
5948 if (next->dreg == ainfo->reg)
5958 /* Argument allocated to (non-volatile) register */
5959 switch (ainfo->regtype) {
5960 case RegTypeGeneral:
5961 if (next->opcode == OP_MOVE &&
5962 next->sreg1 == inst->dreg &&
5963 next->dreg == ainfo->reg) {
5974 next = mono_inst_next (next, filter);
5981 cfg->code_len = code - cfg->native_code;
5982 g_assert (cfg->code_len < cfg->code_size);
5987 /*========================= End of Function ========================*/
5989 /*------------------------------------------------------------------*/
5991 /* Name - mono_arch_emit_epilog */
5993 /* Function - Emit the instructions for a function epilog. */
5995 /*------------------------------------------------------------------*/
5998 mono_arch_emit_epilog (MonoCompile *cfg)
6000 MonoMethod *method = cfg->method;
6003 int max_epilog_size = 96;
6005 if (cfg->method->save_lmf)
6006 max_epilog_size += 128;
6008 if (mono_jit_trace_calls != NULL)
6009 max_epilog_size += 128;
6010 else if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE)
6011 max_epilog_size += 128;
6013 while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6014 cfg->code_size *= 2;
6015 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6016 cfg->stat_code_reallocs++;
6019 code = cfg->native_code + cfg->code_len;
6021 if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6022 code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6026 if (method->save_lmf)
6027 restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6029 if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6030 s390_lg (code, STK_BASE, 0, STK_BASE, 0);
6032 code = backUpStackPtr(cfg, code);
6034 s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6035 s390_br (code, s390_r14);
6037 cfg->code_len = code - cfg->native_code;
6039 g_assert (cfg->code_len < cfg->code_size);
6043 /*========================= End of Function ========================*/
6045 /*------------------------------------------------------------------*/
6047 /* Name - mono_arch_emit_exceptions */
6049 /* Function - Emit the blocks to handle exception conditions. */
6051 /*------------------------------------------------------------------*/
6054 mono_arch_emit_exceptions (MonoCompile *cfg)
6056 MonoJumpInfo *patch_info;
6062 MonoClass *exc_classes [MAX_EXC];
6063 guint8 *exc_throw_start [MAX_EXC];
6065 for (patch_info = cfg->patch_info;
6067 patch_info = patch_info->next) {
6068 if (patch_info->type == MONO_PATCH_INFO_EXC)
6072 code_size = exc_count * 48;
6074 while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6075 cfg->code_size *= 2;
6076 cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6077 cfg->stat_code_reallocs++;
6080 code = cfg->native_code + cfg->code_len;
6082 /*---------------------------------------------------------------------*/
6083 /* Add code to raise exceptions */
6084 /*---------------------------------------------------------------------*/
6085 for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6086 switch (patch_info->type) {
6087 case MONO_PATCH_INFO_EXC: {
6088 guint8 *ip = patch_info->ip.i + cfg->native_code;
6089 MonoClass *exc_class;
6092 /*-----------------------------------------------------*/
6093 /* Patch the branch in epilog to come here */
6094 /*-----------------------------------------------------*/
6095 s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6097 exc_class = mono_class_load_from_name (mono_defaults.corlib,
6099 patch_info->data.name);
6100 throw_ip = patch_info->ip.i;
6102 for (iExc = 0; iExc < nThrows; ++iExc)
6103 if (exc_classes [iExc] == exc_class)
6106 if (iExc < nThrows) {
6107 s390_jcl (code, S390_CC_UN,
6108 (guint64) exc_throw_start [iExc]);
6109 patch_info->type = MONO_PATCH_INFO_NONE;
6112 if (nThrows < MAX_EXC) {
6113 exc_classes [nThrows] = exc_class;
6114 exc_throw_start [nThrows] = code;
6117 /*---------------------------------------------*/
6118 /* Patch the parameter passed to the handler */
6119 /*---------------------------------------------*/
6120 S390_SET (code, s390_r2, exc_class->type_token);
6121 /*---------------------------------------------*/
6122 /* Load return address & parameter register */
6123 /*---------------------------------------------*/
6124 s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6125 cfg->native_code + 8), code));
6126 /*---------------------------------------------*/
6127 /* Reuse the current patch to set the jump */
6128 /*---------------------------------------------*/
6129 patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
6130 patch_info->data.name = "mono_arch_throw_corlib_exception";
6131 patch_info->ip.i = code - cfg->native_code;
6132 S390_BR_TEMPLATE (code, s390_r1);
6142 cfg->code_len = code - cfg->native_code;
6144 g_assert (cfg->code_len < cfg->code_size);
6148 /*========================= End of Function ========================*/
6150 /*------------------------------------------------------------------*/
6152 /* Name - mono_arch_finish_init */
6154 /* Function - Setup the JIT's Thread Level Specific Data. */
6156 /*------------------------------------------------------------------*/
6159 mono_arch_finish_init (void)
6161 appdomain_tls_offset = mono_domain_get_tls_offset();
6162 lmf_tls_offset = mono_get_lmf_tls_offset();
6163 lmf_addr_tls_offset = mono_get_lmf_addr_tls_offset();
6166 /*========================= End of Function ========================*/
6168 /*------------------------------------------------------------------*/
6170 /* Name - mono_arch_free_jit_tls_data */
6172 /* Function - Free tls data. */
6174 /*------------------------------------------------------------------*/
6177 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6181 /*========================= End of Function ========================*/
6183 /*------------------------------------------------------------------*/
6185 /* Name - mono_arch_emit_inst_for_method */
6187 /*------------------------------------------------------------------*/
6190 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6195 /*========================= End of Function ========================*/
6197 /*------------------------------------------------------------------*/
6199 /* Name - mono_arch_decompose_opts */
6201 /* Function - Decompose opcode into a System z opcode. */
6203 /*------------------------------------------------------------------*/
6206 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6209 * Have to rename these to avoid being decomposed normally, since the normal
6210 * decomposition does not work on S390.
6212 switch (ins->opcode) {
6214 ins->opcode = OP_S390_ISUB_OVF;
6216 case OP_ISUB_OVF_UN:
6217 ins->opcode = OP_S390_ISUB_OVF_UN;
6220 ins->opcode = OP_S390_IADD_OVF;
6222 case OP_IADD_OVF_UN:
6223 ins->opcode = OP_S390_IADD_OVF_UN;
6226 ins->opcode = OP_S390_LADD_OVF;
6228 case OP_LADD_OVF_UN:
6229 ins->opcode = OP_S390_LADD_OVF_UN;
6232 ins->opcode = OP_S390_LSUB_OVF;
6234 case OP_LSUB_OVF_UN:
6235 ins->opcode = OP_S390_LSUB_OVF_UN;
6242 /*========================= End of Function ========================*/
6244 /*------------------------------------------------------------------*/
6246 /* Name - mono_arch_print_tree */
6248 /* Function - Print platform-specific opcode details. */
6250 /* Returns - 1 - opcode details have been printed */
6251 /* 0 - opcode details have not been printed */
6253 /*------------------------------------------------------------------*/
6256 mono_arch_print_tree (MonoInst *tree, int arity)
6260 switch (tree->opcode) {
6261 case OP_S390_LOADARG:
6262 case OP_S390_ARGREG:
6263 case OP_S390_ARGPTR:
6264 printf ("[0x%lx(%s)]", tree->inst_offset,
6265 mono_arch_regname (tree->inst_basereg));
6268 case OP_S390_STKARG:
6269 printf ("[0x%lx(previous_frame)]",
6274 printf ("[0x%lx(%d,%s),0x%lx(%s)]",
6275 tree->inst_offset, tree->backend.size,
6276 mono_arch_regname(tree->dreg),
6278 mono_arch_regname(tree->sreg1));
6281 case OP_S390_SETF4RET:
6282 printf ("[f%s,f%s]",
6283 mono_arch_regname (tree->dreg),
6284 mono_arch_regname (tree->sreg1));
6288 printf ("[0x%lx(0x%lx,%s)]", tree->inst_offset,
6290 mono_arch_regname (tree->sreg1));
6293 case OP_S390_BKCHAIN:
6294 printf ("[previous_frame(%s)]",
6295 mono_arch_regname (tree->sreg1));
6303 /*========================= End of Function ========================*/
6305 /*------------------------------------------------------------------*/
6307 /* Name - mono_arch_regalloc_cost */
6309 /* Function - Determine the cost, in the number of memory */
6310 /* references, of the action of allocating the var- */
6311 /* iable VMV into a register during global register */
6314 /* Returns - Cost */
6316 /*------------------------------------------------------------------*/
6319 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6325 /*========================= End of Function ========================*/
6327 /*------------------------------------------------------------------*/
6329 /* Name - mono_arch_flush_register_windows */
6335 /*------------------------------------------------------------------*/
6338 mono_arch_flush_register_windows (void)
6342 /*========================= End of Function ========================*/
6344 /*------------------------------------------------------------------*/
6346 /* Name - mono_arch_is_inst_imm */
6348 /* Function - Determine if operand qualifies as an immediate */
6349 /* value. For s390 this is a value -32768-32768 */
6351 /* Returns - True|False - is [not] immediate value. */
6353 /*------------------------------------------------------------------*/
6356 mono_arch_is_inst_imm (gint64 imm)
6358 return s390_is_imm32 (imm);
6361 /*========================= End of Function ========================*/
6363 /*------------------------------------------------------------------*/
6365 /* Name - mono_arch_get_patch_offset */
6367 /* Function - Dummy entry point until s390x supports aot. */
6369 /* Returns - Offset for patch. */
6371 /*------------------------------------------------------------------*/
6374 mono_arch_get_patch_offset (guint8 *code)
6379 /*========================= End of Function ========================*/
6381 /*------------------------------------------------------------------*/
6383 /* Name - mono_arch_context_get_int_reg. */
6387 /* Returns - Return a register from the context. */
6389 /*------------------------------------------------------------------*/
6392 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6394 return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6397 /*========================= End of Function ========================*/
6399 /*------------------------------------------------------------------*/
6401 /* Name - mono_arch_context_set_int_reg. */
6403 /* Function - Set a value in a specified register. */
6405 /*------------------------------------------------------------------*/
6408 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6410 ctx->uc_mcontext.gregs[reg] = val;
6413 /*========================= End of Function ========================*/
6415 /*------------------------------------------------------------------*/
6417 /* Name - mono_arch_get_this_arg_from_call. */
6421 /*------------------------------------------------------------------*/
6424 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6426 return (gpointer) regs [s390_r2];
6429 /*========================= End of Function ========================*/
6431 /*------------------------------------------------------------------*/
6433 /* Name - mono_arch_install_handler_block_guard */
6437 /*------------------------------------------------------------------*/
6440 mono_arch_install_handler_block_guard (MonoJitInfo *ji, MonoJitExceptionInfo *clause,
6441 MonoContext *ctx, gpointer new_value)
6444 gpointer *sp, old_value;
6447 offset = clause->exvar_offset;
6450 bp = MONO_CONTEXT_GET_BP (ctx);
6451 sp = *(gpointer*)(bp + offset);
6454 if (old_value < ji->code_start || (char*)old_value > ((char*)ji->code_start + ji->code_size))
6462 /*========================= End of Function ========================*/
6464 /*------------------------------------------------------------------*/
6466 /* Name - get_delegate_invoke_impl. */
6470 /*------------------------------------------------------------------*/
6473 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6475 guint8 *code, *start;
6480 start = code = mono_global_codeman_reserve (size);
6482 /* Replace the this argument with the target */
6483 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6484 s390_lg (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6485 s390_br (code, s390_r1);
6486 g_assert ((code - start) <= size);
6488 mono_arch_flush_icache (start, size);
6492 size = 32 + param_count * 8;
6493 start = code = mono_global_codeman_reserve (size);
6495 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6496 /* slide down the arguments */
6497 for (i = 0; i < param_count; ++i) {
6498 s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6500 s390_br (code, s390_r1);
6502 g_assert ((code - start) <= size);
6504 mono_arch_flush_icache (start, size);
6507 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL);
6510 *info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6512 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6513 *info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6520 /*========================= End of Function ========================*/
6522 /*------------------------------------------------------------------*/
6524 /* Name - mono_arch_get_delegate_invoke_impls. */
6528 /*------------------------------------------------------------------*/
6531 mono_arch_get_delegate_invoke_impls (void)
6534 MonoTrampInfo *info;
6537 get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6538 res = g_slist_prepend (res, info);
6540 for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6541 get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6542 res = g_slist_prepend (res, info);
6548 /*========================= End of Function ========================*/
6550 /*------------------------------------------------------------------*/
6552 /* Name - mono_arch_get_delegate_invoke_impl. */
6556 /*------------------------------------------------------------------*/
6559 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6561 guint8 *code, *start;
6563 /* FIXME: Support more cases */
6564 if (MONO_TYPE_ISSTRUCT (sig->ret))
6568 static guint8* cached = NULL;
6573 if (mono_aot_only) {
6574 start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6576 MonoTrampInfo *info;
6577 start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6578 mono_tramp_info_register (info, NULL);
6581 mono_memory_barrier ();
6585 static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6588 if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6590 for (i = 0; i < sig->param_count; ++i)
6591 if (!mono_is_regsize_var (sig->params [i]))
6595 code = cache [sig->param_count];
6599 if (mono_aot_only) {
6600 char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6601 start = mono_aot_get_trampoline (name);
6604 MonoTrampInfo *info;
6605 start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6606 mono_tramp_info_register (info, NULL);
6609 mono_memory_barrier ();
6611 cache [sig->param_count] = start;
6616 /*========================= End of Function ========================*/
6618 /*------------------------------------------------------------------*/
6620 /* Name - mono_arch_get_delegate_virtual_invoke_impl. */
6624 /*------------------------------------------------------------------*/
6627 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6628 int offset, gboolean load_imt_reg)
6630 guint8 *code, *start;
6633 start = code = mono_global_codeman_reserve (size);
6636 * Replace the "this" argument with the target
6638 s390_lgr (code, s390_r1, s390_r2);
6639 s390_lg (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6642 * Load the IMT register, if needed
6645 s390_lg (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6651 s390_lg (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6653 s390_agfi(code, s390_r1, offset);
6655 s390_lg (code, s390_r1, 0, s390_r1, 0);
6656 s390_br (code, s390_r1);
6661 /*========================= End of Function ========================*/
6663 /*------------------------------------------------------------------*/
6665 /* Name - mono_arch_build_imt_thunk. */
6669 /*------------------------------------------------------------------*/
6672 mono_arch_build_imt_thunk (MonoVTable *vtable, MonoDomain *domain,
6673 MonoIMTCheckItem **imt_entries, int count,
6674 gpointer fail_tramp)
6678 guchar *code, *start;
6681 for (i = 0; i < count; ++i) {
6682 MonoIMTCheckItem *item = imt_entries [i];
6683 if (item->is_equals) {
6684 if (item->check_target_idx) {
6685 if (!item->compare_done)
6686 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6687 if (item->has_target_code)
6688 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6690 item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6694 item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6696 if (!item->has_target_code)
6697 item->chunk_size += LOAD_SIZE;
6699 item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6700 #if ENABLE_WRONG_METHOD_CHECK
6701 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6706 item->chunk_size += CMP_SIZE + JUMP_SIZE;
6707 imt_entries [item->check_target_idx]->compare_done = TRUE;
6709 size += item->chunk_size;
6713 code = mono_method_alloc_generic_virtual_thunk (domain, size);
6715 code = mono_domain_code_reserve (domain, size);
6719 for (i = 0; i < count; ++i) {
6720 MonoIMTCheckItem *item = imt_entries [i];
6721 item->code_target = (guint8 *) code;
6722 if (item->is_equals) {
6723 if (item->check_target_idx) {
6724 if (!item->compare_done) {
6725 S390_SET (code, s390_r0, item->key);
6726 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6728 item->jmp_code = (guint8*) code;
6729 s390_jcl (code, S390_CC_NE, 0);
6731 if (item->has_target_code) {
6732 S390_SET (code, s390_r1, item->value.target_code);
6734 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6735 s390_lg (code, s390_r1, 0, s390_r1, 0);
6737 s390_br (code, s390_r1);
6742 S390_SET (code, s390_r0, item->key);
6743 s390_cgr (code, s390_r0, MONO_ARCH_IMT_REG);
6744 item->jmp_code = (guint8*) code;
6745 s390_jcl (code, S390_CC_NE, 0);
6746 if (item->has_target_code) {
6747 S390_SET (code, s390_r1, item->value.target_code);
6750 S390_SET (code, s390_r1,
6751 (&(vtable->vtable [item->value.vtable_slot])));
6752 s390_lg (code, s390_r1, 0, s390_r1, 0);
6754 s390_br (code, s390_r1);
6755 target = (gint64) S390_RELATIVE(code, item->jmp_code);
6756 s390_patch_rel(item->jmp_code+2, target);
6757 S390_SET (code, s390_r1, fail_tramp);
6758 s390_br (code, s390_r1);
6759 item->jmp_code = NULL;
6761 /* enable the commented code to assert on wrong method */
6762 #if ENABLE_WRONG_METHOD_CHECK
6763 g_assert_not_reached ();
6765 S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
6766 s390_lg (code, s390_r1, 0, s390_r1, 0);
6767 s390_br (code, s390_r1);
6771 S390_SET (code, s390_r0, item->key);
6772 s390_cgr (code, MONO_ARCH_IMT_REG, s390_r0);
6773 item->jmp_code = (guint8 *) code;
6774 s390_jcl (code, S390_CC_GE, 0);
6778 * patch the branches to get to the target items
6780 for (i = 0; i < count; ++i) {
6781 MonoIMTCheckItem *item = imt_entries [i];
6782 if (item->jmp_code) {
6783 if (item->check_target_idx) {
6785 offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
6787 s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
6792 mono_arch_flush_icache ((guint8*)start, (code - start));
6793 mono_profiler_code_buffer_new (start, code - start, MONO_PROFILER_CODE_BUFFER_IMT_TRAMPOLINE, NULL);
6796 mono_stats.imt_thunks_size += (code - start);
6798 g_assert (code - start <= size);
6800 snprintf(trampName, sizeof(trampName), "%d_imt_thunk_trampoline", domain->domain_id);
6801 mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
6806 /*========================= End of Function ========================*/
6808 /*------------------------------------------------------------------*/
6810 /* Name - mono_arch_find_imt_method. */
6812 /* Function - Get the method address from MONO_ARCH_IMT_REG */
6813 /* found in the save area. */
6815 /*------------------------------------------------------------------*/
6818 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
6820 return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
6823 /*========================= End of Function ========================*/
6825 /*------------------------------------------------------------------*/
6827 /* Name - mono_arch_find_static_call_vtable */
6829 /* Function - Find the static call vtable. */
6831 /*------------------------------------------------------------------*/
6834 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
6836 mgreg_t *r = (mgreg_t*)regs;
6838 return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
6841 /*========================= End of Function ========================*/
6843 /*------------------------------------------------------------------*/
6845 /* Name - mono_arch_get_cie_program */
6847 /* Function - Find the static call vtable. */
6849 /*------------------------------------------------------------------*/
6852 mono_arch_get_cie_program (void)
6856 mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
6861 /*========================= End of Function ========================*/
6863 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
6865 /*------------------------------------------------------------------*/
6867 /* Name - mono_arch_set_breakpoint. */
6869 /* Function - Set a breakpoint at the native code corresponding */
6870 /* to JI at NATIVE_OFFSET. The location should */
6871 /* contain code emitted by OP_SEQ_POINT. */
6873 /*------------------------------------------------------------------*/
6876 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
6880 breakpointCode.pTrigger = bp_trigger_page;
6881 memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
6882 code += BREAKPOINT_SIZE;
6885 /*========================= End of Function ========================*/
6887 /*------------------------------------------------------------------*/
6889 /* Name - mono_arch_clear_breakpoint. */
6891 /* Function - Clear the breakpoint at IP. */
6893 /*------------------------------------------------------------------*/
6896 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
6901 for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
6905 /*========================= End of Function ========================*/
6907 /*------------------------------------------------------------------*/
6909 /* Name - mono_arch_is_breakpoint_event. */
6913 /*------------------------------------------------------------------*/
6916 mono_arch_is_breakpoint_event (void *info, void *sigctx)
6918 siginfo_t* sinfo = (siginfo_t*) info;
6921 * Sometimes the address is off by 4
6923 if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
6929 /*========================= End of Function ========================*/
6931 /*------------------------------------------------------------------*/
6933 /* Name - mono_arch_skip_breakpoint. */
6935 /* Function - Modify the CTX so the IP is placed after the */
6936 /* breakpoint instruction, so when we resume, the */
6937 /* instruction is not executed again. */
6939 /*------------------------------------------------------------------*/
6942 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
6944 MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
6947 /*========================= End of Function ========================*/
6949 /*------------------------------------------------------------------*/
6951 /* Name - mono_arch_start_single_stepping. */
6953 /* Function - Start single stepping. */
6955 /*------------------------------------------------------------------*/
6958 mono_arch_start_single_stepping (void)
6960 mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
6963 /*========================= End of Function ========================*/
6965 /*------------------------------------------------------------------*/
6967 /* Name - mono_arch_stop_single_stepping. */
6969 /* Function - Stop single stepping. */
6971 /*------------------------------------------------------------------*/
6974 mono_arch_stop_single_stepping (void)
6976 mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
6979 /*========================= End of Function ========================*/
6981 /*------------------------------------------------------------------*/
6983 /* Name - mono_arch_is_single_step_event. */
6985 /* Function - Return whether the machine state in sigctx cor- */
6986 /* responds to a single step event. */
6988 /*------------------------------------------------------------------*/
6991 mono_arch_is_single_step_event (void *info, void *sigctx)
6993 siginfo_t* sinfo = (siginfo_t*) info;
6996 * Sometimes the address is off by 4
6998 if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7004 /*========================= End of Function ========================*/
7006 /*------------------------------------------------------------------*/
7008 /* Name - mono_arch_skip_single_step. */
7010 /* Function - Modify the ctx so the IP is placed after the */
7011 /* single step trigger instruction, so that the */
7012 /* instruction is not executed again. */
7014 /*------------------------------------------------------------------*/
7017 mono_arch_skip_single_step (MonoContext *ctx)
7019 MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7022 /*========================= End of Function ========================*/
7024 /*------------------------------------------------------------------*/
7026 /* Name - mono_arch_create_seq_point_info. */
7028 /* Function - Return a pointer to a data struction which is */
7029 /* used by the sequence point implementation in */
7032 /*------------------------------------------------------------------*/
7035 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7041 /*========================= End of Function ========================*/
7043 /*------------------------------------------------------------------*/
7045 /* Name - mono_arch_init_lmf_ext. */
7049 /*------------------------------------------------------------------*/
7052 mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
7054 ext->lmf.previous_lmf = prev_lmf;
7055 /* Mark that this is a MonoLMFExt */
7056 ext->lmf.previous_lmf = (gpointer)(((gssize)ext->lmf.previous_lmf) | 2);
7057 ext->lmf.ebp = (gssize)ext;
7060 /*========================= End of Function ========================*/
7064 /*------------------------------------------------------------------*/
7066 /* Name - mono_arch_cpu_enumerate_simd_versions. */
7068 /* Function - If this CPU supports vector operations then it */
7069 /* supports the equivalent of SSE1-4. */
7071 /*------------------------------------------------------------------*/
7074 mono_arch_cpu_enumerate_simd_versions (void)
7076 guint32 sseOpts = 0;
7078 if (mono_hwcap_s390x_has_vec)
7079 sseOpts = (SIMD_VERSION_SSE1 | SIMD_VERSION_SSE2 |
7080 SIMD_VERSION_SSE3 | SIMD_VERSION_SSSE3 |
7081 SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7082 SIMD_VERSION_SSE4a);
7087 /*========================= End of Function ========================*/
7089 /*------------------------------------------------------------------*/
7091 /* Name - mono_arch_opcode_supported. */
7093 /* Function - Check if a given return code is supported. */
7095 /*------------------------------------------------------------------*/
7098 mono_arch_opcode_supported (int opcode)
7101 case OP_ATOMIC_ADD_I4:
7102 case OP_ATOMIC_ADD_I8:
7103 case OP_ATOMIC_EXCHANGE_I4:
7104 case OP_ATOMIC_EXCHANGE_I8:
7111 /*========================= End of Function ========================*/