1 /**
2  * \file
3  * Function    - S/390 backend for the Mono code generator.
4  *
5  * Name	       - Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
6  *
7  * Date        - January, 2004
8  *
9  * Derivation  - From mini-x86 & mini-ppc by -
10  * 	         Paolo Molaro (lupus@ximian.com)
11  * 		 Dietmar Maurer (dietmar@ximian.com)
12  *
13  */
14 
15 /*------------------------------------------------------------------*/
16 /*                 D e f i n e s                                    */
17 /*------------------------------------------------------------------*/
18 
19 #define MAX_ARCH_DELEGATE_PARAMS 7
20 
21 #define EMIT_COND_BRANCH(ins,cond) 						\
22 {										\
23 if (ins->inst_true_bb->native_offset) { 					\
24 	int displace;								\
25 	displace = ((cfg->native_code + 					\
26 		    ins->inst_true_bb->native_offset) - code) / 2;		\
27 	if (s390_is_imm16(displace)) {						\
28 		s390_brc (code, cond, displace);				\
29 	} else { 								\
30 		s390_jcl (code, cond, displace); 				\
31 	}									\
32 } else { 									\
33 	mono_add_patch_info (cfg, code - cfg->native_code, 			\
34 			     MONO_PATCH_INFO_BB, ins->inst_true_bb); 		\
35 	s390_jcl (code, cond, 0);						\
36 } 										\
37 }
38 
39 #define EMIT_UNCOND_BRANCH(ins) 						\
40 {										\
41 if (ins->inst_target_bb->native_offset) { 					\
42 	int displace;								\
43 	displace = ((cfg->native_code + 					\
44 		    ins->inst_target_bb->native_offset) - code) / 2;		\
45 	if (s390_is_imm16(displace)) {						\
46 		s390_brc (code, S390_CC_UN, displace);				\
47 	} else { 								\
48 		s390_jcl (code, S390_CC_UN, displace); 				\
49 	}									\
50 } else { 									\
51 	mono_add_patch_info (cfg, code - cfg->native_code, 			\
52 			     MONO_PATCH_INFO_BB, ins->inst_target_bb); 		\
53 	s390_jcl (code, S390_CC_UN, 0);						\
54 } 										\
55 }
56 
57 #define EMIT_COND_SYSTEM_EXCEPTION(cond,exc_name)            		\
58         do {                                                        	\
59 		mono_add_patch_info (cfg, code - cfg->native_code,   	\
60 				     MONO_PATCH_INFO_EXC, exc_name);  	\
61 		s390_jcl (code, cond, 0);				\
62 	} while (0);
63 
64 #define EMIT_COMP_AND_BRANCH(ins, cab, cmp)					\
65 {										\
66 if (ins->inst_true_bb->native_offset) { 					\
67 	int displace;								\
68 	displace = ((cfg->native_code + 					\
69 		    ins->inst_true_bb->native_offset) - code) / 2;		\
70 	if (s390_is_imm16(displace)) {						\
71 		s390_##cab (code, ins->sreg1, ins->sreg2, 			\
72 			    ins->sreg3, displace);				\
73 	} else { 								\
74 		s390_##cmp (code, ins->sreg1, ins->sreg2);			\
75 		displace = ((cfg->native_code + 				\
76 			    ins->inst_true_bb->native_offset) - code) / 2;	\
77 		s390_jcl (code, ins->sreg3, displace); 				\
78 	}									\
79 } else { 									\
80 	s390_##cmp (code, ins->sreg1, ins->sreg2);				\
81 	mono_add_patch_info (cfg, code - cfg->native_code, 			\
82 			     MONO_PATCH_INFO_BB, ins->inst_true_bb); 		\
83 	s390_jcl (code, ins->sreg3, 0);						\
84 } 										\
85 }
86 
87 #define EMIT_COMP_AND_BRANCH_IMM(ins, cab, cmp, lat, logical)			\
88 {										\
89 if (ins->inst_true_bb->native_offset) { 					\
90 	int displace;								\
91 	if ((ins->backend.data == 0) && (!logical)) {				\
92 		s390_##lat (code, ins->sreg1, ins->sreg1);			\
93 		displace = ((cfg->native_code + 				\
94 			    ins->inst_true_bb->native_offset) - code) / 2;	\
95 		if (s390_is_imm16(displace)) {					\
96 			s390_brc (code, ins->sreg3, displace); 			\
97 		} else {							\
98 			s390_jcl (code, ins->sreg3, displace); 			\
99 		}								\
100 	} else { 								\
101 		S390_SET (code, s390_r0, ins->backend.data);			\
102 		displace = ((cfg->native_code + 				\
103 			    ins->inst_true_bb->native_offset) - code) / 2;	\
104 		if (s390_is_imm16(displace)) {					\
105 			s390_##cab (code, ins->sreg1, s390_r0,    		\
106 				    ins->sreg3, displace);			\
107 		} else { 							\
108 			s390_##cmp (code, ins->sreg1, s390_r0);			\
109 			displace = ((cfg->native_code + 			\
110 			    ins->inst_true_bb->native_offset) - code) / 2;	\
111 			s390_jcl (code, ins->sreg3, displace); 			\
112 		}								\
113 	}									\
114 } else { 									\
115 	if ((ins->backend.data == 0) && (!logical)) {				\
116 		s390_##lat (code, ins->sreg1, ins->sreg1);			\
117 	} else {								\
118 		S390_SET (code, s390_r0, ins->backend.data);			\
119 		s390_##cmp (code, ins->sreg1, s390_r0);				\
120 	}									\
121 	mono_add_patch_info (cfg, code - cfg->native_code, 			\
122 			     MONO_PATCH_INFO_BB, ins->inst_true_bb); 		\
123 	s390_jcl (code, ins->sreg3, 0);						\
124 } 										\
125 }
126 
127 #define CHECK_SRCDST_COM						\
128 	if (ins->dreg == ins->sreg2) {					\
129 		src2 = ins->sreg1;					\
130 	} else {							\
131 		src2 = ins->sreg2;					\
132 		if (ins->dreg != ins->sreg1) {				\
133 			s390_lgr (code, ins->dreg, ins->sreg1);		\
134 		}							\
135 	}
136 
137 #define CHECK_SRCDST_NCOM						\
138 	if (ins->dreg == ins->sreg2) {					\
139 		src2 = s390_r13;					\
140 		s390_lgr (code, s390_r13, ins->sreg2);			\
141 	} else {							\
142 		src2 = ins->sreg2;					\
143 	}								\
144 	if (ins->dreg != ins->sreg1) {					\
145 		s390_lgr (code, ins->dreg, ins->sreg1);			\
146 	}
147 
148 #define CHECK_SRCDST_COM_I						\
149 	if (ins->dreg == ins->sreg2) {					\
150 		src2 = ins->sreg1;					\
151 	} else {							\
152 		src2 = ins->sreg2;					\
153 		if (ins->dreg != ins->sreg1) {				\
154 			s390_lgfr (code, ins->dreg, ins->sreg1);	\
155 		}							\
156 	}
157 
158 #define CHECK_SRCDST_NCOM_I						\
159 	if (ins->dreg == ins->sreg2) {					\
160 		src2 = s390_r13;					\
161 		s390_lgfr (code, s390_r13, ins->sreg2);			\
162 	} else {							\
163 		src2 = ins->sreg2;					\
164 	}								\
165 	if (ins->dreg != ins->sreg1) {					\
166 		s390_lgfr (code, ins->dreg, ins->sreg1);		\
167 	}
168 
169 #define CHECK_SRCDST_COM_F						\
170 	if (ins->dreg == ins->sreg2) {					\
171 		src2 = ins->sreg1;					\
172 	} else {							\
173 		src2 = ins->sreg2;					\
174 		if (ins->dreg != ins->sreg1) {				\
175 			s390_ldr (code, ins->dreg, ins->sreg1);		\
176 		}							\
177 	}
178 
179 #define CHECK_SRCDST_NCOM_F						\
180 	if (ins->dreg == ins->sreg2) {					\
181 		src2 = s390_f15;					\
182 		s390_ldr (code, s390_r13, ins->sreg2);			\
183 	} else {							\
184 		src2 = ins->sreg2;					\
185 	}								\
186 	if (ins->dreg != ins->sreg1) {					\
187 		s390_ldr (code, ins->dreg, ins->sreg1);			\
188 	}
189 
190 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { 			\
191                 MonoInst *inst; 						\
192 		int sReg, dReg;							\
193 		MONO_INST_NEW (cfg, inst, OP_NOP);				\
194 		if (size > 256) {						\
195 			inst->dreg	  = dest;				\
196 			inst->inst_offset = offset;				\
197 			inst->sreg1	  = src;				\
198 			inst->inst_imm	  = imm;				\
199 		} else {							\
200 			if (s390_is_uimm12(offset)) {				\
201 				inst->dreg	  = dest;			\
202 				inst->inst_offset = offset;			\
203 			} else {						\
204 				dReg = mono_alloc_preg (cfg);			\
205 				MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM,	\
206 					dReg, dest, offset);			\
207 				inst->dreg	  = dReg;			\
208 				inst->inst_offset = 0;				\
209 			}							\
210 			if (s390_is_uimm12(imm)) {  				\
211 				inst->sreg1	  = src; 			\
212 				inst->inst_imm    = imm;   			\
213 			} else {						\
214 				sReg = mono_alloc_preg (cfg); 			\
215 				MONO_EMIT_NEW_BIALU_IMM(cfg, OP_ADD_IMM,	\
216 					sReg, src, imm);   			\
217 				inst->sreg1	  = sReg;			\
218 				inst->inst_imm    = 0;				\
219 			}							\
220 		}								\
221                 inst->opcode 	  	= OP_S390_MOVE; 			\
222 		inst->backend.size	= size;					\
223         MONO_ADD_INS (cfg->cbb, inst);		 				\
224 	} while (0)
225 
226 #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do {				\
227 	int reg = mono_alloc_preg (cfg); \
228 	switch (size) {								\
229 		case 0: 							\
230 			MONO_EMIT_NEW_ICONST(cfg, reg, 0);			\
231 		break;								\
232 		case 1:								\
233 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE,	\
234 				reg, sr, so);					\
235 		break;								\
236 		case 2:								\
237 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE,	\
238 				reg, sr, so);					\
239 		break;								\
240 		case 4:								\
241 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE,	\
242 				reg, sr, so);					\
243 		break;								\
244 		case 8:								\
245 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI8_MEMBASE,	\
246 				reg, sr, so);					\
247 		break;								\
248 	}									\
249 	mono_call_inst_add_outarg_reg(cfg, call, reg, dr, FALSE);		\
250 } while (0)
251 
252 #define MONO_OUTPUT_VTS(cfg, size, dr, dx, sr, so) do {				\
253 	int tmpr;								\
254 	switch (size) {								\
255 		case 0: 							\
256 			tmpr = mono_alloc_preg (cfg); \
257 			MONO_EMIT_NEW_ICONST(cfg, tmpr, 0);			\
258 			MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
259 				dr, dx, tmpr);					\
260 		break;								\
261 		case 1:								\
262 			tmpr = mono_alloc_preg (cfg); \
263 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE,	\
264 				tmpr, sr, so);					\
265 			MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
266 				dr, dx, tmpr);					\
267 		break;								\
268 		case 2:								\
269 			tmpr = mono_alloc_preg (cfg); 				\
270 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE,	\
271 				tmpr, sr, so);					\
272 			MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
273 				dr, dx, tmpr);					\
274 		break;								\
275 		case 4:								\
276 			tmpr = mono_alloc_preg (cfg);   			\
277 			MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADI4_MEMBASE,	\
278 				tmpr, sr, so);					\
279 			MONO_EMIT_NEW_STORE_MEMBASE(cfg, OP_STORE_MEMBASE_REG,  \
280 				dr, dx, tmpr);					\
281 		break;								\
282 		case 8:								\
283 			MONO_EMIT_NEW_MOVE (cfg, dr, dx, sr, so, size);		\
284 		break;								\
285 	}									\
286 } while (0)
287 
288 #undef DEBUG
289 #define DEBUG(a) if (cfg->verbose_level > 1) a
290 
291 #define MAX_EXC	16
292 
293 #define S390_TRACE_STACK_SIZE (5*sizeof(gpointer)+4*sizeof(gdouble))
294 
295 #define BREAKPOINT_SIZE		sizeof(breakpoint_t)
296 #define S390X_NOP_SIZE	 	sizeof(RR_Format)
297 
298 #define MAX(a, b) ((a) > (b) ? (a) : (b))
299 
300 /*
301  * imt trampoline size values
302  */
303 #define CMP_SIZE 	24
304 #define LOADCON_SIZE	20
305 #define LOAD_SIZE	6
306 #define BR_SIZE		2
307 #define JUMP_SIZE	6
308 #define ENABLE_WRONG_METHOD_CHECK 0
309 
310 #define mono_mini_arch_lock() mono_os_mutex_lock (&mini_arch_mutex)
311 #define mono_mini_arch_unlock() mono_os_mutex_unlock (&mini_arch_mutex)
312 
313 /*========================= End of Defines =========================*/
314 
315 /*------------------------------------------------------------------*/
316 /*                 I n c l u d e s                                  */
317 /*------------------------------------------------------------------*/
318 
319 #include "mini.h"
320 #include <string.h>
321 #include <sys/types.h>
322 #include <unistd.h>
323 
324 #include <mono/metadata/abi-details.h>
325 #include <mono/metadata/appdomain.h>
326 #include <mono/metadata/debug-helpers.h>
327 #include <mono/metadata/profiler-private.h>
328 #include <mono/utils/mono-error.h>
329 #include <mono/utils/mono-error-internals.h>
330 #include <mono/utils/mono-math.h>
331 #include <mono/utils/mono-mmap.h>
332 #include <mono/utils/mono-hwcap.h>
333 #include <mono/utils/mono-threads.h>
334 #include <mono/utils/unlocked.h>
335 
336 #include "mini-s390x.h"
337 #include "cpu-s390x.h"
338 #include "support-s390x.h"
339 #include "jit-icalls.h"
340 #include "ir-emit.h"
341 #include "trace.h"
342 #include "mini-gc.h"
343 #include "aot-runtime.h"
344 #include "mini-runtime.h"
345 
346 /*========================= End of Includes ========================*/
347 
348 /*------------------------------------------------------------------*/
349 /*                 T y p e d e f s                                  */
350 /*------------------------------------------------------------------*/
351 
352 typedef struct {
353 	guint stack_size,
354 	      local_size,
355 	      code_size,
356 	      parm_size,
357 	      offset,
358 	      offStruct,
359 	      retStruct;
360 } size_data;
361 
362 /*------------------------------------------------------------------*/
363 /* Used by the instrument_emit_epilog 		                    */
364 /*------------------------------------------------------------------*/
365 
366 enum {
367 	SAVE_NONE,
368 	SAVE_STRUCT,
369 	SAVE_ONE,
370 	SAVE_TWO,
371 	SAVE_R4,
372 	SAVE_R8
373 };
374 
375 typedef struct InstList InstList;
376 
377 struct InstList {
378 	InstList *prev;
379 	InstList *next;
380 	MonoInst *data;
381 };
382 
383 typedef enum {
384 	RegTypeGeneral,
385 	RegTypeBase,
386 	RegTypeFP,
387 	RegTypeFPR4,
388 	RegTypeStructByVal,
389 	RegTypeStructByValInFP,
390 	RegTypeStructByAddr,
391 	RegTypeStructByAddrOnStack
392 } ArgStorage;
393 
394 typedef struct {
395 	gint32  offset;		/* offset from caller's stack */
396 	gint32  offparm;	/* offset from callee's stack */
397 	guint16 vtsize; 	/* in param area */
398 	guint8  reg;
399 	ArgStorage regtype;
400 	guint32 size;        	/* Size of structure used by RegTypeStructByVal */
401 	gint32  type;		/* Data type of argument */
402 } ArgInfo;
403 
404 typedef struct {
405 	int nargs;
406 	int lastgr;
407 	guint32 stack_usage;
408 	guint32 struct_ret;
409 	ArgInfo ret;
410 	ArgInfo sigCookie;
411 	size_data sz;
412 	int vret_arg_index;
413 	ArgInfo args [1];
414 } CallInfo;
415 
416 typedef struct {
417 	gint64	gr[5];		/* R2-R6			    */
418 	gdouble fp[3];		/* F0-F2			    */
419 } __attribute__ ((__packed__)) RegParm;
420 
421 typedef struct {
422 	RR_Format  basr;
423 	RI_Format  j;
424 	void	   *pTrigger;
425 	RXY_Format lg;
426 	RXY_Format trigger;
427 } __attribute__ ((__packed__)) breakpoint_t;
428 
429 /*========================= End of Typedefs ========================*/
430 
431 /*------------------------------------------------------------------*/
432 /*                   P r o t o t y p e s                            */
433 /*------------------------------------------------------------------*/
434 
435 static void indent (int);
436 static guint8 * backUpStackPtr(MonoCompile *, guint8 *);
437 static void decodeParm (MonoType *, void *, int);
438 static void enter_method (MonoMethod *, RegParm *, char *);
439 static void leave_method (MonoMethod *, ...);
440 static inline void add_general (guint *, size_data *, ArgInfo *);
441 static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint);
442 static inline void add_float (guint *, size_data *, ArgInfo *);
443 static CallInfo * get_call_info (MonoCompile *, MonoMemPool *, MonoMethodSignature *);
444 static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean);
445 static guint8 * emit_load_volatile_arguments (guint8 *, MonoCompile *);
446 static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long);
447 static void compare_and_branch(MonoBasicBlock *, MonoInst *, int, gboolean);
448 
449 /*========================= End of Prototypes ======================*/
450 
451 /*------------------------------------------------------------------*/
452 /*                 G l o b a l   V a r i a b l e s                  */
453 /*------------------------------------------------------------------*/
454 
455 __thread int indent_level = 0;
456 __thread FILE *trFd = NULL;
457 int curThreadNo = 0;
458 
459 /*
460  * The code generated for sequence points reads from this location,
461  * which is made read-only when single stepping is enabled.
462  */
463 static gpointer ss_trigger_page;
464 
465 /*
466  * Enabled breakpoints read from this trigger page
467  */
468 static gpointer bp_trigger_page;
469 
470 breakpoint_t breakpointCode;
471 
472 static mono_mutex_t mini_arch_mutex;
473 
474 static const char * grNames[] = {
475 	"s390_r0", "s390_sp", "s390_r2", "s390_r3", "s390_r4",
476 	"s390_r5", "s390_r6", "s390_r7", "s390_r8", "s390_r9",
477 	"s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14",
478 	"s390_r15"
479 };
480 
481 static const char * fpNames[] = {
482 	"s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4",
483 	"s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9",
484 	"s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14",
485 	"s390_f15"
486 };
487 
488 static const char * vrNames[] = {
489 	"vr0",  "vr1",  "vr2",  "vr3",  "vr4",  "vr5",  "vr6",  "vr7",
490 	"vr8",  "vr9",  "vr10", "vr11", "vr12", "vr13", "vr14", "vr15",
491 	"vr16", "vr17", "vr18", "vr19", "vr20", "vr21", "vr22", "vr23",
492 	"vr24", "vr25", "vr26", "vr27", "vr28", "vr29", "vr30", "vr31"
493 };
494 
495 /*====================== End of Global Variables ===================*/
496 
497 /*------------------------------------------------------------------*/
498 /*                                                                  */
499 /* Name		- mono_arch_regname                                 */
500 /*                                                                  */
501 /* Function	- Returns the name of the register specified by     */
502 /*		  the input parameter.         		 	    */
503 /*		                               		 	    */
504 /*------------------------------------------------------------------*/
505 
506 const char*
mono_arch_regname(int reg)507 mono_arch_regname (int reg)
508 {
509 	if (reg >= 0 && reg < 16)
510 		return grNames [reg];
511 	else
512 		return "unknown";
513 }
514 
515 /*========================= End of Function ========================*/
516 
517 /*------------------------------------------------------------------*/
518 /*                                                                  */
519 /* Name		- mono_arch_fregname                                */
520 /*                                                                  */
521 /* Function	- Returns the name of the register specified by     */
522 /*		  the input parameter.         		 	    */
523 /*		                               		 	    */
524 /*------------------------------------------------------------------*/
525 
526 const char*
mono_arch_fregname(int reg)527 mono_arch_fregname (int reg)
528 {
529 	if (reg >= 0 && reg < 16)
530 		return fpNames [reg];
531 	else
532 		return "unknown";
533 }
534 
535 /*========================= End of Function ========================*/
536 
537 /*------------------------------------------------------------------*/
538 /*                                                                  */
539 /* Name		- mono_arch_xregname                                */
540 /*                                                                  */
541 /* Function	- Returns the name of the register specified by     */
542 /*		  the input parameter.         		 	    */
543 /*		                               		 	    */
544 /*------------------------------------------------------------------*/
545 
546 const char *
mono_arch_xregname(int reg)547 mono_arch_xregname (int reg)
548 {
549 	if (reg < s390_VR_NREG)
550 		return vrNames [reg];
551 	else
552 		return "unknown";
553 }
554 
555 /*========================= End of Function ========================*/
556 
557 /*------------------------------------------------------------------*/
558 /*                                                                  */
559 /* Name		- arch_get_argument_info                            */
560 /*                                                                  */
561 /* Function	- Gathers information on parameters such as size,   */
562 /*		  alignment, and padding. arg_info should be large  */
563 /*		  enough to hold param_count + 1 entries.	    */
564 /*		                               			    */
565 /* Parameters   - @csig - Method signature     			    */
566 /*		  @param_count - No. of parameters to consider      */
567 /*		  @arg_info - An array to store the result info	    */
568 /*		                               			    */
569 /* Returns      - Size of the activation frame 			    */
570 /*		                               			    */
571 /*------------------------------------------------------------------*/
572 
573 int
mono_arch_get_argument_info(MonoMethodSignature * csig,int param_count,MonoJitArgumentInfo * arg_info)574 mono_arch_get_argument_info (MonoMethodSignature *csig,
575 			     int param_count,
576 			     MonoJitArgumentInfo *arg_info)
577 {
578 	int k, frame_size = 0;
579 	int size, align, pad;
580 	int offset = 8;
581 
582 	if (MONO_TYPE_ISSTRUCT (csig->ret)) {
583 		frame_size += sizeof (gpointer);
584 		offset += 8;
585 	}
586 
587 	arg_info [0].offset = offset;
588 
589 	if (csig->hasthis) {
590 		frame_size += sizeof (gpointer);
591 		offset += 8;
592 	}
593 
594 	arg_info [0].size = frame_size;
595 
596 	for (k = 0; k < param_count; k++) {
597 
598 		if (csig->pinvoke)
599 			size = mono_type_native_stack_size (csig->params [k], (guint32 *) &align);
600 		else
601 			size = mini_type_stack_size (csig->params [k], &align);
602 
603 		frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
604 		arg_info [k].pad = pad;
605 		frame_size += size;
606 		arg_info [k + 1].pad = 0;
607 		arg_info [k + 1].size = size;
608 		offset += pad;
609 		arg_info [k + 1].offset = offset;
610 		offset += size;
611 	}
612 
613 	align = MONO_ARCH_FRAME_ALIGNMENT;
614 	frame_size += pad = (align - (frame_size & (align - 1))) & (align - 1);
615 	arg_info [k].pad = pad;
616 
617 	return frame_size;
618 }
619 
620 /*========================= End of Function ========================*/
621 
622 /*------------------------------------------------------------------*/
623 /*                                                                  */
624 /* Name		- emit_unwind_regs.                                 */
625 /*                                                                  */
626 /* Function	- Determines if a value can be returned in one or   */
627 /*                two registers.                                    */
628 /*                                                                  */
629 /*------------------------------------------------------------------*/
630 
631 static void __inline__
emit_unwind_regs(MonoCompile * cfg,guint8 * code,int start,int end,long offset)632 emit_unwind_regs(MonoCompile *cfg, guint8 *code, int start, int end, long offset)
633 {
634 	int i;
635 
636 	for (i = start; i < end; i++) {
637 		mono_emit_unwind_op_offset (cfg, code, i, offset);
638 		mini_gc_set_slot_type_from_cfa (cfg, offset, SLOT_NOREF);
639 		offset += sizeof(gulong);
640 	}
641 }
642 
643 /*========================= End of Function ========================*/
644 
645 /*------------------------------------------------------------------*/
646 /*                                                                  */
647 /* Name		- retFitsInReg.                                     */
648 /*                                                                  */
649 /* Function	- Determines if a value can be returned in one or   */
650 /*                two registers.                                    */
651 /*                                                                  */
652 /*------------------------------------------------------------------*/
653 
654 static inline gboolean
retFitsInReg(guint32 size)655 retFitsInReg(guint32 size)
656 {
657 	switch (size) {
658 		case 0:
659 		case 1:
660 		case 2:
661 		case 4:
662 		case 8:
663 			return (TRUE);
664 		break;
665 		default:
666 			return (FALSE);
667 	}
668 }
669 
670 /*========================= End of Function ========================*/
671 
672 /*------------------------------------------------------------------*/
673 /*                                                                  */
674 /* Name		- backStackPtr.                                     */
675 /*                                                                  */
676 /* Function	- Restore Stack Pointer to previous frame.          */
677 /*                                                                  */
678 /*------------------------------------------------------------------*/
679 
680 static inline guint8 *
backUpStackPtr(MonoCompile * cfg,guint8 * code)681 backUpStackPtr(MonoCompile *cfg, guint8 *code)
682 {
683 	int stackSize = cfg->stack_usage;
684 
685 	if (cfg->frame_reg != STK_BASE)
686 		s390_lgr (code, STK_BASE, cfg->frame_reg);
687 
688 	if (s390_is_imm16 (stackSize)) {
689 		s390_aghi  (code, STK_BASE, stackSize);
690 	} else {
691 		while (stackSize > 32767) {
692 			s390_aghi  (code, STK_BASE, 32767);
693 			stackSize -= 32767;
694 		}
695 		s390_aghi  (code, STK_BASE, stackSize);
696 	}
697 	return (code);
698 }
699 
700 /*========================= End of Function ========================*/
701 
702 /*------------------------------------------------------------------*/
703 /*                                                                  */
704 /* Name		- indent                                            */
705 /*                                                                  */
706 /* Function	- Perform nice indenting to current level           */
707 /*                                                                  */
708 /*------------------------------------------------------------------*/
709 
710 static void
indent(int diff)711 indent (int diff) {
712 	int v;
713 	if (diff < 0)
714 		indent_level += diff;
715 	v = indent_level;
716 	fprintf (trFd, "%p [%3d] ",(void *)pthread_self(),v);
717 	while (v-- > 0) {
718 		fprintf (trFd, ". ");
719 	}
720 	if (diff > 0)
721 		indent_level += diff;
722 }
723 
724 /*========================= End of Function ========================*/
725 
726 /*------------------------------------------------------------------*/
727 /*                                                                  */
728 /* Name		- cvtMonoType                                       */
729 /*                                                                  */
730 /* Function	- Convert a mono-type to a string.                  */
731 /*		                               			    */
732 /*------------------------------------------------------------------*/
733 
734 static const char *
cvtMonoType(MonoTypeEnum t)735 cvtMonoType(MonoTypeEnum t)
736 {
737   switch(t)
738     {
739     case MONO_TYPE_END:
740       return "MONO_TYPE_END";
741     case MONO_TYPE_VOID:
742       return "MONO_TYPE_VOID";
743     case MONO_TYPE_BOOLEAN:
744       return "MONO_TYPE_BOOLEAN";
745     case MONO_TYPE_CHAR:
746       return "MONO_TYPE_CHAR";
747     case MONO_TYPE_I1:
748       return "MONO_TYPE_I1";
749     case MONO_TYPE_U1:
750       return "MONO_TYPE_U1";
751     case MONO_TYPE_I2:
752       return "MONO_TYPE_I2";
753     case MONO_TYPE_U2:
754       return "MONO_TYPE_U2";
755     case MONO_TYPE_I4:
756       return "MONO_TYPE_I4";
757     case MONO_TYPE_U4:
758       return "MONO_TYPE_U4";
759     case MONO_TYPE_I8:
760       return "MONO_TYPE_I8";
761     case MONO_TYPE_U8:
762       return "MONO_TYPE_U8";
763     case MONO_TYPE_R4:
764       return "MONO_TYPE_R4";
765     case MONO_TYPE_R8:
766       return "MONO_TYPE_R8";
767     case MONO_TYPE_STRING:
768       return "MONO_TYPE_STRING";
769     case MONO_TYPE_PTR:
770       return "MONO_TYPE_PTR";
771     case MONO_TYPE_BYREF:
772       return "MONO_TYPE_BYREF";
773     case MONO_TYPE_VALUETYPE:
774       return "MONO_TYPE_VALUETYPE";
775     case MONO_TYPE_CLASS:
776       return "MONO_TYPE_CLASS";
777     case MONO_TYPE_VAR:
778       return "MONO_TYPE_VAR";
779     case MONO_TYPE_ARRAY:
780       return "MONO_TYPE_ARRAY";
781     case MONO_TYPE_GENERICINST:
782       return "MONO_TYPE_GENERICINST";
783     case MONO_TYPE_TYPEDBYREF:
784       return "MONO_TYPE_TYPEDBYREF";
785     case MONO_TYPE_I:
786       return "MONO_TYPE_I";
787     case MONO_TYPE_U:
788       return "MONO_TYPE_U";
789     case MONO_TYPE_FNPTR:
790       return "MONO_TYPE_FNPTR";
791     case MONO_TYPE_OBJECT:
792       return "MONO_TYPE_OBJECT";
793     case MONO_TYPE_SZARRAY:
794       return "MONO_TYPE_SZARRAY";
795     case MONO_TYPE_MVAR:
796       return "MONO_TYPE_MVAR";
797     case MONO_TYPE_CMOD_REQD:
798       return "MONO_TYPE_CMOD_REQD";
799     case MONO_TYPE_CMOD_OPT:
800       return "MONO_TYPE_CMOD_OPT";
801     case MONO_TYPE_INTERNAL:
802       return "MONO_TYPE_INTERNAL";
803     case MONO_TYPE_MODIFIER:
804       return "MONO_TYPE_MODIFIER";
805     case MONO_TYPE_SENTINEL:
806       return "MONO_TYPE_SENTINEL";
807     case MONO_TYPE_PINNED:
808       return "MONO_TYPE_PINNED";
809     default:
810       ;
811     }
812   return "unknown";
813 }
814 
815 /*========================= End of Function ========================*/
816 
817 /*------------------------------------------------------------------*/
818 /*                                                                  */
819 /* Name		- decodeParmString                                  */
820 /*                                                                  */
821 /* Function	- Decode a parameter string for the trace.          */
822 /*		                               			    */
823 /*------------------------------------------------------------------*/
824 
825 static void
decodeParmString(MonoString * s)826 decodeParmString (MonoString *s)
827 {
828 	MonoError error;
829 	char *str = mono_string_to_utf8_checked(s, &error);
830 	if (is_ok (&error))  {
831 		fprintf (trFd, "[STRING:%p:%s], ", s, str);
832 		g_free (str);
833 	} else {
834 		mono_error_cleanup (&error);
835 		fprintf (trFd, "[STRING:%p:], ", s);
836 	}
837 }
838 
839 /*========================= End of Function ========================*/
840 
841 /*------------------------------------------------------------------*/
842 /*                                                                  */
843 /* Name		- decodeParm                                        */
844 /*                                                                  */
845 /* Function	- Decode a parameter for the trace.                 */
846 /*		                               			    */
847 /*------------------------------------------------------------------*/
848 
849 
850 static void
decodeParm(MonoType * type,void * curParm,int size)851 decodeParm(MonoType *type, void *curParm, int size)
852 {
853 	guint32 simpleType;
854 
855 	if (type->byref) {
856 		fprintf (trFd, "[BYREF:%p], ", *((char **) curParm));
857 	} else {
858 		simpleType = mini_get_underlying_type(type)->type;
859 enum_parmtype:
860 		switch (simpleType) {
861 			case MONO_TYPE_I :
862 				fprintf (trFd, "[INTPTR:%p], ", *((int **) curParm));
863 				break;
864 			case MONO_TYPE_U :
865 				fprintf (trFd, "[UINTPTR:%p], ", *((int **) curParm));
866 				break;
867 			case MONO_TYPE_BOOLEAN :
868 				fprintf (trFd, "[BOOL:%ld], ", *((gint64 *) curParm));
869 				break;
870 			case MONO_TYPE_CHAR :
871 				fprintf (trFd, "[CHAR:%c], ", *((int  *) curParm));
872 				break;
873 			case MONO_TYPE_I1 :
874 				fprintf (trFd, "[INT1:%ld], ", *((gint64 *) curParm));
875 				break;
876 			case MONO_TYPE_I2 :
877 				fprintf (trFd, "[INT2:%ld], ", *((gint64 *) curParm));
878 				break;
879 			case MONO_TYPE_I4 :
880 				fprintf (trFd, "[INT4:%ld], ", *((gint64 *) curParm));
881 				break;
882 			case MONO_TYPE_U1 :
883 				fprintf (trFd, "[UINT1:%lu], ", *((guint64 *) curParm));
884 				break;
885 			case MONO_TYPE_U2 :
886 				fprintf (trFd, "[UINT2:%lu], ", *((guint64 *) curParm));
887 				break;
888 			case MONO_TYPE_U4 :
889 				fprintf (trFd, "[UINT4:%lu], ", *((guint64 *) curParm));
890 				break;
891 			case MONO_TYPE_U8 :
892 				fprintf (trFd, "[UINT8:%lu], ", *((guint64 *) curParm));
893 				break;
894 			case MONO_TYPE_STRING : {
895 				MonoString *s = *((MonoString **) curParm);
896 				if (s) {
897 					g_assert (((MonoObject *) s)->vtable->klass == mono_defaults.string_class);
898 					decodeParmString (s);
899 				} else {
900 					fprintf (trFd, "[STRING:null], ");
901 				}
902 				break;
903 			}
904 			case MONO_TYPE_CLASS :
905 			case MONO_TYPE_OBJECT : {
906 				MonoObject *obj = *((MonoObject **) curParm);
907 				MonoClass *klass;
908 				if ((obj) && (obj->vtable)) {
909 					fprintf (trFd, "[CLASS/OBJ:");
910 					klass = obj->vtable->klass;
911 					fprintf (trFd, "%p [%p] ",obj,curParm);
912 					if (klass == mono_defaults.string_class) {
913 						decodeParmString ((MonoString *)obj);
914 					} else if (klass == mono_defaults.int32_class) {
915 						fprintf (trFd, "[INT32:%p:%d]",
916 							obj, *(gint32 *)((char *)obj + sizeof (MonoObject)));
917 					} else
918 						fprintf (trFd, "[%s.%s:%p]",
919 						       klass->name_space, klass->name, obj);
920 					fprintf (trFd, "], ");
921 				} else {
922 					fprintf (trFd, "[OBJECT:null], ");
923 				}
924 				break;
925 			}
926 			case MONO_TYPE_PTR :
927 				fprintf (trFd, "[PTR:%p], ", *((gpointer **) (curParm)));
928 				break;
929 			case MONO_TYPE_FNPTR :
930 				fprintf (trFd, "[FNPTR:%p], ", *((gpointer **) (curParm)));
931 				break;
932 			case MONO_TYPE_ARRAY :
933 				fprintf (trFd, "[ARRAY:%p], ", *((gpointer **) (curParm)));
934 				break;
935 			case MONO_TYPE_SZARRAY :
936 				fprintf (trFd, "[SZARRAY:%p], ", *((gpointer **) (curParm)));
937 				break;
938 			case MONO_TYPE_I8 :
939 				fprintf (trFd, "[INT8:%ld], ", *((gint64 *) (curParm)));
940 				break;
941 			case MONO_TYPE_R4 :
942 				fprintf (trFd, "[FLOAT4:%g], ", *((float *) (curParm)));
943 				break;
944 			case MONO_TYPE_R8 :
945 				fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
946 				break;
947 			case MONO_TYPE_VALUETYPE : {
948 				int i;
949 				MonoMarshalType *info;
950 
951 				if (type->data.klass->enumtype) {
952 					simpleType = mono_class_enum_basetype (type->data.klass)->type;
953 					fprintf (trFd, "{VALUETYPE} - ");
954 					goto enum_parmtype;
955 				}
956 
957 				info = mono_marshal_load_type_info (type->data.klass);
958 
959 				if ((info->native_size == sizeof(float)) &&
960 				    (info->num_fields  == 1) &&
961 				    (info->fields[0].field->type->type == MONO_TYPE_R4)) {
962 						fprintf (trFd, "[FLOAT4:%f], ", *((float *) (curParm)));
963 					break;
964 				}
965 
966 				if ((info->native_size == sizeof(double)) &&
967 				    (info->num_fields  == 1) &&
968 				    (info->fields[0].field->type->type == MONO_TYPE_R8)) {
969 					fprintf (trFd, "[FLOAT8:%g], ", *((double *) (curParm)));
970 					break;
971 				}
972 
973 				fprintf (trFd, "[VALUETYPE:");
974 				for (i = 0; i < size; i++)
975 					fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
976 				fprintf (trFd, "], ");
977 				break;
978 			}
979 			case MONO_TYPE_TYPEDBYREF: {
980 				int i;
981 				fprintf (trFd, "[TYPEDBYREF:");
982 				for (i = 0; i < size; i++)
983 					fprintf (trFd, "%02x,", *((guint8 *)curParm+i));
984 				fprintf (trFd, "]");
985 				break;
986 			}
987 			default :
988 				fprintf (trFd, "[%s], ",cvtMonoType(simpleType));
989 		}
990 	}
991 }
992 
993 /*========================= End of Function ========================*/
994 
995 /*------------------------------------------------------------------*/
996 /*                                                                  */
997 /* Name		- enter_method                                      */
998 /*                                                                  */
999 /* Function	- Perform tracing of the entry to the current       */
1000 /*		  method.                      			    */
1001 /*		                               			    */
1002 /*------------------------------------------------------------------*/
1003 
1004 static void
enter_method(MonoMethod * method,RegParm * rParm,char * sp)1005 enter_method (MonoMethod *method, RegParm *rParm, char *sp)
1006 {
1007 	int i, oParm = 0, iParm = 0;
1008 	MonoClass *klass;
1009 	MonoObject *obj;
1010 	MonoMethodSignature *sig;
1011 	char *fname;
1012 	guint64 ip;
1013 	CallInfo *cinfo;
1014 	ArgInfo *ainfo;
1015 	void *curParm;
1016 
1017 	if (trFd == NULL) {
1018 		char buf[32];
1019 		sprintf(buf, "/tmp/mono.%d.trc.%d", getpid(), curThreadNo++);
1020 		trFd = fopen(buf, "w");
1021 	}
1022 	fname = mono_method_full_name (method, TRUE);
1023 	indent (1);
1024 	fprintf (trFd, "ENTER: %s ", fname);
1025 	g_free (fname);
1026 
1027 	ip  = (*(guint64 *) (sp+S390_RET_ADDR_OFFSET));
1028 	fprintf (trFd, "ip: %p sp: %p - ", (gpointer) ip, sp);
1029 
1030 	if (rParm == NULL)
1031 		return;
1032 
1033 	sig = mono_method_signature (method);
1034 
1035 	cinfo = get_call_info (NULL, NULL, sig);
1036 
1037 	if (cinfo->struct_ret) {
1038 		fprintf (trFd, "[STRUCTRET:%p], ", (gpointer) rParm->gr[0]);
1039 		iParm = 1;
1040 	}
1041 
1042 	if (sig->hasthis) {
1043 		gpointer *this_arg = (gpointer *) rParm->gr[iParm];
1044 		obj = (MonoObject *) this_arg;
1045 		switch(method->klass->this_arg.type) {
1046 		case MONO_TYPE_VALUETYPE:
1047 			if (obj) {
1048 				guint64 *value = (guint64 *) ((uintptr_t)this_arg + sizeof(MonoObject));
1049 				fprintf (trFd, "this:[value:%p:%016lx], ", this_arg, *value);
1050 			} else
1051 				fprintf (trFd, "this:[NULL], ");
1052 			break;
1053 		case MONO_TYPE_STRING:
1054 			if (obj) {
1055 				if (obj->vtable) {
1056 					klass = obj->vtable->klass;
1057 					if (klass == mono_defaults.string_class) {
1058 						fprintf (trFd, "this:");
1059 						decodeParmString((MonoString *)obj);
1060 					} else {
1061 						fprintf (trFd, "this:%p[%s.%s], ",
1062 							obj, klass->name_space, klass->name);
1063 					}
1064 				} else
1065 					fprintf (trFd, "vtable:[NULL], ");
1066 			} else
1067 				fprintf (trFd, "this:[NULL], ");
1068 			break;
1069 		default :
1070 			fprintf (trFd, "this[%s]: %p, ",cvtMonoType(method->klass->this_arg.type),this_arg);
1071 		}
1072 		oParm++;
1073 	}
1074 
1075 	for (i = 0; i < sig->param_count; ++i) {
1076 		ainfo = &cinfo->args[i + oParm];
1077 		switch (ainfo->regtype) {
1078 			case RegTypeGeneral :
1079 				decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size);
1080 				break;
1081 			case RegTypeFP :
1082 				decodeParm(sig->params[i], &(rParm->fp[ainfo->reg]), ainfo->size);
1083 				break;
1084 			case RegTypeBase :
1085 				decodeParm(sig->params[i], sp+ainfo->offset, ainfo->size);
1086 				break;
1087 			case RegTypeStructByVal :
1088 				if (ainfo->reg != STK_BASE) {
1089 					int offset = sizeof(glong) - ainfo->size;
1090 					curParm = &(rParm->gr[ainfo->reg-2])+offset;
1091 				}
1092 				else
1093 					curParm = sp+ainfo->offset;
1094 
1095 				if (retFitsInReg (ainfo->vtsize))
1096 					decodeParm(sig->params[i],
1097 				 	           curParm,
1098 					           ainfo->size);
1099 				else
1100 					decodeParm(sig->params[i],
1101 				 	           *((char **) curParm),
1102 					           ainfo->vtsize);
1103 				break;
1104 			case RegTypeStructByAddr :
1105 				if (ainfo->reg != STK_BASE)
1106 					curParm = &(rParm->gr[ainfo->reg-2]);
1107 				else
1108 					curParm = sp+ainfo->offset;
1109 
1110 				decodeParm(sig->params[i],
1111 				           *((char **) curParm),
1112 				           ainfo->vtsize);
1113 				break;
1114 
1115 			default :
1116 				fprintf (trFd, "???, ");
1117 		}
1118 	}
1119 	fprintf (trFd, "\n");
1120 	g_free(cinfo);
1121 }
1122 
1123 /*========================= End of Function ========================*/
1124 
1125 /*------------------------------------------------------------------*/
1126 /*                                                                  */
1127 /* Name		- leave_method                                      */
1128 /*                                                                  */
1129 /* Function	-                                                   */
1130 /*		                               			    */
1131 /*------------------------------------------------------------------*/
1132 
1133 static void
leave_method(MonoMethod * method,...)1134 leave_method (MonoMethod *method, ...)
1135 {
1136 	MonoType *type;
1137 	char *fname;
1138 	guint64 ip;
1139 	va_list ap;
1140 
1141 	va_start(ap, method);
1142 
1143 	fname = mono_method_full_name (method, TRUE);
1144 	indent (-1);
1145 	fprintf (trFd, "LEAVE: %s", fname);
1146 	g_free (fname);
1147 
1148 	type = mono_method_signature (method)->ret;
1149 
1150 handle_enum:
1151 	switch (type->type) {
1152 	case MONO_TYPE_VOID:
1153 		break;
1154 	case MONO_TYPE_BOOLEAN: {
1155 		int val = va_arg (ap, int);
1156 		if (val)
1157 			fprintf (trFd, "[TRUE:%d]", val);
1158 		else
1159 			fprintf (trFd, "[FALSE]");
1160 
1161 		break;
1162 	}
1163 	case MONO_TYPE_CHAR: {
1164 		int val = va_arg (ap, int);
1165 		fprintf (trFd, "[CHAR:%d]", val);
1166 		break;
1167 	}
1168 	case MONO_TYPE_I1: {
1169 		int val = va_arg (ap, int);
1170 		fprintf (trFd, "[INT1:%d]", val);
1171 		break;
1172 	}
1173 	case MONO_TYPE_U1: {
1174 		int val = va_arg (ap, int);
1175 		fprintf (trFd, "[UINT1:%d]", val);
1176 		break;
1177 	}
1178 	case MONO_TYPE_I2: {
1179 		int val = va_arg (ap, int);
1180 		fprintf (trFd, "[INT2:%d]", val);
1181 		break;
1182 	}
1183 	case MONO_TYPE_U2: {
1184 		int val = va_arg (ap, int);
1185 		fprintf (trFd, "[UINT2:%d]", val);
1186 		break;
1187 	}
1188 	case MONO_TYPE_I4: {
1189 		int val = va_arg (ap, int);
1190 		fprintf (trFd, "[INT4:%d]", val);
1191 		break;
1192 	}
1193 	case MONO_TYPE_U4: {
1194 		int val = va_arg (ap, int);
1195 		fprintf (trFd, "[UINT4:%d]", val);
1196 		break;
1197 	}
1198 	case MONO_TYPE_I: {
1199 		gint64 val = va_arg (ap, gint64);
1200 		fprintf (trFd, "[INT:%ld]", val);
1201 		fprintf (trFd, "]");
1202 		break;
1203 	}
1204 	case MONO_TYPE_U: {
1205 		gint64 val = va_arg (ap, gint64);
1206 		fprintf (trFd, "[UINT:%lu]", val);
1207 		fprintf (trFd, "]");
1208 		break;
1209 	}
1210 	case MONO_TYPE_STRING: {
1211 		MonoString *s = va_arg (ap, MonoString *);
1212 ;
1213 		if (s) {
1214 			g_assert (((MonoObject *)s)->vtable->klass == mono_defaults.string_class);
1215 			decodeParmString (s);
1216 		} else
1217 			fprintf (trFd, "[STRING:null], ");
1218 		break;
1219 	}
1220 	case MONO_TYPE_CLASS:
1221 	case MONO_TYPE_OBJECT: {
1222 		MonoObject *o = va_arg (ap, MonoObject *);
1223 
1224 		if ((o) && (o->vtable)) {
1225 			if (o->vtable->klass == mono_defaults.boolean_class) {
1226 				fprintf (trFd, "[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject)));
1227 			} else if  (o->vtable->klass == mono_defaults.int32_class) {
1228 				fprintf (trFd, "[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject))));
1229 			} else if  (o->vtable->klass == mono_defaults.int64_class) {
1230 				fprintf (trFd, "[INT64:%p:%ld]", o, *((gint64 *)((char *)o + sizeof (MonoObject))));
1231 			} else
1232 				fprintf (trFd, "[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o);
1233 		} else
1234 			fprintf (trFd, "[OBJECT:%p]", o);
1235 
1236 		break;
1237 	}
1238 	case MONO_TYPE_PTR:
1239 	case MONO_TYPE_FNPTR:
1240 	case MONO_TYPE_ARRAY:
1241 	case MONO_TYPE_SZARRAY: {
1242 		gpointer p = va_arg (ap, gpointer);
1243 		fprintf (trFd, "[result=%p]", p);
1244 		break;
1245 	}
1246 	case MONO_TYPE_I8: {
1247 		gint64 l =  va_arg (ap, gint64);
1248 		fprintf (trFd, "[LONG:%ld]", l);
1249 		break;
1250 	}
1251 	case MONO_TYPE_U8: {
1252 		guint64 l =  va_arg (ap, guint64);
1253 		fprintf (trFd, "[ULONG:%lu]", l);
1254 		break;
1255 	}
1256 	case MONO_TYPE_R4: {
1257 		double f = va_arg (ap, double);
1258 		fprintf (trFd, "[FLOAT4:%g]\n", f);
1259 		break;
1260 	}
1261 	case MONO_TYPE_R8: {
1262 		double f = va_arg (ap, double);
1263 		fprintf (trFd, "[FLOAT8:%g]\n", f);
1264 		break;
1265 	}
1266 	case MONO_TYPE_VALUETYPE: {
1267 		MonoMarshalType *info;
1268 		if (type->data.klass->enumtype) {
1269 			type = mono_class_enum_basetype (type->data.klass);
1270 			goto handle_enum;
1271 		} else {
1272 			int size, align;
1273 
1274 			info = mono_marshal_load_type_info (type->data.klass);
1275 
1276 			if ((info->native_size == sizeof(float)) &&
1277 			    (info->num_fields  == 1) &&
1278 			    (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1279 				double f = va_arg (ap, double);
1280 				fprintf (trFd, "[FLOAT4:%g]\n", (double) f);
1281 				break;
1282 			}
1283 
1284 			if ((info->native_size == sizeof(double)) &&
1285 			    (info->num_fields  == 1) &&
1286 			    (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1287 				double f = va_arg (ap, double);
1288 				fprintf (trFd, "[FLOAT8:%g]\n", f);
1289 				break;
1290 			}
1291 
1292 			size = mono_type_size (type, &align);
1293 			switch (size) {
1294 				case 1: {
1295 					guint32 p = va_arg (ap, guint32);
1296 					fprintf (trFd, "[%02x]\n",p);
1297 					break;
1298 				}
1299 				case 2: {
1300 					guint32 p = va_arg (ap, guint32);
1301 					fprintf (trFd, "[%04x]\n",p);
1302 					break;
1303 				}
1304 				case 4: {
1305 					guint32 p = va_arg (ap, guint32);
1306 					fprintf (trFd, "[%08x]\n",p);
1307 					break;
1308 				}
1309 				case 8: {
1310 					guint64 p = va_arg (ap, guint64);
1311 					fprintf (trFd, "[%016lx]\n",p);
1312 					break;
1313 				}
1314 				default: {
1315 					gpointer p = va_arg (ap, gpointer);
1316 					fprintf (trFd, "[VALUETYPE] %p\n",p);
1317 				}
1318 			}
1319 		}
1320 		break;
1321 	}
1322 	case MONO_TYPE_TYPEDBYREF: {
1323 		guint8 *p = va_arg (ap, gpointer);
1324 		int j, size, align;
1325 		size = mono_type_size (type, &align);
1326 		switch (size) {
1327 		case 1:
1328 		case 2:
1329 		case 4:
1330 		case 8:
1331 			fprintf (trFd, "[");
1332 			for (j = 0; p && j < size; j++)
1333 				fprintf (trFd, "%02x,", p [j]);
1334 			fprintf (trFd, "]\n");
1335 			break;
1336 		default:
1337 			fprintf (trFd, "[TYPEDBYREF]\n");
1338 		}
1339 	}
1340 		break;
1341 	case MONO_TYPE_GENERICINST: {
1342 		fprintf (trFd, "[GENERICINST]\n");
1343 	}
1344 		break;
1345 	case MONO_TYPE_MVAR: {
1346 		fprintf (trFd, "[MVAR]\n");
1347 	}
1348 		break;
1349 	case MONO_TYPE_CMOD_REQD: {
1350 		fprintf (trFd, "[CMOD_REQD]\n");
1351 	}
1352 		break;
1353 	case MONO_TYPE_CMOD_OPT: {
1354 		fprintf (trFd, "[CMOD_OPT]\n");
1355 	}
1356 		break;
1357 	case MONO_TYPE_INTERNAL: {
1358 		fprintf (trFd, "[INTERNAL]\n");
1359 	}
1360 		break;
1361 	default:
1362 		fprintf (trFd, "(unknown return type %x)",
1363 			mono_method_signature (method)->ret->type);
1364 	}
1365 
1366 	ip = ((gint64) __builtin_extract_return_addr (__builtin_return_address (0)));
1367 	fprintf (trFd, " ip: %p\n", (gpointer) ip);
1368 	va_end (ap);
1369 }
1370 
1371 /*========================= End of Function ========================*/
1372 
1373 /*------------------------------------------------------------------*/
1374 /*                                                                  */
1375 /* Name		- mono_arch_cpu_init                                */
1376 /*                                                                  */
1377 /* Function	- Perform CPU specific initialization to execute    */
1378 /*		  managed code.               			    */
1379 /*		                               			    */
1380 /*------------------------------------------------------------------*/
1381 
1382 void
mono_arch_cpu_init(void)1383 mono_arch_cpu_init (void)
1384 {
1385 }
1386 
1387 /*========================= End of Function ========================*/
1388 
1389 /*------------------------------------------------------------------*/
1390 /*                                                                  */
1391 /* Name		- mono_arch_init.                                   */
1392 /*                                                                  */
1393 /* Function	- Initialize architecture specific code.	    */
1394 /*		                               			    */
1395 /*------------------------------------------------------------------*/
1396 
1397 void
mono_arch_init(void)1398 mono_arch_init (void)
1399 {
1400 	guint8 *code;
1401 
1402 	mono_set_partial_sharing_supported (FALSE);
1403 	mono_os_mutex_init_recursive (&mini_arch_mutex);
1404 
1405 	ss_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1406 	bp_trigger_page = mono_valloc (NULL, mono_pagesize (), MONO_MMAP_READ, MONO_MEM_ACCOUNT_OTHER);
1407 	mono_mprotect (bp_trigger_page, mono_pagesize (), 0);
1408 
1409 	code = (guint8 *) &breakpointCode;
1410 	s390_basr(code, s390_r13, 0);
1411 	s390_j(code, 6);
1412 	s390_llong(code, 0);
1413 	s390_lg(code, s390_r13, 0, s390_r13, 4);
1414 	s390_lg(code, s390_r0, 0, s390_r13, 0);
1415 }
1416 
1417 /*========================= End of Function ========================*/
1418 
1419 /*------------------------------------------------------------------*/
1420 /*                                                                  */
1421 /* Name		- mono_arch_cleanup.                                */
1422 /*                                                                  */
1423 /* Function	- Cleanup architecture specific code	.	    */
1424 /*		                               			    */
1425 /*------------------------------------------------------------------*/
1426 
1427 void
mono_arch_cleanup(void)1428 mono_arch_cleanup (void)
1429 {
1430 	if (ss_trigger_page)
1431 		mono_vfree (ss_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1432 	if (bp_trigger_page)
1433 		mono_vfree (bp_trigger_page, mono_pagesize (), MONO_MEM_ACCOUNT_OTHER);
1434 	mono_os_mutex_destroy (&mini_arch_mutex);
1435 }
1436 
1437 /*========================= End of Function ========================*/
1438 
1439 /*------------------------------------------------------------------*/
1440 /*                                                                  */
1441 /* Name		- mono_arch_have_fast_tls                           */
1442 /*                                                                  */
1443 /* Function	- Returns whether we use fast inlined thread local  */
1444 /*                storage managed access, instead of falling back   */
1445 /*                to native code.                                   */
1446 /*		                               			    */
1447 /*------------------------------------------------------------------*/
1448 
1449 gboolean
mono_arch_have_fast_tls(void)1450 mono_arch_have_fast_tls (void)
1451 {
1452 	return TRUE;
1453 }
1454 
1455 /*========================= End of Function ========================*/
1456 
1457 /*------------------------------------------------------------------*/
1458 /*                                                                  */
1459 /* Name		- mono_arch_cpu_optimizations                       */
1460 /*                                                                  */
1461 /* Function	- Returns the optimizations supported on this CPU   */
1462 /*		                               			    */
1463 /*------------------------------------------------------------------*/
1464 
1465 guint32
mono_arch_cpu_optimizations(guint32 * exclude_mask)1466 mono_arch_cpu_optimizations (guint32 *exclude_mask)
1467 {
1468 	guint32 opts = 0;
1469 
1470 	/*----------------------------------------------------------*/
1471 	/* No s390-specific optimizations yet 			    */
1472 	/*----------------------------------------------------------*/
1473 	*exclude_mask = MONO_OPT_LINEARS;
1474 	return opts;
1475 }
1476 
1477 /*========================= End of Function ========================*/
1478 
1479 /*------------------------------------------------------------------*/
1480 /*                                                                  */
1481 /* Name		- mono_arch_get_allocatable_int_vars                */
1482 /*                                                                  */
1483 /* Function	-                                                   */
1484 /*		                               			    */
1485 /*------------------------------------------------------------------*/
1486 
1487 GList *
mono_arch_get_allocatable_int_vars(MonoCompile * cfg)1488 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
1489 {
1490 	GList *vars = NULL;
1491 	int i;
1492 
1493 	for (i = 0; i < cfg->num_varinfo; i++) {
1494 		MonoInst *ins = cfg->varinfo [i];
1495 		MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
1496 
1497 		/* unused vars */
1498 		if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
1499 			continue;
1500 
1501 		if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) ||
1502 		    (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
1503 			continue;
1504 
1505 		/* we can only allocate 32 bit values */
1506 		if (mono_is_regsize_var(ins->inst_vtype)) {
1507 			g_assert (MONO_VARINFO (cfg, i)->reg == -1);
1508 			g_assert (i == vmv->idx);
1509 			vars = mono_varlist_insert_sorted (cfg, vars, vmv, FALSE);
1510 		}
1511 	}
1512 
1513 	return vars;
1514 }
1515 
1516 /*========================= End of Function ========================*/
1517 
1518 /*------------------------------------------------------------------*/
1519 /*                                                                  */
1520 /* Name		- mono_arch_global_int_regs                         */
1521 /*                                                                  */
1522 /* Function	- Return a list of usable integer registers.        */
1523 /*		                               			    */
1524 /*------------------------------------------------------------------*/
1525 
1526 GList *
mono_arch_get_global_int_regs(MonoCompile * cfg)1527 mono_arch_get_global_int_regs (MonoCompile *cfg)
1528 {
1529 	GList *regs = NULL;
1530 	MonoMethodHeader *header;
1531 	int i, top = 13;
1532 
1533 	header = cfg->header;
1534 	if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
1535 		cfg->frame_reg = s390_r11;
1536 
1537 
1538 	/* FIXME: s390_r12 is reserved for bkchain_reg. Only reserve it if needed */
1539 	top = 12;
1540 	for (i = 8; i < top; ++i) {
1541 		if ((cfg->frame_reg != i) &&
1542 		    //!((cfg->uses_rgctx_reg) && (i == MONO_ARCH_IMT_REG)))
1543 		    (i != MONO_ARCH_IMT_REG))
1544 			regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
1545 	}
1546 
1547 	return regs;
1548 }
1549 
1550 /*========================= End of Function ========================*/
1551 
1552 /*------------------------------------------------------------------*/
1553 /*                                                                  */
1554 /* Name		-  mono_arch_flush_icache                           */
1555 /*                                                                  */
1556 /* Function	-  Flush the CPU icache.                            */
1557 /*		                               			    */
1558 /*------------------------------------------------------------------*/
1559 
1560 void
mono_arch_flush_icache(guint8 * code,gint size)1561 mono_arch_flush_icache (guint8 *code, gint size)
1562 {
1563 }
1564 
1565 /*========================= End of Function ========================*/
1566 
1567 /*------------------------------------------------------------------*/
1568 /*                                                                  */
1569 /* Name		- add_general                                       */
1570 /*                                                                  */
1571 /* Function	- Determine code and stack size incremements for a  */
1572 /* 		  parameter.                                        */
1573 /*                                                                  */
1574 /*------------------------------------------------------------------*/
1575 
1576 static void inline
add_general(guint * gr,size_data * sz,ArgInfo * ainfo)1577 add_general (guint *gr, size_data *sz, ArgInfo *ainfo)
1578 {
1579 	if (*gr > S390_LAST_ARG_REG) {
1580 		sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1581 		ainfo->offset   = sz->stack_size;
1582 		ainfo->reg	= STK_BASE;
1583 		ainfo->regtype  = RegTypeBase;
1584 		sz->stack_size += sizeof(long);
1585 		sz->local_size += sizeof(long);
1586 		sz->offStruct  += sizeof(long);
1587 		sz->code_size  += 12;
1588 	} else {
1589 		ainfo->reg      = *gr;
1590 		sz->code_size  += 8;
1591 	}
1592 	(*gr) ++;
1593 }
1594 
1595 /*========================= End of Function ========================*/
1596 
1597 /*------------------------------------------------------------------*/
1598 /*                                                                  */
1599 /* Name		- add_stackParm                                     */
1600 /*                                                                  */
1601 /* Function	- Determine code and stack size incremements for a  */
1602 /* 		  parameter.                                        */
1603 /*                                                                  */
1604 /*------------------------------------------------------------------*/
1605 
1606 static void inline
add_stackParm(guint * gr,size_data * sz,ArgInfo * ainfo,gint size)1607 add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size)
1608 {
1609 	if (*gr > S390_LAST_ARG_REG) {
1610 		sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
1611 		ainfo->reg	    = STK_BASE;
1612 		ainfo->offset   = sz->stack_size;
1613 		ainfo->regtype  = RegTypeStructByAddrOnStack;
1614 		sz->stack_size += sizeof (gpointer);
1615 		sz->parm_size  += sizeof(gpointer);
1616 		sz->offStruct  += sizeof(gpointer);
1617 	} else {
1618 		ainfo->reg      = *gr;
1619 		ainfo->offset   = sz->stack_size;
1620 		ainfo->regtype  = RegTypeStructByAddr;
1621 	}
1622 	(*gr) ++;
1623 	ainfo->offparm  = sz->offset;
1624 	sz->offset      = S390_ALIGN(sz->offset+size, sizeof(long));
1625 	ainfo->size     = size;
1626 	ainfo->vtsize   = size;
1627 	sz->parm_size  += size;
1628 }
1629 
1630 /*========================= End of Function ========================*/
1631 
1632 /*------------------------------------------------------------------*/
1633 /*                                                                  */
1634 /* Name		- add_float                                         */
1635 /*                                                                  */
1636 /* Function	- Determine code and stack size incremements for a  */
1637 /* 		  float parameter.                                  */
1638 /*                                                                  */
1639 /*------------------------------------------------------------------*/
1640 
1641 static void inline
add_float(guint * fr,size_data * sz,ArgInfo * ainfo)1642 add_float (guint *fr,  size_data *sz, ArgInfo *ainfo)
1643 {
1644 	if ((*fr) <= S390_LAST_FPARG_REG) {
1645 		ainfo->regtype = RegTypeFP;
1646 		ainfo->reg     = *fr;
1647 		sz->code_size += 4;
1648 		(*fr) += 2;
1649 	}
1650 	else {
1651 		ainfo->offset   = sz->stack_size;
1652 		ainfo->reg      = STK_BASE;
1653 		ainfo->regtype  = RegTypeBase;
1654 		sz->code_size  += 4;
1655 		sz->stack_size += sizeof(double);
1656 		sz->local_size += sizeof(double);
1657 		sz->offStruct  += sizeof(double);
1658 	}
1659 }
1660 
1661 /*========================= End of Function ========================*/
1662 
1663 /*------------------------------------------------------------------*/
1664 /*                                                                  */
1665 /* Name		- get_call_info                                     */
1666 /*                                                                  */
1667 /* Function	- Determine the amount of space required for code   */
1668 /* 		  and stack. In addition determine starting points  */
1669 /*		  for stack-based parameters, and area for struct-  */
1670 /*		  ures being returned on the stack.		    */
1671 /*                                                                  */
1672 /*------------------------------------------------------------------*/
1673 
1674 static CallInfo *
get_call_info(MonoCompile * cfg,MonoMemPool * mp,MonoMethodSignature * sig)1675 get_call_info (MonoCompile *cfg, MonoMemPool *mp, MonoMethodSignature *sig)
1676 {
1677 	guint i, fr, gr, size, pstart;
1678 	int nParm = sig->hasthis + sig->param_count;
1679 	MonoType *ret_type;
1680 	guint32 simpleType, align;
1681 	gboolean is_pinvoke = sig->pinvoke;
1682 	CallInfo *cinfo;
1683 	size_data *sz;
1684 
1685 	if (mp)
1686 		cinfo = mono_mempool_alloc0 (mp, sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1687 	else
1688 		cinfo = g_malloc0 (sizeof (CallInfo) + sizeof (ArgInfo) * nParm);
1689 
1690 	fr                = 0;
1691 	gr                = s390_r2;
1692 	nParm 		  = 0;
1693 	cinfo->struct_ret = 0;
1694 	sz                = &cinfo->sz;
1695 	sz->retStruct     = 0;
1696 	sz->offset        = 0;
1697 	sz->offStruct     = S390_MINIMAL_STACK_SIZE;
1698 	sz->stack_size    = S390_MINIMAL_STACK_SIZE;
1699 	sz->code_size     = 0;
1700 	sz->parm_size     = 0;
1701 	sz->local_size    = 0;
1702 	align		  = 0;
1703 	size		  = 0;
1704 
1705 	/*----------------------------------------------------------*/
1706 	/* We determine the size of the return code/stack in case we*/
1707 	/* need to reserve a register to be used to address a stack */
1708 	/* area that the callee will use.			    */
1709 	/*----------------------------------------------------------*/
1710 
1711 	ret_type = mini_get_underlying_type (sig->ret);
1712 	simpleType = ret_type->type;
1713 enum_retvalue:
1714 	switch (simpleType) {
1715 		case MONO_TYPE_I1:
1716 		case MONO_TYPE_U1:
1717 		case MONO_TYPE_I2:
1718 		case MONO_TYPE_U2:
1719 		case MONO_TYPE_I4:
1720 		case MONO_TYPE_U4:
1721 		case MONO_TYPE_I:
1722 		case MONO_TYPE_U:
1723 		case MONO_TYPE_OBJECT:
1724 		case MONO_TYPE_PTR:
1725 		case MONO_TYPE_FNPTR:
1726 			cinfo->ret.reg = s390_r2;
1727 			sz->code_size += 4;
1728 			break;
1729 		case MONO_TYPE_R4:
1730 		case MONO_TYPE_R8:
1731 			cinfo->ret.reg = s390_f0;
1732 			sz->code_size += 4;
1733 			break;
1734 		case MONO_TYPE_I8:
1735 		case MONO_TYPE_U8:
1736 			cinfo->ret.reg = s390_r2;
1737 			sz->code_size += 4;
1738 			break;
1739 		case MONO_TYPE_GENERICINST:
1740 			if (!mono_type_generic_inst_is_valuetype (sig->ret)) {
1741 				cinfo->ret.reg = s390_r2;
1742 				sz->code_size += 4;
1743 				break;
1744 			}
1745 			/* Fall through */
1746 		case MONO_TYPE_VALUETYPE: {
1747 			MonoClass *klass = mono_class_from_mono_type (sig->ret);
1748 			if (klass->enumtype) {
1749 				simpleType = mono_class_enum_basetype (klass)->type;
1750 				goto enum_retvalue;
1751 			}
1752 			size = mini_type_stack_size_full (&klass->byval_arg, NULL, sig->pinvoke);
1753 
1754 			cinfo->struct_ret = 1;
1755 			cinfo->ret.size   = size;
1756 			cinfo->ret.vtsize = size;
1757                         break;
1758 		}
1759 		case MONO_TYPE_TYPEDBYREF:
1760 			size = sizeof (MonoTypedRef);
1761 			cinfo->struct_ret = 1;
1762 			cinfo->ret.size   = size;
1763 			cinfo->ret.vtsize = size;
1764 			break;
1765 		case MONO_TYPE_VOID:
1766 			break;
1767 		default:
1768 			g_error ("Can't handle as return value 0x%x", sig->ret->type);
1769 	}
1770 
1771 
1772 	pstart = 0;
1773 	/*
1774 	 * To simplify get_this_arg_reg () and LLVM integration, emit the vret arg after
1775 	 * the first argument, allowing 'this' to be always passed in the first arg reg.
1776 	 * Also do this if the first argument is a reference type, since virtual calls
1777 	 * are sometimes made using calli without sig->hasthis set, like in the delegate
1778 	 * invoke wrappers.
1779 	 */
1780 	if (cinfo->struct_ret && !is_pinvoke &&
1781 	    (sig->hasthis ||
1782              (sig->param_count > 0 &&
1783 	      MONO_TYPE_IS_REFERENCE (mini_get_underlying_type (sig->params [0]))))) {
1784 		if (sig->hasthis) {
1785 			cinfo->args[nParm].size = sizeof (gpointer);
1786 			add_general (&gr, sz, cinfo->args + nParm);
1787 		} else {
1788 			cinfo->args[nParm].size = sizeof (gpointer);
1789 			add_general (&gr, sz, &cinfo->args [sig->hasthis + nParm]);
1790 			pstart = 1;
1791 		}
1792 		nParm ++;
1793 		cinfo->vret_arg_index = 1;
1794 		cinfo->ret.reg = gr;
1795 		gr ++;
1796 	} else {
1797 		/* this */
1798 		if (sig->hasthis) {
1799 			cinfo->args[nParm].size = sizeof (gpointer);
1800 			add_general (&gr, sz, cinfo->args + nParm);
1801 			nParm ++;
1802 		}
1803 
1804 		if (cinfo->struct_ret) {
1805 			cinfo->ret.reg = gr;
1806 			gr ++;
1807 		}
1808 	}
1809 
1810 	if ((sig->call_convention == MONO_CALL_VARARG) && (sig->param_count == 0)) {
1811 		gr = S390_LAST_ARG_REG + 1;
1812 		fr = S390_LAST_FPARG_REG + 1;
1813 
1814 		/* Emit the signature cookie just before the implicit arguments */
1815 		add_general (&gr, sz, &cinfo->sigCookie);
1816 	}
1817 
1818 	/*----------------------------------------------------------*/
1819 	/* We determine the size of the parameter code and stack    */
1820 	/* requirements by checking the types and sizes of the      */
1821 	/* parameters.						    */
1822 	/*----------------------------------------------------------*/
1823 
1824 	for (i = pstart; i < sig->param_count; ++i) {
1825 		MonoType *ptype;
1826 
1827 		/*--------------------------------------------------*/
1828 		/* Handle vararg type calls. All args are put on    */
1829 		/* the stack.                                       */
1830 		/*--------------------------------------------------*/
1831 		if ((sig->call_convention == MONO_CALL_VARARG) &&
1832 		    (i == sig->sentinelpos)) {
1833 			gr = S390_LAST_ARG_REG + 1;
1834 			fr = S390_LAST_FPARG_REG + 1;
1835 			add_general (&gr, sz, &cinfo->sigCookie);
1836 		}
1837 
1838 		if (sig->params [i]->byref) {
1839 			add_general (&gr, sz, cinfo->args+nParm);
1840 			cinfo->args[nParm].size = sizeof(gpointer);
1841 			nParm++;
1842 			continue;
1843 		}
1844 
1845 		ptype = mini_get_underlying_type (sig->params [i]);
1846 		simpleType = ptype->type;
1847 		cinfo->args[nParm].type = simpleType;
1848 		switch (simpleType) {
1849 		case MONO_TYPE_I1:
1850 		case MONO_TYPE_U1:
1851 			cinfo->args[nParm].size = sizeof(char);
1852 			add_general (&gr, sz, cinfo->args+nParm);
1853 			nParm++;
1854 			break;
1855 		case MONO_TYPE_I2:
1856 		case MONO_TYPE_U2:
1857 			cinfo->args[nParm].size = sizeof(short);
1858 			add_general (&gr, sz, cinfo->args+nParm);
1859 			nParm++;
1860 			break;
1861 		case MONO_TYPE_I4:
1862 		case MONO_TYPE_U4:
1863 			cinfo->args[nParm].size = sizeof(int);
1864 			add_general (&gr, sz, cinfo->args+nParm);
1865 			nParm++;
1866 			break;
1867 		case MONO_TYPE_I:
1868 		case MONO_TYPE_U:
1869 		case MONO_TYPE_PTR:
1870 		case MONO_TYPE_FNPTR:
1871 		case MONO_TYPE_OBJECT:
1872 			cinfo->args[nParm].size = sizeof(gpointer);
1873 			add_general (&gr, sz, cinfo->args+nParm);
1874 			nParm++;
1875 			break;
1876 		case MONO_TYPE_I8:
1877 		case MONO_TYPE_U8:
1878 			cinfo->args[nParm].size = sizeof(long long);
1879 			add_general (&gr, sz, cinfo->args+nParm);
1880 			nParm++;
1881 			break;
1882 		case MONO_TYPE_R4:
1883 			cinfo->args[nParm].size = sizeof(float);
1884 			add_float (&fr, sz, cinfo->args+nParm);
1885 			nParm++;
1886 			break;
1887 		case MONO_TYPE_R8:
1888 			cinfo->args[nParm].size = sizeof(double);
1889 			add_float (&fr, sz, cinfo->args+nParm);
1890 			nParm++;
1891 			break;
1892 		case MONO_TYPE_GENERICINST:
1893 			if (!mono_type_generic_inst_is_valuetype (ptype)) {
1894 				cinfo->args[nParm].size = sizeof(gpointer);
1895 				add_general (&gr, sz, cinfo->args+nParm);
1896 				nParm++;
1897 				break;
1898 			}
1899 			/* Fall through */
1900 		case MONO_TYPE_VALUETYPE: {
1901 			MonoMarshalType *info;
1902 			MonoClass *klass = mono_class_from_mono_type (ptype);
1903 
1904 			if (sig->pinvoke)
1905 				size = mono_class_native_size(klass, NULL);
1906 			else
1907 				size = mono_class_value_size(klass, NULL);
1908 
1909 			if (simpleType != MONO_TYPE_GENERICINST) {
1910 				info = mono_marshal_load_type_info(klass);
1911 
1912 				if ((info->native_size == sizeof(float)) &&
1913 				    (info->num_fields  == 1) &&
1914 				    (info->fields[0].field->type->type == MONO_TYPE_R4)) {
1915 					cinfo->args[nParm].size = sizeof(float);
1916 					add_float(&fr, sz, cinfo->args+nParm);
1917 					nParm ++;
1918 					break;
1919 				}
1920 
1921 				if ((info->native_size == sizeof(double)) &&
1922 				    (info->num_fields  == 1) &&
1923 				    (info->fields[0].field->type->type == MONO_TYPE_R8)) {
1924 					cinfo->args[nParm].size = sizeof(double);
1925 					add_float(&fr, sz, cinfo->args+nParm);
1926 					nParm ++;
1927 					break;
1928 				}
1929 			}
1930 
1931 			cinfo->args[nParm].vtsize  = 0;
1932 			cinfo->args[nParm].size    = 0;
1933 
1934 			switch (size) {
1935 				/*----------------------------------*/
1936 				/* On S/390, structures of size 1,  */
1937 				/* 2, 4, and 8 bytes are passed in  */
1938 				/* (a) register(s).		    */
1939 				/*----------------------------------*/
1940 				case 0:
1941 				case 1:
1942 				case 2:
1943 				case 4:
1944 				case 8:
1945 					add_general(&gr, sz, cinfo->args+nParm);
1946 					cinfo->args[nParm].size    = size;
1947 					cinfo->args[nParm].regtype = RegTypeStructByVal;
1948 					nParm++;
1949 					sz->local_size 		  += sizeof(long);
1950 					break;
1951 				default:
1952 					add_stackParm(&gr, sz, cinfo->args+nParm, size);
1953 					nParm++;
1954 			}
1955 		}
1956 			break;
1957 		case MONO_TYPE_TYPEDBYREF: {
1958 			int size = sizeof (MonoTypedRef);
1959 
1960 			cinfo->args[nParm].vtsize  = 0;
1961 			cinfo->args[nParm].size    = 0;
1962 
1963 			switch (size) {
1964 				/*----------------------------------*/
1965 				/* On S/390, structures of size 1,  */
1966 				/* 2, 4, and 8 bytes are passed in  */
1967 				/* (a) register(s).		    */
1968 				/*----------------------------------*/
1969 				case 0:
1970 				case 1:
1971 				case 2:
1972 				case 4:
1973 				case 8:
1974 					add_general(&gr, sz, cinfo->args+nParm);
1975 					cinfo->args[nParm].size    = size;
1976 					cinfo->args[nParm].regtype = RegTypeStructByVal;
1977 					nParm++;
1978 					sz->local_size 		  += sizeof(long);
1979 					break;
1980 				default:
1981 					add_stackParm(&gr, sz, cinfo->args+nParm, size);
1982 					nParm++;
1983 			}
1984 		}
1985 			break;
1986 		default:
1987 			g_error ("Can't trampoline 0x%x", ptype);
1988 		}
1989 	}
1990 
1991 	/*----------------------------------------------------------*/
1992 	/* Handle the case where there are no implicit arguments    */
1993 	/*----------------------------------------------------------*/
1994 	if ((sig->call_convention == MONO_CALL_VARARG) &&
1995 	    (nParm > 0) &&
1996 	    (!sig->pinvoke) &&
1997 	    (sig->param_count == sig->sentinelpos)) {
1998 		gr = S390_LAST_ARG_REG + 1;
1999 		fr = S390_LAST_FPARG_REG + 1;
2000 		add_general (&gr, sz, &cinfo->sigCookie);
2001 	}
2002 
2003 	/*----------------------------------------------------------*/
2004 	/* If we are passing a structure back then if it won't be   */
2005 	/* in a register(s) then we make room at the end of the     */
2006 	/* parameters that may have been placed on the stack        */
2007 	/*----------------------------------------------------------*/
2008 	if (cinfo->struct_ret) {
2009 		cinfo->ret.offset = sz->stack_size;
2010 		switch (cinfo->ret.size) {
2011 		case 0:
2012 		case 1:
2013 		case 2:
2014 		case 4:
2015 		case 8:
2016 			break;
2017 		default:
2018 			sz->stack_size   += S390_ALIGN(cinfo->ret.size, align);
2019 		}
2020 	}
2021 
2022 	cinfo->lastgr   = gr;
2023 	sz->stack_size  = sz->stack_size + sz->local_size + sz->parm_size +
2024 			  sz->offset;
2025 	sz->stack_size  = S390_ALIGN(sz->stack_size, sizeof(long));
2026 
2027 	return (cinfo);
2028 }
2029 
2030 /*========================= End of Function ========================*/
2031 
2032 /*------------------------------------------------------------------*/
2033 /*                                                                  */
2034 /* Name		- mono_arch_allocate_vars                           */
2035 /*                                                                  */
2036 /* Function	- Set var information according to the calling      */
2037 /*		  convention for S/390. The local var stuff should  */
2038 /*		  most likely be split in another method.	    */
2039 /*		                               			    */
2040 /* Parameter    - @m - Compile unit.          			    */
2041 /*		                               			    */
2042 /*------------------------------------------------------------------*/
2043 
2044 void
mono_arch_allocate_vars(MonoCompile * cfg)2045 mono_arch_allocate_vars (MonoCompile *cfg)
2046 {
2047 	MonoMethodSignature *sig;
2048 	MonoMethodHeader *header;
2049 	MonoInst *inst;
2050 	CallInfo *cinfo;
2051 	int iParm, iVar, offset, align, size, curinst;
2052 	int frame_reg = STK_BASE;
2053 	int sArg, eArg;
2054 
2055 	header  = cfg->header;
2056 
2057 	cfg->flags |= MONO_CFG_HAS_SPILLUP;
2058 
2059 	/*---------------------------------------------------------*/
2060 	/* We use the frame register also for any method that has  */
2061 	/* filter clauses. This way, when the handlers are called, */
2062 	/* the code will reference local variables using the frame */
2063 	/* reg instead of the stack pointer: if we had to restore  */
2064 	/* the stack pointer, we'd corrupt the method frames that  */
2065 	/* are already on the stack (since filters get called      */
2066 	/* before stack unwinding happens) when the filter code    */
2067 	/* would call any method.				   */
2068 	/*---------------------------------------------------------*/
2069 	if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2070 		frame_reg = s390_r11;
2071 
2072 	cfg->frame_reg = frame_reg;
2073 
2074 	cfg->arch.bkchain_reg = -1;
2075 
2076 	if (frame_reg != STK_BASE)
2077 		cfg->used_int_regs |= (1LL << frame_reg);
2078 
2079 	sig     = mono_method_signature (cfg->method);
2080 
2081 	cinfo   = get_call_info (cfg, cfg->mempool, sig);
2082 
2083 	if (!cinfo->struct_ret) {
2084 		switch (mini_get_underlying_type (sig->ret)->type) {
2085 		case MONO_TYPE_VOID:
2086 			break;
2087 		default:
2088 			cfg->ret->opcode = OP_REGVAR;
2089 			cfg->ret->dreg   = s390_r2;
2090 			break;
2091 		}
2092 	}
2093 
2094 	/*--------------------------------------------------------------*/
2095 	/* local vars are at a positive offset from the stack pointer 	*/
2096 	/* also note that if the function uses alloca, we use s390_r11	*/
2097 	/* to point at the local variables.				*/
2098 	/* add parameter area size for called functions 		*/
2099 	/*--------------------------------------------------------------*/
2100 	if (cfg->param_area == 0)
2101 		offset = S390_MINIMAL_STACK_SIZE;
2102 	else
2103 		offset = cfg->param_area;
2104 
2105 	cfg->sig_cookie = 0;
2106 
2107 	if (cinfo->struct_ret) {
2108 		inst 		   = cfg->vret_addr;
2109 		offset 		   = S390_ALIGN(offset, sizeof(gpointer));
2110 		inst->inst_offset  = offset;
2111 		inst->opcode 	   = OP_REGOFFSET;
2112 		inst->inst_basereg = frame_reg;
2113 		offset 		  += sizeof(gpointer);
2114 		if (G_UNLIKELY (cfg->verbose_level > 1)) {
2115 			printf ("vret_addr =");
2116 			mono_print_ins (cfg->vret_addr);
2117 		}
2118 	}
2119 
2120 	if (sig->hasthis) {
2121 		inst = cfg->args [0];
2122 		if (inst->opcode != OP_REGVAR) {
2123 			inst->opcode 	   = OP_REGOFFSET;
2124 			inst->inst_basereg = frame_reg;
2125 			offset 		   = S390_ALIGN(offset, sizeof(gpointer));
2126 			inst->inst_offset  = offset;
2127 			offset 		  += sizeof (gpointer);
2128 		}
2129 		curinst = sArg = 1;
2130 	} else {
2131 		curinst = sArg = 0;
2132 	}
2133 
2134 	eArg = sig->param_count + sArg;
2135 
2136 	if (sig->call_convention == MONO_CALL_VARARG)
2137 		cfg->sig_cookie += S390_MINIMAL_STACK_SIZE;
2138 
2139 	for (iParm = sArg; iParm < eArg; ++iParm) {
2140 		inst = cfg->args [curinst];
2141 		if (inst->opcode != OP_REGVAR) {
2142 			switch (cinfo->args[iParm].regtype) {
2143 			case RegTypeStructByAddr : {
2144 				MonoInst *indir;
2145 
2146 				size = sizeof (gpointer);
2147 
2148 				inst->opcode       = OP_REGOFFSET;
2149 				inst->inst_basereg = frame_reg;
2150 				offset             = S390_ALIGN (offset, sizeof (gpointer));
2151 				inst->inst_offset  = offset;
2152 
2153 				/* Add a level of indirection */
2154 				MONO_INST_NEW (cfg, indir, 0);
2155 				*indir          = *inst;
2156 				inst->opcode    = OP_VTARG_ADDR;
2157 				inst->inst_left = indir;
2158 			}
2159 				break;
2160 			case RegTypeStructByAddrOnStack : {
2161 				MonoInst *indir;
2162 
2163 				size = sizeof (gpointer);
2164 
2165 				/* Similar to the == STK_BASE case below */
2166 				cfg->arch.bkchain_reg = s390_r12;
2167 				cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2168 
2169 				inst->opcode = OP_REGOFFSET;
2170 				inst->dreg = mono_alloc_preg (cfg);
2171 				inst->inst_basereg = cfg->arch.bkchain_reg;
2172 				inst->inst_offset = cinfo->args [iParm].offset;
2173 
2174 				/* Add a level of indirection */
2175 				MONO_INST_NEW (cfg, indir, 0);
2176 				*indir = *inst;
2177 				inst->opcode = OP_VTARG_ADDR;
2178 				inst->inst_left = indir;
2179 				break;
2180 			}
2181 			case RegTypeStructByVal :
2182 				size		   = cinfo->args[iParm].size;
2183 				offset		   = S390_ALIGN(offset, size);
2184 				inst->opcode       = OP_REGOFFSET;
2185 				inst->inst_basereg = frame_reg;
2186 				inst->inst_offset  = offset;
2187 				break;
2188 			default :
2189 				if (cinfo->args [iParm].reg == STK_BASE) {
2190 					/*
2191 					 * These arguments are in the previous frame, so we can't
2192 					 * compute their offset from the current frame pointer right
2193 					 * now, since cfg->stack_offset is not yet known, so dedicate a
2194 					 * register holding the previous frame pointer.
2195 					 */
2196 					cfg->arch.bkchain_reg = s390_r12;
2197 					cfg->used_int_regs |= 1 << cfg->arch.bkchain_reg;
2198 
2199 					inst->opcode 	   = OP_REGOFFSET;
2200 					inst->inst_basereg = cfg->arch.bkchain_reg;
2201 					size		   = (cinfo->args[iParm].size < 8
2202 									  ? 8 - cinfo->args[iParm].size
2203 									  : 0);
2204 					inst->inst_offset  = cinfo->args [iParm].offset + size;
2205 					size = sizeof (long);
2206 				} else {
2207 					inst->opcode 	   = OP_REGOFFSET;
2208 					inst->inst_basereg = frame_reg;
2209 					size		   = (cinfo->args[iParm].size < 8
2210 									  ? sizeof(int)
2211 									  : sizeof(long));
2212 					offset		   = S390_ALIGN(offset, size);
2213 					if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2214 						inst->inst_offset  = offset;
2215 					else
2216 						inst->inst_offset  = offset + (8 - size);
2217 				}
2218 				break;
2219 			}
2220 			offset += MAX(size, 8);
2221 		}
2222 		curinst++;
2223 	}
2224 
2225 	cfg->locals_min_stack_offset = offset;
2226 
2227 	curinst = cfg->locals_start;
2228 	for (iVar = curinst; iVar < cfg->num_varinfo; ++iVar) {
2229 		inst = cfg->varinfo [iVar];
2230 		if ((inst->flags & MONO_INST_IS_DEAD) ||
2231 		    (inst->opcode == OP_REGVAR))
2232 			continue;
2233 
2234 		/*--------------------------------------------------*/
2235 		/* inst->backend.is_pinvoke indicates native sized  */
2236 		/* value typs this is used by the pinvoke wrappers  */
2237 		/* when they call functions returning structure     */
2238 		/*--------------------------------------------------*/
2239 		if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (inst->inst_vtype))
2240 			size = mono_class_native_size (mono_class_from_mono_type(inst->inst_vtype),
2241 						       (guint32 *) &align);
2242 		else
2243 			size = mono_type_size (inst->inst_vtype, &align);
2244 
2245 		offset 		   = S390_ALIGN(offset, align);
2246 		inst->inst_offset  = offset;
2247 		inst->opcode 	   = OP_REGOFFSET;
2248 		inst->inst_basereg = frame_reg;
2249 		offset 		  += size;
2250 		DEBUG (g_print("allocating local %d to %ld, size: %d\n",
2251 				iVar, inst->inst_offset, size));
2252 	}
2253 
2254 	cfg->locals_max_stack_offset = offset;
2255 
2256 	/*------------------------------------------------------*/
2257 	/* Allow space for the trace method stack area if needed*/
2258 	/*------------------------------------------------------*/
2259 	if ((mono_jit_trace_calls != NULL && mono_trace_eval (cfg->method)))
2260 		offset += S390_TRACE_STACK_SIZE;
2261 
2262 	/*------------------------------------------------------*/
2263 	/* Reserve space to save LMF and caller saved registers */
2264 	/*------------------------------------------------------*/
2265 	if (cfg->method->save_lmf)
2266 		offset += sizeof (MonoLMF);
2267 
2268 	/*------------------------------------------------------*/
2269 	/* align the offset 					*/
2270 	/*------------------------------------------------------*/
2271 	cfg->stack_offset = S390_ALIGN(offset, S390_STACK_ALIGNMENT);
2272 
2273 	/*------------------------------------------------------*/
2274 	/* Fix offsets for args whose value is in parent frame  */
2275 	/*------------------------------------------------------*/
2276 	for (iParm = sArg; iParm < eArg; ++iParm) {
2277 		inst = cfg->args [iParm];
2278 
2279 		if (inst->opcode == OP_S390_STKARG) {
2280 			inst->opcode = OP_REGOFFSET;
2281 			inst->inst_offset += cfg->stack_offset;
2282 		}
2283 	}
2284 }
2285 
2286 /*========================= End of Function ========================*/
2287 
2288 /*------------------------------------------------------------------*/
2289 /*                                                                  */
2290 /* Name		- mono_arch_create_vars                             */
2291 /*                                                                  */
2292 /*------------------------------------------------------------------*/
2293 
2294 void
mono_arch_create_vars(MonoCompile * cfg)2295 mono_arch_create_vars (MonoCompile *cfg)
2296 {
2297 	MonoMethodSignature *sig;
2298 	CallInfo *cinfo;
2299 
2300 	sig = mono_method_signature (cfg->method);
2301 
2302 	cinfo = get_call_info (cfg, cfg->mempool, sig);
2303 
2304 	if (cinfo->struct_ret) {
2305 		cfg->vret_addr = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_ARG);
2306 		if (G_UNLIKELY (cfg->verbose_level > 1)) {
2307 			printf ("vret_addr = ");
2308 			mono_print_ins (cfg->vret_addr);
2309 		}
2310 	}
2311 }
2312 
2313 /*========================= End of Function ========================*/
2314 
2315 /*------------------------------------------------------------------*/
2316 /*                                                                  */
2317 /* Name		- add_outarg_reg2.                                  */
2318 /*                                                                  */
2319 /*------------------------------------------------------------------*/
2320 
2321 static void
add_outarg_reg2(MonoCompile * cfg,MonoCallInst * call,ArgStorage storage,int reg,MonoInst * tree)2322 add_outarg_reg2 (MonoCompile *cfg, MonoCallInst *call, ArgStorage storage, int reg, MonoInst *tree)
2323 {
2324 	MonoInst *ins;
2325 
2326 	switch (storage) {
2327 	case RegTypeGeneral:
2328 		MONO_INST_NEW (cfg, ins, OP_MOVE);
2329 		ins->dreg = mono_alloc_ireg (cfg);
2330 		ins->sreg1 = tree->dreg;
2331 		MONO_ADD_INS (cfg->cbb, ins);
2332 		mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, FALSE);
2333 		break;
2334 	case RegTypeFP:
2335 		MONO_INST_NEW (cfg, ins, OP_FMOVE);
2336 		ins->dreg = mono_alloc_freg (cfg);
2337 		ins->sreg1 = tree->dreg;
2338 		MONO_ADD_INS (cfg->cbb, ins);
2339 		mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2340 		break;
2341 	case RegTypeFPR4:
2342 		MONO_INST_NEW (cfg, ins, OP_S390_SETF4RET);
2343 		ins->dreg = mono_alloc_freg (cfg);
2344 		ins->sreg1 = tree->dreg;
2345 		MONO_ADD_INS (cfg->cbb, ins);
2346 		mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, reg, TRUE);
2347 		break;
2348 	default:
2349 		g_assert_not_reached ();
2350 	}
2351 }
2352 
2353 /*========================= End of Function ========================*/
2354 
2355 /*------------------------------------------------------------------*/
2356 /*                                                                  */
2357 /* Name		- emit_sig_cookie.                                  */
2358 /*                                                                  */
2359 /*------------------------------------------------------------------*/
2360 
2361 static void
emit_sig_cookie(MonoCompile * cfg,MonoCallInst * call,CallInfo * cinfo)2362 emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
2363 {
2364 	MonoMethodSignature *tmpSig;
2365 	MonoInst *sig_arg;
2366 
2367 	cfg->disable_aot = TRUE;
2368 
2369 	/*----------------------------------------------------------*/
2370 	/* mono_ArgIterator_Setup assumes the signature cookie is   */
2371 	/* passed first and all the arguments which were before it  */
2372 	/* passed on the stack after the signature. So compensate   */
2373 	/* by passing a different signature.			    */
2374 	/*----------------------------------------------------------*/
2375 	tmpSig = mono_metadata_signature_dup (call->signature);
2376 	tmpSig->param_count -= call->signature->sentinelpos;
2377 	tmpSig->sentinelpos  = 0;
2378 	if (tmpSig->param_count > 0)
2379 		memcpy (tmpSig->params,
2380 			call->signature->params + call->signature->sentinelpos,
2381 			tmpSig->param_count * sizeof(MonoType *));
2382 
2383 	MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
2384 	sig_arg->dreg = mono_alloc_ireg (cfg);
2385 	sig_arg->inst_p0 = tmpSig;
2386 	MONO_ADD_INS (cfg->cbb, sig_arg);
2387 
2388 	MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, STK_BASE,
2389 				     cinfo->sigCookie.offset, sig_arg->dreg);
2390 }
2391 
2392 /*========================= End of Function ========================*/
2393 
2394 /*------------------------------------------------------------------*/
2395 /*                                                                  */
2396 /* Name		- mono_arch_emit_call                               */
2397 /*                                                                  */
2398 /*------------------------------------------------------------------*/
2399 
2400 void
mono_arch_emit_call(MonoCompile * cfg,MonoCallInst * call)2401 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
2402 {
2403 	MonoInst *in;
2404 	MonoMethodSignature *sig;
2405 	MonoInst *ins;
2406 	int i, n, lParamArea;
2407 	CallInfo *cinfo;
2408 	ArgInfo *ainfo = NULL;
2409 	int stackSize;
2410 	MonoMethodHeader *header;
2411 	int frmReg;
2412 
2413 	sig = call->signature;
2414 	n = sig->param_count + sig->hasthis;
2415 	DEBUG (g_print ("Call requires: %d parameters\n",n));
2416 
2417 	cinfo = get_call_info (cfg, cfg->mempool, sig);
2418 
2419 	stackSize         = cinfo->sz.stack_size + cinfo->sz.local_size +
2420 			    cinfo->sz.parm_size + cinfo->sz.offset;
2421 	call->stack_usage = MAX(stackSize, call->stack_usage);
2422 	lParamArea        = MAX((call->stack_usage-S390_MINIMAL_STACK_SIZE-cinfo->sz.parm_size), 0);
2423 	cfg->param_area   = MAX(((signed) cfg->param_area), lParamArea);
2424 	cfg->flags       |= MONO_CFG_HAS_CALLS;
2425 
2426 	if (cinfo->struct_ret) {
2427 		MONO_INST_NEW (cfg, ins, OP_MOVE);
2428 		ins->sreg1 = call->vret_var->dreg;
2429 		ins->dreg = mono_alloc_preg (cfg);
2430 		MONO_ADD_INS (cfg->cbb, ins);
2431 		mono_call_inst_add_outarg_reg (cfg, call, ins->dreg, cinfo->ret.reg, FALSE);
2432 	}
2433 
2434 	header = cfg->header;
2435 	if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2436 		frmReg = s390_r11;
2437 	else
2438 		frmReg = STK_BASE;
2439 
2440 	for (i = 0; i < n; ++i) {
2441 		MonoType *t;
2442 
2443 		ainfo = cinfo->args + i;
2444 		if (i >= sig->hasthis)
2445 			t = sig->params [i - sig->hasthis];
2446 		else
2447 			t = &mono_defaults.int_class->byval_arg;
2448 		t = mini_get_underlying_type (t);
2449 
2450 		in = call->args [i];
2451 
2452 		if ((sig->call_convention == MONO_CALL_VARARG) &&
2453 		    (!sig->pinvoke) &&
2454 		    (i == sig->sentinelpos)) {
2455 			emit_sig_cookie (cfg, call, cinfo);
2456 		}
2457 
2458 		switch (ainfo->regtype) {
2459 		case RegTypeGeneral:
2460 			add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2461 			break;
2462 		case RegTypeFP:
2463 			if (MONO_TYPE_ISSTRUCT (t)) {
2464 				/* Valuetype passed in one fp register */
2465 				ainfo->regtype = RegTypeStructByValInFP;
2466 				/* Fall through */
2467 			} else {
2468 				if (ainfo->size == 4)
2469 					ainfo->regtype = RegTypeFPR4;
2470 				add_outarg_reg2 (cfg, call, ainfo->regtype, ainfo->reg, in);
2471 				break;
2472 			}
2473 		case RegTypeStructByVal:
2474 		case RegTypeStructByAddr:
2475 		case RegTypeStructByAddrOnStack: {
2476 			guint32 align;
2477 			guint32 size;
2478 
2479 			if (sig->params [i - sig->hasthis]->type == MONO_TYPE_TYPEDBYREF) {
2480 				size = sizeof (MonoTypedRef);
2481 				align = sizeof (gpointer);
2482 			}
2483 			else
2484 				if (sig->pinvoke)
2485 					size = mono_type_native_stack_size (&in->klass->byval_arg, &align);
2486 				else {
2487 					/*
2488 					 * Other backends use mono_type_stack_size (), but that
2489 					 * aligns the size to 8, which is larger than the size of
2490 					 * the source, leading to reads of invalid memory if the
2491 					 * source is at the end of address space.
2492 					 */
2493 					size = mono_class_value_size (in->klass, &align);
2494 				}
2495 
2496 			g_assert (in->klass);
2497 
2498 			ainfo->offparm += cinfo->sz.offStruct;
2499 
2500 			MONO_INST_NEW (cfg, ins, OP_OUTARG_VT);
2501 			ins->sreg1 = in->dreg;
2502 			ins->klass = in->klass;
2503 			ins->backend.size = ainfo->size;
2504 			ins->inst_p0 = call;
2505 			ins->inst_p1 = mono_mempool_alloc (cfg->mempool, sizeof (ArgInfo));
2506 			memcpy (ins->inst_p1, ainfo, sizeof (ArgInfo));
2507 
2508 			MONO_ADD_INS (cfg->cbb, ins);
2509 
2510 			if (ainfo->regtype == RegTypeStructByAddr) {
2511 				/*
2512 				 * We use OP_OUTARG_VT to copy the valuetype to a stack location, then
2513 				 * use the normal OUTARG opcodes to pass the address of the location to
2514 				 * the callee.
2515 				 */
2516 				int treg = mono_alloc_preg (cfg);
2517 				MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2518 							 frmReg, ainfo->offparm);
2519 				mono_call_inst_add_outarg_reg (cfg, call, treg, ainfo->reg, FALSE);
2520 			} else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
2521 				/* The address of the valuetype is passed on the stack */
2522 				int treg = mono_alloc_preg (cfg);
2523 				MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, treg,
2524 							 frmReg, ainfo->offparm);
2525 				MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG,
2526 							     ainfo->reg, ainfo->offset, treg);
2527 
2528 				if (cfg->compute_gc_maps) {
2529 					MonoInst *def;
2530 
2531 					EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, t);
2532 				}
2533 			}
2534 			break;
2535 		}
2536 		case RegTypeBase:
2537 			if (!t->byref && t->type == MONO_TYPE_R4) {
2538 				MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER4_MEMBASE_REG,
2539 							     STK_BASE, ainfo->offset + 4,
2540 						  	     in->dreg);
2541 			} else if (!t->byref && (t->type == MONO_TYPE_R8)) {
2542 				MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORER8_MEMBASE_REG,
2543 						  	     STK_BASE, ainfo->offset,
2544 							     in->dreg);
2545 			} else {
2546 				MONO_INST_NEW (cfg, ins, OP_STORE_MEMBASE_REG);
2547 				ins->inst_destbasereg = STK_BASE;
2548 				ins->inst_offset = ainfo->offset;
2549 				ins->sreg1 = in->dreg;
2550 				MONO_ADD_INS (cfg->cbb, ins);
2551 			}
2552 			break;
2553 		default:
2554 			g_assert_not_reached ();
2555 			break;
2556 		}
2557 	}
2558 
2559 	/*
2560 	 * Handle the case where there are no implicit arguments
2561 	 */
2562 	if ((sig->call_convention == MONO_CALL_VARARG) &&
2563 	    (!sig->pinvoke) &&
2564 	    (i == sig->sentinelpos)) {
2565 		emit_sig_cookie (cfg, call, cinfo);
2566 	}
2567 }
2568 
2569 /*========================= End of Function ========================*/
2570 
2571 /*------------------------------------------------------------------*/
2572 /*                                                                  */
2573 /* Name		- mono_arch_emit_outarg_vt                          */
2574 /*                                                                  */
2575 /*------------------------------------------------------------------*/
2576 
2577 void
mono_arch_emit_outarg_vt(MonoCompile * cfg,MonoInst * ins,MonoInst * src)2578 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
2579 {
2580 	MonoCallInst *call = (MonoCallInst*)ins->inst_p0;
2581 	ArgInfo *ainfo = (ArgInfo*)ins->inst_p1;
2582 	int size = ins->backend.size;
2583 
2584 	if (ainfo->regtype == RegTypeStructByVal) {
2585 		/*
2586 				arg->ins.sreg1  = ainfo->reg;
2587 				arg->ins.opcode = OP_OUTARG_VT;
2588 				arg->size       = ainfo->size;
2589 				arg->offset     = ainfo->offset;
2590 				arg->offPrm     = ainfo->offparm + cinfo->sz.offStruct;
2591 		*/
2592 		if (ainfo->reg != STK_BASE) {
2593 			MONO_OUTPUT_VTR (cfg, size, ainfo->reg, src->dreg, 0);
2594 		} else {
2595 			MONO_OUTPUT_VTS (cfg, size, ainfo->reg, ainfo->offset,
2596 							  src->dreg, 0);
2597 		}
2598 	} else if (ainfo->regtype == RegTypeStructByValInFP) {
2599 		int dreg = mono_alloc_freg (cfg);
2600 
2601 		if (ainfo->size == 4) {
2602 			MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR4_MEMBASE, dreg, src->dreg, 0);
2603 			MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, dreg, dreg);
2604 		} else {
2605 			g_assert (ainfo->size == 8);
2606 
2607 			MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADR8_MEMBASE, dreg, src->dreg, 0);
2608 		}
2609 
2610 		mono_call_inst_add_outarg_reg (cfg, call, dreg, ainfo->reg, TRUE);
2611 	} else {
2612 		MonoError error;
2613 		MonoMethodHeader *header;
2614 		int srcReg;
2615 
2616 		header = mono_method_get_header_checked (cfg->method, &error);
2617 		mono_error_assert_ok (&error); /* FIXME don't swallow the error */
2618 		if ((cfg->flags & MONO_CFG_HAS_ALLOCA) || header->num_clauses)
2619 			srcReg = s390_r11;
2620 		else
2621 			srcReg = STK_BASE;
2622 
2623 		MONO_EMIT_NEW_MOVE (cfg, srcReg, ainfo->offparm,
2624 							 src->dreg, 0, size);
2625 
2626 		if (cfg->compute_gc_maps) {
2627 			MonoInst *def;
2628 
2629 			EMIT_NEW_GC_PARAM_SLOT_LIVENESS_DEF (cfg, def, ainfo->offset, &ins->klass->byval_arg);
2630 		}
2631 	}
2632 }
2633 
2634 /*========================= End of Function ========================*/
2635 
2636 /*------------------------------------------------------------------*/
2637 /*                                                                  */
2638 /* Name		- mono_arch_emit_setret                             */
2639 /*                                                                  */
2640 /*------------------------------------------------------------------*/
2641 
2642 void
mono_arch_emit_setret(MonoCompile * cfg,MonoMethod * method,MonoInst * val)2643 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
2644 {
2645 	MonoType *ret = mini_get_underlying_type (mono_method_signature (method)->ret);
2646 
2647 	if (!ret->byref) {
2648 		if (ret->type == MONO_TYPE_R4) {
2649 			MONO_EMIT_NEW_UNALU (cfg, OP_S390_SETF4RET, s390_f0, val->dreg);
2650 			return;
2651 		} else if (ret->type == MONO_TYPE_R8) {
2652 			MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, s390_f0, val->dreg);
2653 			return;
2654 		}
2655 	}
2656 
2657 	MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->ret->dreg, val->dreg);
2658 }
2659 
2660 /*========================= End of Function ========================*/
2661 
2662 /*------------------------------------------------------------------*/
2663 /*                                                                  */
2664 /* Name		- mono_arch_instrument_mem_needs                    */
2665 /*                                                                  */
2666 /* Function	- Allow tracing to work with this interface (with   */
2667 /*		  an optional argument).       			    */
2668 /*		                               			    */
2669 /*------------------------------------------------------------------*/
2670 
2671 void
mono_arch_instrument_mem_needs(MonoMethod * method,int * stack,int * code)2672 mono_arch_instrument_mem_needs (MonoMethod *method, int *stack, int *code)
2673 {
2674 	/* no stack room needed now (may be needed for FASTCALL-trace support) */
2675 	*stack = 0;
2676 	/* split prolog-epilog requirements? */
2677 	*code = 50; /* max bytes needed: check this number */
2678 }
2679 
2680 /*========================= End of Function ========================*/
2681 
2682 /*------------------------------------------------------------------*/
2683 /*                                                                  */
2684 /* Name		- mono_arch_instrument_prolog                       */
2685 /*                                                                  */
2686 /* Function	- Create an "instrumented" prolog.                  */
2687 /*		                               			    */
2688 /*------------------------------------------------------------------*/
2689 
2690 void*
mono_arch_instrument_prolog(MonoCompile * cfg,void * func,void * p,gboolean enable_arguments)2691 mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p,
2692 			     gboolean enable_arguments)
2693 {
2694 	guchar 	*code = p;
2695 	int 	parmOffset,
2696 	    	fpOffset,
2697 		baseReg;
2698 
2699 	parmOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2700 	if (cfg->method->save_lmf)
2701 		parmOffset -= sizeof(MonoLMF);
2702 	fpOffset   = parmOffset + (5*sizeof(gpointer));
2703 	baseReg = STK_BASE;
2704 
2705 	s390_stmg (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2706 	s390_stdy (code, s390_f0, 0, STK_BASE, fpOffset);
2707 	s390_stdy (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2708 	s390_stdy (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2709 	s390_stdy (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2710 	S390_SET  (code, s390_r1, func);
2711 	S390_SET  (code, s390_r2, cfg->method);
2712 	s390_lay  (code, s390_r3, 0, STK_BASE, parmOffset);
2713 	s390_lgr  (code, s390_r4, STK_BASE);
2714 	s390_aghi (code, s390_r4, cfg->stack_usage);
2715 	s390_basr (code, s390_r14, s390_r1);
2716 	s390_ldy  (code, s390_f6, 0, STK_BASE, fpOffset+3*sizeof(gdouble));
2717 	s390_ldy  (code, s390_f4, 0, STK_BASE, fpOffset+2*sizeof(gdouble));
2718 	s390_ldy  (code, s390_f2, 0, STK_BASE, fpOffset+sizeof(gdouble));
2719 	s390_ldy  (code, s390_f0, 0, STK_BASE, fpOffset);
2720 	s390_lmg  (code, s390_r2, s390_r6, STK_BASE, parmOffset);
2721 
2722 	return code;
2723 }
2724 
2725 /*========================= End of Function ========================*/
2726 
2727 /*------------------------------------------------------------------*/
2728 /*                                                                  */
2729 /* Name		- mono_arch_instrument_epilog                       */
2730 /*                                                                  */
2731 /* Function	- Create an epilog that will handle the returned    */
2732 /*		  values used in instrumentation.		    */
2733 /*		                               			    */
2734 /*------------------------------------------------------------------*/
2735 
2736 void*
mono_arch_instrument_epilog_full(MonoCompile * cfg,void * func,void * p,gboolean enable_arguments,gboolean preserve_argument_registers)2737 mono_arch_instrument_epilog_full (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments, gboolean preserve_argument_registers)
2738 {
2739 	guchar 	   *code = p;
2740 	int   	   save_mode = SAVE_NONE,
2741 		   saveOffset,
2742 		   offset;
2743 	MonoMethod *method = cfg->method;
2744 	int rtype = mini_get_underlying_type (mono_method_signature (method)->ret)->type;
2745 
2746 	offset = code - cfg->native_code;
2747 	/*-----------------------------------------*/
2748 	/* We need about 128 bytes of instructions */
2749 	/*-----------------------------------------*/
2750 	if (offset > (cfg->code_size - 128)) {
2751 		cfg->code_size *= 2;
2752 		cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
2753 		code = cfg->native_code + offset;
2754 	}
2755 
2756 	saveOffset = cfg->stack_usage - S390_TRACE_STACK_SIZE;
2757 	if (method->save_lmf)
2758 		saveOffset -= sizeof(MonoLMF);
2759 
2760 handle_enum:
2761 	switch (rtype) {
2762 	case MONO_TYPE_VOID:
2763 		/* special case string .ctor icall */
2764 		if (strcmp (".ctor", method->name) && method->klass == mono_defaults.string_class)
2765 			save_mode = SAVE_ONE;
2766 		else
2767 			save_mode = SAVE_NONE;
2768 		break;
2769 	case MONO_TYPE_I8:
2770 	case MONO_TYPE_U8:
2771 		save_mode = SAVE_ONE;
2772 		break;
2773 	case MONO_TYPE_R4:
2774 		save_mode = SAVE_R4;
2775 		break;
2776 	case MONO_TYPE_R8:
2777 		save_mode = SAVE_R8;
2778 		break;
2779 	case MONO_TYPE_VALUETYPE:
2780 		if (mono_method_signature (method)->ret->data.klass->enumtype) {
2781 			rtype = mono_class_enum_basetype (mono_method_signature (method)->ret->data.klass)->type;
2782 			goto handle_enum;
2783 		}
2784 		save_mode = SAVE_STRUCT;
2785 		break;
2786 	default:
2787 		save_mode = SAVE_ONE;
2788 		break;
2789 	}
2790 
2791 	switch (save_mode) {
2792 	case SAVE_ONE:
2793 		s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2794 		if (enable_arguments) {
2795 			s390_lgr (code, s390_r3, s390_r2);
2796 		}
2797 		break;
2798 	case SAVE_R4:
2799 		s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2800 		if (enable_arguments) {
2801 			s390_ldebr (code, s390_f0, s390_f0);
2802 		}
2803 		break;
2804 	case SAVE_R8:
2805 		s390_std (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2806 		break;
2807 	case SAVE_STRUCT:
2808 		s390_stg (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2809 		if (enable_arguments) {
2810 			s390_lg (code, s390_r3, 0, cfg->frame_reg,
2811 				 S390_MINIMAL_STACK_SIZE+cfg->param_area);
2812 		}
2813 		break;
2814 	case SAVE_NONE:
2815 	default:
2816 		break;
2817 	}
2818 
2819 	S390_SET  (code, s390_r1, func);
2820 	S390_SET  (code, s390_r2, cfg->method);
2821 	s390_basr (code, s390_r14, s390_r1);
2822 
2823 	switch (save_mode) {
2824 	case SAVE_ONE:
2825 		s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2826 		break;
2827 	case SAVE_R4:
2828 	case SAVE_R8:
2829 		s390_ld  (code, s390_f0, 0, cfg->frame_reg, saveOffset);
2830 		break;
2831 	case SAVE_STRUCT:
2832 		s390_lg  (code, s390_r2, 0, cfg->frame_reg, saveOffset);
2833 		break;
2834 	case SAVE_NONE:
2835 	default:
2836 		break;
2837 	}
2838 
2839 	return code;
2840 }
2841 
2842 /*========================= End of Function ========================*/
2843 
2844 /*------------------------------------------------------------------*/
2845 /*                                                                  */
2846 /* Name		- compare_and_branch                                */
2847 /*                                                                  */
2848 /* Function	- Form a peephole pass at the code looking for      */
2849 /*		  simple optimizations.        			    */
2850 /*		                               			    */
2851 /*------------------------------------------------------------------*/
2852 
2853 static void
compare_and_branch(MonoBasicBlock * bb,MonoInst * ins,int cc,gboolean logical)2854 compare_and_branch(MonoBasicBlock *bb, MonoInst *ins, int cc, gboolean logical)
2855 {
2856 	MonoInst *last;
2857 
2858 	if (mono_hwcap_s390x_has_gie) {
2859 		last = mono_inst_prev (ins, FILTER_IL_SEQ_POINT);
2860 		ins->sreg1 = last->sreg1;
2861 		ins->sreg2 = last->sreg2;
2862 		ins->sreg3 = cc;
2863 		switch(last->opcode) {
2864 		case OP_ICOMPARE:
2865 			if (logical)
2866 				ins->opcode = OP_S390_CLRJ;
2867 			else
2868 				ins->opcode = OP_S390_CRJ;
2869 			MONO_DELETE_INS(bb, last);
2870 			break;
2871 		case OP_COMPARE:
2872 		case OP_LCOMPARE:
2873 			if (logical)
2874 				ins->opcode = OP_S390_CLGRJ;
2875 			else
2876 				ins->opcode = OP_S390_CGRJ;
2877 			MONO_DELETE_INS(bb, last);
2878 			break;
2879 		case OP_ICOMPARE_IMM:
2880 			ins->backend.data = (gpointer) last->inst_imm;
2881 			if (logical)
2882 				ins->opcode = OP_S390_CLIJ;
2883 			else
2884 				ins->opcode = OP_S390_CIJ;
2885 			MONO_DELETE_INS(bb, last);
2886 			break;
2887 		case OP_COMPARE_IMM:
2888 		case OP_LCOMPARE_IMM:
2889 			ins->backend.data = (gpointer) last->inst_imm;
2890 			if (logical)
2891 				ins->opcode = OP_S390_CLGIJ;
2892 			else
2893 				ins->opcode = OP_S390_CGIJ;
2894 			MONO_DELETE_INS(bb, last);
2895 			break;
2896 		}
2897 	}
2898 }
2899 
2900 /*========================= End of Function ========================*/
2901 
2902 /*------------------------------------------------------------------*/
2903 /*                                                                  */
2904 /* Name		- mono_arch_peephole_pass_1                         */
2905 /*                                                                  */
2906 /* Function	- Form a peephole pass at the code looking for      */
2907 /*		  simple optimizations.        			    */
2908 /*		                               			    */
2909 /*------------------------------------------------------------------*/
2910 
2911 void
mono_arch_peephole_pass_1(MonoCompile * cfg,MonoBasicBlock * bb)2912 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
2913 {
2914 	MonoInst *ins, *n;
2915 
2916 	MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2917 		switch (ins->opcode) {
2918 		case OP_IBEQ:
2919 		case OP_LBEQ:
2920 			compare_and_branch(bb, ins, S390_CC_EQ, FALSE);
2921 			break;
2922 		case OP_LBNE_UN:
2923 		case OP_IBNE_UN:
2924 			compare_and_branch(bb, ins, S390_CC_NE, TRUE);
2925 			break;
2926 		case OP_LBLT:
2927 		case OP_IBLT:
2928 			compare_and_branch(bb, ins, S390_CC_LT, FALSE);
2929 			break;
2930 		case OP_LBLT_UN:
2931 		case OP_IBLT_UN:
2932 			compare_and_branch(bb, ins, S390_CC_LT, TRUE);
2933 			break;
2934 		case OP_LBGT:
2935 		case OP_IBGT:
2936 			compare_and_branch(bb, ins, S390_CC_GT, FALSE);
2937 			break;
2938 		case OP_LBGT_UN:
2939 		case OP_IBGT_UN:
2940 			compare_and_branch(bb, ins, S390_CC_GT, TRUE);
2941 			break;
2942 		case OP_LBGE:
2943 		case OP_IBGE:
2944 			compare_and_branch(bb, ins, S390_CC_GE, FALSE);
2945 			break;
2946 		case OP_LBGE_UN:
2947 		case OP_IBGE_UN:
2948 			compare_and_branch(bb, ins, S390_CC_GE, TRUE);
2949 			break;
2950 		case OP_LBLE:
2951 		case OP_IBLE:
2952 			compare_and_branch(bb, ins, S390_CC_LE, FALSE);
2953 			break;
2954 		case OP_LBLE_UN:
2955 		case OP_IBLE_UN:
2956 			compare_and_branch(bb, ins, S390_CC_LE, TRUE);
2957 			break;
2958 
2959 		// default:
2960 		//	mono_peephole_ins (bb, ins);
2961 		}
2962 	}
2963 }
2964 
2965 /*========================= End of Function ========================*/
2966 
2967 /*------------------------------------------------------------------*/
2968 /*                                                                  */
2969 /* Name		- mono_arch_peephole_pass_2                         */
2970 /*                                                                  */
2971 /* Function	- Form a peephole pass at the code looking for      */
2972 /*		  simple optimizations.        			    */
2973 /*		                               			    */
2974 /*------------------------------------------------------------------*/
2975 
2976 void
mono_arch_peephole_pass_2(MonoCompile * cfg,MonoBasicBlock * bb)2977 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
2978 {
2979 	MonoInst *ins, *n, *last_ins = NULL;
2980 
2981 	MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins) {
2982 		switch (ins->opcode) {
2983 		case OP_LOADU4_MEMBASE:
2984 		case OP_LOADI4_MEMBASE:
2985 			if (last_ins && (last_ins->opcode == OP_STOREI4_MEMBASE_REG) &&
2986 					ins->inst_basereg == last_ins->inst_destbasereg &&
2987 					ins->inst_offset == last_ins->inst_offset) {
2988 				ins->opcode = (ins->opcode == OP_LOADI4_MEMBASE) ? OP_ICONV_TO_I4 : OP_ICONV_TO_U4;
2989 				ins->sreg1 = last_ins->sreg1;
2990 			}
2991 			break;
2992 		}
2993 		mono_peephole_ins (bb, ins);
2994 	}
2995 }
2996 
2997 /*========================= End of Function ========================*/
2998 
2999 /*------------------------------------------------------------------*/
3000 /*                                                                  */
3001 /* Name		- mono_arch_lowering_pass.                          */
3002 /*                                                                  */
3003 /*------------------------------------------------------------------*/
3004 
3005 void
mono_arch_lowering_pass(MonoCompile * cfg,MonoBasicBlock * bb)3006 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
3007 {
3008 	MonoInst *ins, *next;
3009 
3010 	MONO_BB_FOR_EACH_INS_SAFE (bb, next, ins) {
3011 		switch (ins->opcode) {
3012 		case OP_DIV_IMM:
3013 		case OP_REM_IMM:
3014 		case OP_IDIV_IMM:
3015 		case OP_IREM_IMM:
3016 		case OP_IDIV_UN_IMM:
3017 		case OP_IREM_UN_IMM:
3018 		case OP_LAND_IMM:
3019 		case OP_LOR_IMM:
3020 		case OP_LREM_IMM:
3021 		case OP_LXOR_IMM:
3022 		case OP_LOCALLOC_IMM:
3023 			mono_decompose_op_imm (cfg, bb, ins);
3024 			break;
3025 		case OP_LADD_IMM:
3026 			if (!s390_is_imm16 (ins->inst_imm))
3027 				/* This is created by the memcpy code which ignores is_inst_imm */
3028 				mono_decompose_op_imm (cfg, bb, ins);
3029 			break;
3030 		default:
3031 			break;
3032 		}
3033 	}
3034 
3035 	bb->max_vreg = cfg->next_vreg;
3036 }
3037 
3038 /*========================= End of Function ========================*/
3039 
3040 /*------------------------------------------------------------------*/
3041 /*                                                                  */
3042 /* Name		- emit_float_to_int                                 */
3043 /*                                                                  */
3044 /* Function	- Create instructions which will convert a floating */
3045 /*		  point value to integer.      			    */
3046 /*		                               			    */
3047 /*------------------------------------------------------------------*/
3048 
3049 static guchar*
emit_float_to_int(MonoCompile * cfg,guchar * code,int dreg,int sreg,int size,gboolean is_signed)3050 emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size, gboolean is_signed)
3051 {
3052 	/* sreg is a float, dreg is an integer reg. */
3053 	if (is_signed) {
3054 		s390_cgdbr (code, dreg, 5, sreg);
3055 		switch (size) {
3056 		case 1:
3057 			s390_ltgr (code, dreg, dreg);
3058 			s390_jnl  (code, 4);
3059 			s390_oill (code, dreg, 0x80);
3060 			s390_lghi (code, s390_r0, 0xff);
3061 			s390_ngr  (code, dreg, s390_r0);
3062 			break;
3063 		case 2:
3064 			s390_ltgr (code, dreg, dreg);
3065 			s390_jnl  (code, 4);
3066 			s390_oill (code, dreg, 0x8000);
3067 			s390_llill(code, s390_r0, 0xffff);
3068 			s390_ngr  (code, dreg, s390_r0);
3069 			break;
3070 		}
3071 	} else {
3072 		short *o[1];
3073 		S390_SET    (code, s390_r13, 0x41e0000000000000llu);
3074 		s390_ldgr   (code, s390_f14, s390_r13);
3075 		s390_ldr    (code, s390_f15, sreg);
3076 		s390_cdbr   (code, s390_f15, s390_f14);
3077 		s390_jl     (code, 0); CODEPTR (code, o[0]);
3078 		S390_SET    (code, s390_r13, 0x41f0000000000000llu);
3079 		s390_ldgr   (code, s390_f14, s390_r13);
3080 		s390_sdbr   (code, s390_f15, s390_f14);
3081 		s390_cfdbr  (code, dreg, 7, s390_f15);
3082 		s390_j      (code, 4);
3083 		PTRSLOT (code, o[0]);
3084 		s390_cfdbr  (code, dreg, 5, sreg);
3085 		switch (size) {
3086 		case 1:
3087 			s390_lghi (code, s390_r0, 0xff);
3088 			s390_ngr  (code, dreg, s390_r0);
3089 			break;
3090 		case 2:
3091 			s390_llill(code, s390_r0, 0xffff);
3092 			s390_ngr  (code, dreg, s390_r0);
3093 			break;
3094 		}
3095 	}
3096 	return code;
3097 }
3098 
3099 /*========================= End of Function ========================*/
3100 
3101 /*------------------------------------------------------------------*/
3102 /*                                                                  */
3103 /* Name		- is_unsigned.                             	    */
3104 /*                                                                  */
3105 /* Function	- Return TRUE if next opcode is checking for un-    */
3106 /*		  signed value.					    */
3107 /*		                               			    */
3108 /*------------------------------------------------------------------*/
3109 
3110 static gboolean
is_unsigned(MonoInst * next)3111 is_unsigned (MonoInst *next)
3112 {
3113 	if ((next) &&
3114 		(((next->opcode >= OP_IBNE_UN) &&
3115 		  (next->opcode <= OP_IBLT_UN)) ||
3116 		 ((next->opcode >= OP_LBNE_UN) &&
3117 		  (next->opcode <= OP_LBLT_UN)) ||
3118 		 ((next->opcode >= OP_COND_EXC_NE_UN) &&
3119 		  (next->opcode <= OP_COND_EXC_LT_UN)) ||
3120 		 ((next->opcode >= OP_COND_EXC_INE_UN) &&
3121 		  (next->opcode <= OP_COND_EXC_ILT_UN)) ||
3122 		 ((next->opcode == OP_CLT_UN) ||
3123 		  (next->opcode == OP_CGT_UN) ||
3124 		  (next->opcode == OP_ICGE_UN)  ||
3125 		  (next->opcode == OP_ICLE_UN)) ||
3126 		 ((next->opcode == OP_ICLT_UN) ||
3127 		  (next->opcode == OP_ICGT_UN) ||
3128 		  (next->opcode == OP_LCLT_UN) ||
3129 		  (next->opcode == OP_LCGT_UN))))
3130 		return TRUE;
3131 	else
3132 		return FALSE;
3133 }
3134 
3135 /*========================= End of Function ========================*/
3136 
3137 /*------------------------------------------------------------------*/
3138 /*                                                                  */
3139 /* Name		- mono_arch_output_basic_block                      */
3140 /*                                                                  */
3141 /* Function	- Perform the "real" work of emitting instructions  */
3142 /*		  that will do the work of in the basic block.      */
3143 /*		                               			    */
3144 /*------------------------------------------------------------------*/
3145 
3146 void
mono_arch_output_basic_block(MonoCompile * cfg,MonoBasicBlock * bb)3147 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
3148 {
3149 	MonoInst *ins;
3150 	MonoCallInst *call;
3151 	guint offset;
3152 	guint8 *code = cfg->native_code + cfg->code_len;
3153 	guint last_offset = 0;
3154 	int max_len, src2;
3155 
3156 	/* we don't align basic blocks of loops on s390 */
3157 
3158 	if (cfg->verbose_level > 2)
3159 		g_print ("Basic block %d starting at offset 0x%x\n", bb->block_num, bb->native_offset);
3160 
3161 	MONO_BB_FOR_EACH_INS (bb, ins) {
3162 		offset = code - cfg->native_code;
3163 
3164 		max_len = ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
3165 
3166 		if (offset > (cfg->code_size - max_len - 16)) {
3167 			cfg->code_size *= 2;
3168 			cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
3169 			code = cfg->native_code + offset;
3170 		}
3171 
3172 		mono_debug_record_line_number (cfg, ins, offset);
3173 
3174 		switch (ins->opcode) {
3175 		case OP_STOREI1_MEMBASE_IMM: {
3176 			s390_lghi (code, s390_r0, ins->inst_imm);
3177 			S390_LONG (code, stcy, stc, s390_r0, 0,
3178 				   ins->inst_destbasereg, ins->inst_offset);
3179 		}
3180 			break;
3181 		case OP_STOREI2_MEMBASE_IMM: {
3182 			s390_lghi (code, s390_r0, ins->inst_imm);
3183 			S390_LONG (code, sthy, sth, s390_r0, 0,
3184 				   ins->inst_destbasereg, ins->inst_offset);
3185 		}
3186 			break;
3187 		case OP_STOREI4_MEMBASE_IMM: {
3188 			s390_lgfi (code, s390_r0, ins->inst_imm);
3189 			S390_LONG (code, sty, st, s390_r0, 0,
3190 				   ins->inst_destbasereg, ins->inst_offset);
3191 		}
3192 			break;
3193 		case OP_STORE_MEMBASE_IMM:
3194 		case OP_STOREI8_MEMBASE_IMM: {
3195 			S390_SET (code, s390_r0, ins->inst_imm);
3196 			S390_LONG (code, stg, stg, s390_r0, 0,
3197 				   ins->inst_destbasereg, ins->inst_offset);
3198 		}
3199 			break;
3200 		case OP_STOREI1_MEMBASE_REG: {
3201 			S390_LONG (code, stcy, stc, ins->sreg1, 0,
3202 				   ins->inst_destbasereg, ins->inst_offset);
3203 		}
3204 			break;
3205 		case OP_STOREI2_MEMBASE_REG: {
3206 			S390_LONG (code, sthy, sth, ins->sreg1, 0,
3207 				   ins->inst_destbasereg, ins->inst_offset);
3208 		}
3209 			break;
3210 		case OP_STOREI4_MEMBASE_REG: {
3211 			S390_LONG (code, sty, st, ins->sreg1, 0,
3212 				   ins->inst_destbasereg, ins->inst_offset);
3213 		}
3214 			break;
3215 		case OP_STORE_MEMBASE_REG:
3216 		case OP_STOREI8_MEMBASE_REG: {
3217 			S390_LONG (code, stg, stg, ins->sreg1, 0,
3218 				   ins->inst_destbasereg, ins->inst_offset);
3219 		}
3220 			break;
3221 		case OP_LOADU4_MEM:
3222 			g_assert_not_reached ();
3223 			break;
3224 		case OP_LOAD_MEMBASE:
3225 		case OP_LOADI8_MEMBASE: {
3226 			S390_LONG (code, lg, lg, ins->dreg, 0,
3227 				   ins->inst_basereg, ins->inst_offset);
3228 		}
3229 			break;
3230 		case OP_LOADI4_MEMBASE: {
3231 			S390_LONG (code, lgf, lgf, ins->dreg, 0,
3232 				   ins->inst_basereg, ins->inst_offset);
3233 		}
3234 			break;
3235 		case OP_LOADU4_MEMBASE: {
3236 			S390_LONG (code, llgf, llgf, ins->dreg, 0,
3237 				   ins->inst_basereg, ins->inst_offset);
3238 		}
3239 			break;
3240 		case OP_LOADU1_MEMBASE: {
3241 			S390_LONG (code, llgc, llgc, ins->dreg, 0,
3242 				   ins->inst_basereg, ins->inst_offset);
3243 		}
3244 			break;
3245 		case OP_LOADI1_MEMBASE: {
3246 			S390_LONG (code, lgb, lgb, ins->dreg, 0,
3247 				   ins->inst_basereg, ins->inst_offset);
3248 		}
3249 			break;
3250 		case OP_LOADU2_MEMBASE: {
3251 			S390_LONG (code, llgh, llgh, ins->dreg, 0,
3252 				   ins->inst_basereg, ins->inst_offset);
3253 		}
3254 			break;
3255 		case OP_LOADI2_MEMBASE: {
3256 			S390_LONG (code, lgh, lgh, ins->dreg, 0,
3257 				   ins->inst_basereg, ins->inst_offset);
3258 		}
3259 			break;
3260 		case OP_LCONV_TO_I1: {
3261 			s390_lgbr (code, ins->dreg, ins->sreg1);
3262 		}
3263 			break;
3264 		case OP_LCONV_TO_I2: {
3265 			s390_lghr (code, ins->dreg, ins->sreg1);
3266 		}
3267 			break;
3268 		case OP_LCONV_TO_U1: {
3269 			s390_llgcr (code, ins->dreg, ins->sreg1);
3270 		}
3271 			break;
3272 		case OP_LCONV_TO_U2: {
3273 			s390_llghr (code, ins->dreg, ins->sreg1);
3274 		}
3275 			break;
3276 		case OP_ICONV_TO_I1: {
3277 			s390_lgbr  (code, ins->dreg, ins->sreg1);
3278 		}
3279 			break;
3280 		case OP_ICONV_TO_I2: {
3281 			s390_lghr  (code, ins->dreg, ins->sreg1);
3282 		}
3283 			break;
3284 		case OP_ICONV_TO_U1: {
3285 			s390_llgcr (code, ins->dreg, ins->sreg1);
3286 		}
3287 			break;
3288 		case OP_ICONV_TO_U2: {
3289 			s390_llghr (code, ins->dreg, ins->sreg1);
3290 		}
3291 			break;
3292 		case OP_ICONV_TO_U4: {
3293 			s390_llgfr (code, ins->dreg, ins->sreg1);
3294 		}
3295 			break;
3296 		case OP_ICONV_TO_I4: {
3297 			s390_lgfr (code, ins->dreg, ins->sreg1);
3298 		}
3299 			break;
3300 		case OP_COMPARE:
3301 		case OP_LCOMPARE: {
3302 			if (is_unsigned (ins->next))
3303 				s390_clgr (code, ins->sreg1, ins->sreg2);
3304 			else
3305 				s390_cgr  (code, ins->sreg1, ins->sreg2);
3306 		}
3307 			break;
3308 		case OP_ICOMPARE: {
3309 			if (is_unsigned (ins->next))
3310 				s390_clr  (code, ins->sreg1, ins->sreg2);
3311 			else
3312 				s390_cr   (code, ins->sreg1, ins->sreg2);
3313 		}
3314 			break;
3315 		case OP_COMPARE_IMM:
3316 		case OP_LCOMPARE_IMM: {
3317 			gboolean branchUn = is_unsigned (ins->next);
3318 			if ((ins->inst_imm == 0) && (!branchUn)) {
3319 				s390_ltgr (code, ins->sreg1, ins->sreg1);
3320 			} else {
3321 				S390_SET (code, s390_r0, ins->inst_imm);
3322 				if (branchUn)
3323 					s390_clgr (code, ins->sreg1, s390_r0);
3324 				else
3325 					s390_cgr  (code, ins->sreg1, s390_r0);
3326 			}
3327 		}
3328 			break;
3329 		case OP_ICOMPARE_IMM: {
3330 			gboolean branchUn = is_unsigned (ins->next);
3331 			if ((ins->inst_imm == 0) && (!branchUn)) {
3332 				s390_ltr (code, ins->sreg1, ins->sreg1);
3333 			} else {
3334 				S390_SET (code, s390_r0, ins->inst_imm);
3335 				if (branchUn)
3336 					s390_clr  (code, ins->sreg1, s390_r0);
3337 				else
3338 					s390_cr   (code, ins->sreg1, s390_r0);
3339 			}
3340 		}
3341 			break;
3342 		case OP_BREAK: {
3343 			mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
3344 					     mono_break);
3345 			S390_CALL_TEMPLATE (code, s390_r14);
3346 		}
3347 			break;
3348 		case OP_ADDCC: {
3349 			if (mono_hwcap_s390x_has_mlt) {
3350 				s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3351 			} else {
3352 				CHECK_SRCDST_COM;
3353 				s390_agr  (code, ins->dreg, src2);
3354 			}
3355 		}
3356 			break;
3357 		case OP_LADD: {
3358 			if (mono_hwcap_s390x_has_mlt) {
3359 				s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3360 			} else {
3361 				CHECK_SRCDST_COM;
3362 				s390_agr   (code, ins->dreg, src2);
3363 			}
3364 		}
3365 			break;
3366 		case OP_ADC: {
3367 			CHECK_SRCDST_COM;
3368 			s390_alcgr (code, ins->dreg, src2);
3369 		}
3370 			break;
3371 		case OP_ADD_IMM: {
3372 			if (mono_hwcap_s390x_has_mlt) {
3373 				if (s390_is_imm16 (ins->inst_imm)) {
3374 					s390_aghik(code, ins->dreg, ins->sreg1, ins->inst_imm);
3375 				} else {
3376 					S390_SET  (code, s390_r0, ins->inst_imm);
3377 					s390_agrk (code, ins->dreg, ins->sreg1, s390_r0);
3378 				}
3379 			} else {
3380 				if (ins->dreg != ins->sreg1) {
3381 					s390_lgr  (code, ins->dreg, ins->sreg1);
3382 				}
3383 				if (s390_is_imm16 (ins->inst_imm)) {
3384 					s390_aghi (code, ins->dreg, ins->inst_imm);
3385 				} else if (s390_is_imm32 (ins->inst_imm)) {
3386 					s390_agfi (code, ins->dreg, ins->inst_imm);
3387 				} else {
3388 					S390_SET  (code, s390_r0, ins->inst_imm);
3389 					s390_agr  (code, ins->dreg, s390_r0);
3390 				}
3391 			}
3392 		}
3393 			break;
3394 		case OP_LADD_IMM: {
3395 			if (ins->dreg != ins->sreg1) {
3396 				s390_lgr  (code, ins->dreg, ins->sreg1);
3397 			}
3398 			if (s390_is_imm32 (ins->inst_imm)) {
3399 				s390_agfi (code, ins->dreg, ins->inst_imm);
3400 			} else {
3401 				S390_SET  (code, s390_r0, ins->inst_imm);
3402 				s390_agr  (code, ins->dreg, s390_r0);
3403 			}
3404 		}
3405 			break;
3406 		case OP_ADC_IMM: {
3407 			if (ins->dreg != ins->sreg1) {
3408 				s390_lgr  (code, ins->dreg, ins->sreg1);
3409 			}
3410 			if (s390_is_imm16 (ins->inst_imm)) {
3411 				s390_lghi  (code, s390_r0, ins->inst_imm);
3412 				s390_alcgr (code, ins->dreg, s390_r0);
3413 			} else {
3414 				S390_SET   (code, s390_r0, ins->inst_imm);
3415 				s390_alcgr (code, ins->dreg, s390_r0);
3416 			}
3417 		}
3418 			break;
3419 		case OP_IADD_OVF:
3420 		case OP_S390_IADD_OVF: {
3421 			CHECK_SRCDST_COM;
3422 			s390_ar    (code, ins->dreg, src2);
3423 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3424 			s390_lgfr  (code, ins->dreg, ins->dreg);
3425 		}
3426 			break;
3427 		case OP_IADD_OVF_UN:
3428 		case OP_S390_IADD_OVF_UN: {
3429 			CHECK_SRCDST_COM;
3430 			s390_algr  (code, ins->dreg, src2);
3431 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3432 			s390_llgfr (code, ins->dreg, ins->dreg);
3433 		}
3434 			break;
3435 		case OP_ADD_OVF_CARRY: {
3436 			CHECK_SRCDST_COM;
3437 			s390_lghi  (code, s390_r0, 0);
3438 			s390_lgr   (code, s390_r1, s390_r0);
3439 			s390_alcgr (code, s390_r0, s390_r1);
3440 			s390_agr   (code, ins->dreg, src2);
3441 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3442 			s390_agr   (code, ins->dreg, s390_r0);
3443 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3444 		}
3445 			break;
3446 		case OP_ADD_OVF_UN_CARRY: {
3447 			CHECK_SRCDST_COM;
3448 			s390_alcgr (code, ins->dreg, src2);
3449 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3450 		}
3451 			break;
3452 		case OP_SUBCC: {
3453 			if (mono_hwcap_s390x_has_mlt) {
3454 			    s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3455 			} else {
3456 			    CHECK_SRCDST_NCOM;
3457 			    s390_sgr (code, ins->dreg, src2);
3458 			}
3459 		}
3460 			break;
3461 		case OP_LSUB: {
3462 			if (mono_hwcap_s390x_has_mlt) {
3463 			    s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3464 			} else {
3465 			    CHECK_SRCDST_NCOM;
3466 			    s390_sgr  (code, ins->dreg, src2);
3467 			}
3468 		}
3469 			break;
3470 		case OP_SBB: {
3471 			CHECK_SRCDST_NCOM;
3472 			s390_slbgr(code, ins->dreg, src2);
3473 		}
3474 			break;
3475 		case OP_SUB_IMM: {
3476 			if (ins->dreg != ins->sreg1) {
3477 				s390_lgr   (code, ins->dreg, ins->sreg1);
3478 			}
3479 			if (s390_is_imm16 (-ins->inst_imm)) {
3480 				s390_aghi  (code, ins->dreg, -ins->inst_imm);
3481 			} else if (s390_is_imm32 (-ins->inst_imm)) {
3482 				s390_slgfi  (code, ins->dreg, ins->inst_imm);
3483 			} else {
3484 				S390_SET  (code, s390_r0, ins->inst_imm);
3485 				s390_slgr (code, ins->dreg, s390_r0);
3486 			}
3487 		}
3488 			break;
3489 		case OP_LSUB_IMM: {
3490 			if (ins->dreg != ins->sreg1) {
3491 				s390_lgr   (code, ins->dreg, ins->sreg1);
3492 			}
3493 			if (s390_is_imm16 (-ins->inst_imm)) {
3494 				s390_aghi  (code, ins->dreg, -ins->inst_imm);
3495 			} else if (s390_is_imm32 (-ins->inst_imm)) {
3496 				s390_slgfi (code, ins->dreg, ins->inst_imm);
3497 			} else {
3498 				S390_SET  (code, s390_r0, ins->inst_imm);
3499 				s390_slgr (code, ins->dreg, s390_r0);
3500 			}
3501 		}
3502 			break;
3503 		case OP_SBB_IMM: {
3504 			if (ins->dreg != ins->sreg1) {
3505 				s390_lgr   (code, ins->dreg, ins->sreg1);
3506 			}
3507 			if (s390_is_imm16 (-ins->inst_imm)) {
3508 				s390_lghi  (code, s390_r0, ins->inst_imm);
3509 				s390_slbgr (code, ins->dreg, s390_r0);
3510 			} else {
3511 				S390_SET  (code, s390_r0, ins->inst_imm);
3512 				s390_slbgr(code, ins->dreg, s390_r0);
3513 			}
3514 		}
3515 			break;
3516 		case OP_SUB_OVF_CARRY: {
3517 			CHECK_SRCDST_NCOM;
3518 			s390_lghi  (code, s390_r0, 0);
3519 			s390_lgr   (code, s390_r1, s390_r0);
3520 			s390_slbgr (code, s390_r0, s390_r1);
3521 			s390_sgr   (code, ins->dreg, src2);
3522 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3523 			s390_agr   (code, ins->dreg, s390_r0);
3524 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3525 		}
3526 			break;
3527 		case OP_SUB_OVF_UN_CARRY: {
3528 			CHECK_SRCDST_NCOM;
3529 			s390_slbgr (code, ins->dreg, src2);
3530 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3531 		}
3532 			break;
3533 		case OP_LAND: {
3534 			if (mono_hwcap_s390x_has_mlt) {
3535 				s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3536 			} else {
3537 				if (ins->sreg1 == ins->dreg) {
3538 					s390_ngr  (code, ins->dreg, ins->sreg2);
3539 				} else {
3540 					if (ins->sreg2 == ins->dreg) {
3541 						s390_ngr (code, ins->dreg, ins->sreg1);
3542 					} else {
3543 						s390_lgr (code, ins->dreg, ins->sreg1);
3544 						s390_ngr (code, ins->dreg, ins->sreg2);
3545 					}
3546 				}
3547 			}
3548 		}
3549 			break;
3550 		case OP_AND_IMM: {
3551 			S390_SET_MASK (code, s390_r0, ins->inst_imm);
3552 			if (mono_hwcap_s390x_has_mlt) {
3553 				s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3554 			} else {
3555 				if (ins->dreg != ins->sreg1) {
3556 					s390_lgr  (code, ins->dreg, ins->sreg1);
3557 				}
3558 				s390_ngr (code, ins->dreg, s390_r0);
3559 			}
3560 		}
3561 			break;
3562 		case OP_LDIV: {
3563 			s390_lgr  (code, s390_r1, ins->sreg1);
3564 			s390_dsgr (code, s390_r0, ins->sreg2);
3565 			s390_lgr  (code, ins->dreg, s390_r1);
3566 		}
3567 			break;
3568 		case OP_LDIV_UN: {
3569 			s390_lgr   (code, s390_r1, ins->sreg1);
3570 			s390_lghi  (code, s390_r0, 0);
3571 			s390_dlgr  (code, s390_r0, ins->sreg2);
3572 			s390_lgr   (code, ins->dreg, s390_r1);
3573 		}
3574 			break;
3575 		case OP_LREM: {
3576 			s390_lgr  (code, s390_r1, ins->sreg1);
3577 			s390_dsgr (code, s390_r0, ins->sreg2);
3578 			s390_lgr  (code, ins->dreg, s390_r0);
3579 			break;
3580 		}
3581 		case OP_LREM_IMM: {
3582 			if (s390_is_imm16 (ins->inst_imm)) {
3583 				s390_lghi (code, s390_r13, ins->inst_imm);
3584 			} else {
3585 				s390_lgfi (code, s390_r13, ins->inst_imm);
3586 			}
3587 			s390_lgr  (code, s390_r0, ins->sreg1);
3588 			s390_dsgr (code, s390_r0, s390_r13);
3589 			s390_lgfr (code, ins->dreg, s390_r0);
3590 		}
3591 			break;
3592 		case OP_LREM_UN: {
3593 			s390_lgr   (code, s390_r1, ins->sreg1);
3594 			s390_lghi  (code, s390_r0, 0);
3595 			s390_dlgr  (code, s390_r0, ins->sreg2);
3596 			s390_lgr   (code, ins->dreg, s390_r0);
3597 		}
3598 			break;
3599 		case OP_LOR: {
3600 			if (mono_hwcap_s390x_has_mlt) {
3601 				s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3602 			} else {
3603 				if (ins->sreg1 == ins->dreg) {
3604 					s390_ogr  (code, ins->dreg, ins->sreg2);
3605 				} else {
3606 					if (ins->sreg2 == ins->dreg) {
3607 						s390_ogr (code, ins->dreg, ins->sreg1);
3608 					} else {
3609 						s390_lgr (code, ins->dreg, ins->sreg1);
3610 						s390_ogr (code, ins->dreg, ins->sreg2);
3611 					}
3612 				}
3613 			}
3614 		}
3615 			break;
3616 		case OP_OR_IMM: {
3617 			S390_SET_MASK(code, s390_r0, ins->inst_imm);
3618 			if (mono_hwcap_s390x_has_mlt) {
3619 				s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3620 			} else {
3621 				if (ins->dreg != ins->sreg1) {
3622 					s390_lgr  (code, ins->dreg, ins->sreg1);
3623 				}
3624 				s390_ogr (code, ins->dreg, s390_r0);
3625 			}
3626 		}
3627 			break;
3628 		case OP_LXOR: {
3629 			if (mono_hwcap_s390x_has_mlt) {
3630 				s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3631 			} else {
3632 				if (ins->sreg1 == ins->dreg) {
3633 					s390_xgr  (code, ins->dreg, ins->sreg2);
3634 				}
3635 				else {
3636 					if (ins->sreg2 == ins->dreg) {
3637 						s390_xgr (code, ins->dreg, ins->sreg1);
3638 					}
3639 					else {
3640 						s390_lgr (code, ins->dreg, ins->sreg1);
3641 						s390_xgr (code, ins->dreg, ins->sreg2);
3642 					}
3643 				}
3644 			}
3645 		}
3646 			break;
3647 		case OP_XOR_IMM: {
3648 			S390_SET_MASK(code, s390_r0, ins->inst_imm);
3649 			if (mono_hwcap_s390x_has_mlt) {
3650 				s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
3651 			} else {
3652 				if (ins->dreg != ins->sreg1) {
3653 					s390_lgr  (code, ins->dreg, ins->sreg1);
3654 				}
3655 				s390_xgr (code, ins->dreg, s390_r0);
3656 			}
3657 		}
3658 			break;
3659 		case OP_LSHL: {
3660 			CHECK_SRCDST_NCOM;
3661 			s390_sllg (code, ins->dreg, ins->dreg, src2, 0);
3662 		}
3663 			break;
3664 		case OP_SHL_IMM:
3665 		case OP_LSHL_IMM: {
3666 			if (ins->sreg1 != ins->dreg) {
3667 				s390_lgr   (code, ins->dreg, ins->sreg1);
3668 			}
3669 			s390_sllg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3670 		}
3671 			break;
3672 		case OP_LSHR: {
3673 			CHECK_SRCDST_NCOM;
3674 			s390_srag  (code, ins->dreg, ins->dreg, src2, 0);
3675 		}
3676 			break;
3677 		case OP_SHR_IMM:
3678 		case OP_LSHR_IMM: {
3679 			if (ins->sreg1 != ins->dreg) {
3680 				s390_lgr  (code, ins->dreg, ins->sreg1);
3681 			}
3682 			s390_srag  (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3683 		}
3684 			break;
3685 		case OP_SHR_UN_IMM:
3686 		case OP_LSHR_UN_IMM: {
3687 			if (ins->sreg1 != ins->dreg) {
3688 				s390_lgr   (code, ins->dreg, ins->sreg1);
3689 			}
3690 			s390_srlg (code, ins->dreg, ins->dreg, 0, (ins->inst_imm & 0x3f));
3691 		}
3692 			break;
3693 		case OP_LSHR_UN: {
3694 			CHECK_SRCDST_NCOM;
3695 			s390_srlg (code, ins->dreg, ins->dreg, src2, 0);
3696 		}
3697 			break;
3698 		case OP_LNOT: {
3699 			if (ins->sreg1 != ins->dreg) {
3700 				s390_lgr  (code, ins->dreg, ins->sreg1);
3701 			}
3702 			s390_lghi (code, s390_r0, -1);
3703 			s390_xgr  (code, ins->dreg, s390_r0);
3704 		}
3705 			break;
3706 		case OP_LNEG: {
3707 			s390_lcgr (code, ins->dreg, ins->sreg1);
3708 		}
3709 			break;
3710 		case OP_LMUL: {
3711 			CHECK_SRCDST_COM;
3712 			s390_msgr (code, ins->dreg, src2);
3713 		}
3714 			break;
3715 		case OP_MUL_IMM:
3716 		case OP_LMUL_IMM: {
3717 			if (ins->dreg != ins->sreg1) {
3718 				s390_lgr  (code, ins->dreg, ins->sreg1);
3719 			}
3720 			if ((mono_hwcap_s390x_has_gie) &&
3721 			    (s390_is_imm32 (ins->inst_imm))) {
3722 				s390_msgfi (code, ins->dreg, ins->inst_imm);
3723 			} else {
3724 				if (s390_is_imm16 (ins->inst_imm)) {
3725 					s390_lghi (code, s390_r13, ins->inst_imm);
3726 				} else if (s390_is_imm32 (ins->inst_imm)) {
3727 					s390_lgfi (code, s390_r13, ins->inst_imm);
3728 				} else {
3729 					S390_SET (code, s390_r13, ins->inst_imm);
3730 				}
3731 				s390_msgr (code, ins->dreg, s390_r13);
3732 			}
3733 		}
3734 			break;
3735 		case OP_LMUL_OVF: {
3736 			short int *o[2];
3737 			if (mono_hwcap_s390x_has_mie2) {
3738 				s390_msgrkc (code, ins->dreg, ins->sreg1, ins->sreg2);
3739 				EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3740 			} else {
3741 				s390_ltgr (code, s390_r1, ins->sreg1);
3742 				s390_jz   (code, 0); CODEPTR(code, o[0]);
3743 				s390_ltgr (code, s390_r0, ins->sreg2);
3744 				s390_jnz  (code, 6);
3745 				s390_lghi (code, s390_r1, 0);
3746 				s390_j    (code, 0); CODEPTR(code, o[1]);
3747 				s390_xgr  (code, s390_r0, s390_r1);
3748 				s390_msgr (code, s390_r1, ins->sreg2);
3749 				s390_xgr  (code, s390_r0, s390_r1);
3750 				s390_srlg (code, s390_r0, s390_r0, 0, 63);
3751 				s390_ltgr (code, s390_r0, s390_r0);
3752 				EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3753 				PTRSLOT	  (code, o[0]);
3754 				PTRSLOT   (code, o[1]);
3755 				s390_lgr  (code, ins->dreg, s390_r1);
3756 			}
3757 		}
3758 			break;
3759 		case OP_LMUL_OVF_UN: {
3760 			s390_lghi  (code, s390_r0, 0);
3761 			s390_lgr   (code, s390_r1, ins->sreg1);
3762 			s390_mlgr  (code, s390_r0, ins->sreg2);
3763 			s390_ltgr  (code, s390_r0, s390_r0);
3764 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
3765 			s390_lgr   (code, ins->dreg, s390_r1);
3766 		}
3767 			break;
3768 		case OP_IADDCC: {
3769 			g_assert_not_reached ();
3770 			CHECK_SRCDST_COM_I;
3771 			s390_algr (code, ins->dreg, src2);
3772 		}
3773 			break;
3774 		case OP_IADD: {
3775 			CHECK_SRCDST_COM_I;
3776 			s390_agr  (code, ins->dreg, src2);
3777 		}
3778 			break;
3779 		case OP_IADC: {
3780 			g_assert_not_reached ();
3781 			CHECK_SRCDST_COM_I;
3782 			s390_alcgr (code, ins->dreg, src2);
3783 		}
3784 			break;
3785 		case OP_IADD_IMM: {
3786 			if (ins->dreg != ins->sreg1) {
3787 				s390_lgfr (code, ins->dreg, ins->sreg1);
3788 			}
3789 			if (s390_is_imm16 (ins->inst_imm)) {
3790 				s390_aghi (code, ins->dreg, ins->inst_imm);
3791 			} else {
3792 				s390_afi  (code, ins->dreg, ins->inst_imm);
3793 			}
3794 		}
3795 			break;
3796 		case OP_IADC_IMM: {
3797 			if (ins->dreg != ins->sreg1) {
3798 				s390_lgfr (code, ins->dreg, ins->sreg1);
3799 			}
3800 			if (s390_is_imm16 (ins->inst_imm)) {
3801 				s390_lghi  (code, s390_r0, ins->inst_imm);
3802 				s390_alcgr (code, ins->dreg, s390_r0);
3803 			} else {
3804 				S390_SET   (code, s390_r0, ins->inst_imm);
3805 				s390_alcgr (code, ins->dreg, s390_r0);
3806 			}
3807 		}
3808 			break;
3809 		case OP_LADD_OVF:
3810 		case OP_S390_LADD_OVF: {
3811 			if (mono_hwcap_s390x_has_mlt) {
3812 				s390_agrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3813 			} else {
3814 				CHECK_SRCDST_COM;
3815 				s390_agr    (code, ins->dreg, src2);
3816 			}
3817 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3818 		}
3819 			break;
3820 		case OP_LADD_OVF_UN:
3821 		case OP_S390_LADD_OVF_UN: {
3822 			if (mono_hwcap_s390x_has_mlt) {
3823 				s390_algrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3824 			} else {
3825 				CHECK_SRCDST_COM;
3826 				s390_algr  (code, ins->dreg, src2);
3827 			}
3828 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException");
3829 		}
3830 			break;
3831 		case OP_ISUBCC: {
3832 			if (mono_hwcap_s390x_has_mlt) {
3833 				s390_slgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3834 			} else {
3835 				CHECK_SRCDST_NCOM_I;
3836 				s390_slgr (code, ins->dreg, src2);
3837 			}
3838 		}
3839 			break;
3840 		case OP_ISUB: {
3841 			if (mono_hwcap_s390x_has_mlt) {
3842 				s390_sgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3843 			} else {
3844 				CHECK_SRCDST_NCOM_I;
3845 				s390_sgr  (code, ins->dreg, src2);
3846 			}
3847 		}
3848 			break;
3849 		case OP_ISBB: {
3850 			CHECK_SRCDST_NCOM_I;
3851 			s390_slbgr (code, ins->dreg, src2);
3852 		}
3853 			break;
3854 		case OP_ISUB_IMM: {
3855 			if (ins->dreg != ins->sreg1) {
3856 				s390_lgfr (code, ins->dreg, ins->sreg1);
3857 			}
3858 			if (s390_is_imm16 (-ins->inst_imm)) {
3859 				s390_aghi (code, ins->dreg, -ins->inst_imm);
3860 			} else {
3861 				s390_agfi (code, ins->dreg, -ins->inst_imm);
3862 			}
3863 		}
3864 			break;
3865 		case OP_ISBB_IMM: {
3866 			S390_SET (code, s390_r0, ins->inst_imm);
3867 			s390_slgfr (code, ins->dreg, s390_r0);
3868 		}
3869 			break;
3870 		case OP_ISUB_OVF:
3871 		case OP_S390_ISUB_OVF: {
3872 			if (mono_hwcap_s390x_has_mlt) {
3873 				s390_srk (code, ins->dreg, ins->sreg1, ins->sreg2);
3874 				EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3875 			} else {
3876 				CHECK_SRCDST_NCOM;
3877 				s390_sr   (code, ins->dreg, src2);
3878 				EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3879 				s390_lgfr (code, ins->dreg, ins->dreg);
3880 			}
3881 		}
3882 			break;
3883 		case OP_ISUB_OVF_UN:
3884 		case OP_S390_ISUB_OVF_UN: {
3885 			if (mono_hwcap_s390x_has_mlt) {
3886 				s390_slrk  (code, ins->dreg, ins->sreg1, ins->sreg2);
3887 			} else {
3888 				CHECK_SRCDST_NCOM;
3889 				s390_slr  (code, ins->dreg, src2);
3890 			}
3891 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3892 			s390_llgfr(code, ins->dreg, ins->dreg);
3893 		}
3894 			break;
3895 		case OP_LSUB_OVF:
3896 		case OP_S390_LSUB_OVF: {
3897 			if (mono_hwcap_s390x_has_mlt) {
3898 				s390_sgrk  (code, ins->dreg, ins->sreg1, ins->sreg2);
3899 			} else {
3900 				CHECK_SRCDST_NCOM;
3901 				s390_sgr   (code, ins->dreg, src2);
3902 			}
3903 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException");
3904 		}
3905 			break;
3906 		case OP_LSUB_OVF_UN:
3907 		case OP_S390_LSUB_OVF_UN: {
3908 			CHECK_SRCDST_NCOM;
3909 			s390_slgr  (code, ins->dreg, src2);
3910 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException");
3911 		}
3912 			break;
3913 		case OP_IAND: {
3914 			if (mono_hwcap_s390x_has_mlt) {
3915 				s390_ngrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3916 			} else {
3917 				CHECK_SRCDST_NCOM_I;
3918 				s390_ngr (code, ins->dreg, src2);
3919 			}
3920 		}
3921 			break;
3922 		case OP_IAND_IMM: {
3923 			S390_SET_MASK (code, s390_r0, ins->inst_imm);
3924 			if (mono_hwcap_s390x_has_mlt) {
3925 				s390_ngrk (code, ins->dreg, ins->sreg1, s390_r0);
3926 			} else {
3927 				if (ins->dreg != ins->sreg1) {
3928 					s390_lgfr (code, ins->dreg, ins->sreg1);
3929 				}
3930 				s390_ngr  (code, ins->dreg, s390_r0);
3931 			}
3932 		}
3933 			break;
3934 		case OP_IDIV: {
3935 			s390_lgfr (code, s390_r0, ins->sreg1);
3936 			s390_srda (code, s390_r0, 0, 32);
3937 			s390_dr   (code, s390_r0, ins->sreg2);
3938 			s390_lgfr (code, ins->dreg, s390_r1);
3939 		}
3940 			break;
3941 		case OP_IDIV_UN: {
3942 			s390_lgfr (code, s390_r0, ins->sreg1);
3943 			s390_srdl (code, s390_r0, 0, 32);
3944 			s390_dlr  (code, s390_r0, ins->sreg2);
3945 			s390_lgfr (code, ins->dreg, s390_r1);
3946 		}
3947 			break;
3948 		case OP_IDIV_IMM: {
3949 			if (s390_is_imm16 (ins->inst_imm)) {
3950 				s390_lghi (code, s390_r13, ins->inst_imm);
3951 			} else {
3952 				s390_lgfi (code, s390_r13, ins->inst_imm);
3953 			}
3954 			s390_lgfr (code, s390_r0, ins->sreg1);
3955 			s390_srda (code, s390_r0, 0, 32);
3956 			s390_dr   (code, s390_r0, ins->sreg2);
3957 			s390_lgfr (code, ins->dreg, s390_r1);
3958 		}
3959 			break;
3960 		case OP_IREM: {
3961 			s390_lgfr (code, s390_r0, ins->sreg1);
3962 			s390_srda (code, s390_r0, 0, 32);
3963 			s390_dr   (code, s390_r0, ins->sreg2);
3964 			s390_lgfr (code, ins->dreg, s390_r0);
3965 			break;
3966 		case OP_IREM_UN:
3967 			s390_lgfr (code, s390_r0, ins->sreg1);
3968 			s390_srdl (code, s390_r0, 0, 32);
3969 			s390_dlr  (code, s390_r0, ins->sreg2);
3970 			s390_lgfr (code, ins->dreg, s390_r0);
3971 		}
3972 			break;
3973 		case OP_IREM_IMM: {
3974 			if (s390_is_imm16 (ins->inst_imm)) {
3975 				s390_lghi (code, s390_r13, ins->inst_imm);
3976 			} else {
3977 				s390_lgfi (code, s390_r13, ins->inst_imm);
3978 			}
3979 			s390_lgfr (code, s390_r0, ins->sreg1);
3980 			s390_srda (code, s390_r0, 0, 32);
3981 			s390_dr   (code, s390_r0, ins->sreg2);
3982 			s390_lgfr (code, ins->dreg, s390_r0);
3983 		}
3984 			break;
3985 		case OP_IOR: {
3986 			if (mono_hwcap_s390x_has_mlt) {
3987 				s390_ogrk (code, ins->dreg, ins->sreg1, ins->sreg2);
3988 			} else {
3989 				CHECK_SRCDST_COM_I;
3990 				s390_ogr (code, ins->dreg, src2);
3991 			}
3992 		}
3993 			break;
3994 		case OP_IOR_IMM: {
3995 			S390_SET_MASK (code, s390_r0, ins->inst_imm);
3996 			if (mono_hwcap_s390x_has_mlt) {
3997 				s390_ogrk (code, ins->dreg, ins->sreg1, s390_r0);
3998 			} else {
3999 				if (ins->dreg != ins->sreg1) {
4000 					s390_lgfr (code, ins->dreg, ins->sreg1);
4001 				}
4002 				s390_ogr  (code, ins->dreg, s390_r0);
4003 			}
4004 		}
4005 			break;
4006 		case OP_IXOR: {
4007 			if (mono_hwcap_s390x_has_mlt) {
4008 				s390_xgrk (code, ins->dreg, ins->sreg1, ins->sreg2);
4009 			} else {
4010 				CHECK_SRCDST_COM_I;
4011 				s390_xgr (code, ins->dreg, src2);
4012 			}
4013 		}
4014 			break;
4015 		case OP_IXOR_IMM: {
4016 			S390_SET_MASK (code, s390_r0, ins->inst_imm);
4017 			if (mono_hwcap_s390x_has_mlt) {
4018 				s390_xgrk (code, ins->dreg, ins->sreg1, s390_r0);
4019 			} else {
4020 				if (ins->dreg != ins->sreg1) {
4021 					s390_lgfr (code, ins->dreg, ins->sreg1);
4022 				}
4023 				s390_xgr  (code, ins->dreg, s390_r0);
4024 			}
4025 		}
4026 			break;
4027 		case OP_ISHL: {
4028 			CHECK_SRCDST_NCOM;
4029 			s390_sll  (code, ins->dreg, src2, 0);
4030 		}
4031 			break;
4032 		case OP_ISHL_IMM: {
4033 			if (ins->sreg1 != ins->dreg) {
4034 				s390_lgfr (code, ins->dreg, ins->sreg1);
4035 			}
4036 			s390_sll (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4037 		}
4038 			break;
4039 		case OP_ISHR: {
4040 			CHECK_SRCDST_NCOM;
4041 			s390_sra (code, ins->dreg, src2, 0);
4042 		}
4043 			break;
4044 		case OP_ISHR_IMM: {
4045 			if (ins->sreg1 != ins->dreg) {
4046 				s390_lgfr (code, ins->dreg, ins->sreg1);
4047 			}
4048 			s390_sra (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4049 		}
4050 			break;
4051 		case OP_ISHR_UN_IMM: {
4052 			if (ins->sreg1 != ins->dreg) {
4053 				s390_lgfr (code, ins->dreg, ins->sreg1);
4054 			}
4055 			s390_srl (code, ins->dreg, 0, (ins->inst_imm & 0x1f));
4056 		}
4057 			break;
4058 		case OP_ISHR_UN: {
4059 			CHECK_SRCDST_NCOM;
4060 			s390_srl  (code, ins->dreg, src2, 0);
4061 		}
4062 			break;
4063 		case OP_INOT: {
4064 			if (ins->sreg1 != ins->dreg) {
4065 				s390_lgfr (code, ins->dreg, ins->sreg1);
4066 			}
4067 			s390_lghi (code, s390_r0, -1);
4068 			s390_xgr  (code, ins->dreg, s390_r0);
4069 		}
4070 			break;
4071 		case OP_INEG: {
4072 			s390_lcgr (code, ins->dreg, ins->sreg1);
4073 		}
4074 			break;
4075 		case OP_IMUL: {
4076 			CHECK_SRCDST_COM_I;
4077 			s390_msr (code, ins->dreg, src2);
4078 		}
4079 			break;
4080 		case OP_IMUL_IMM: {
4081 			if (ins->dreg != ins->sreg1) {
4082 				s390_lgfr (code, ins->dreg, ins->sreg1);
4083 			}
4084 			if (s390_is_imm16 (ins->inst_imm)) {
4085 				s390_lghi (code, s390_r0, ins->inst_imm);
4086 			} else {
4087 				s390_lgfi (code, s390_r0, ins->inst_imm);
4088 			}
4089 			s390_msr  (code, ins->dreg, s390_r0);
4090 		}
4091 			break;
4092 		case OP_IMUL_OVF: {
4093 			short int *o[2];
4094 			s390_ltr  (code, s390_r1, ins->sreg1);
4095 			s390_jz   (code, 0); CODEPTR(code, o[0]);
4096 			s390_ltr  (code, s390_r0, ins->sreg2);
4097 			s390_jnz  (code, 6);
4098 			s390_lhi  (code, s390_r1, 0);
4099 			s390_j    (code, 0); CODEPTR(code, o[1]);
4100 			s390_xr	  (code, s390_r0, s390_r1);
4101 			s390_msr  (code, s390_r1, ins->sreg2);
4102 			s390_xr   (code, s390_r0, s390_r1);
4103 			s390_srl  (code, s390_r0, 0, 31);
4104 			s390_ltr  (code, s390_r0, s390_r0);
4105 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4106 			PTRSLOT	  (code, o[0]);
4107 			PTRSLOT   (code, o[1]);
4108 			s390_lgfr (code, ins->dreg, s390_r1);
4109 		}
4110 			break;
4111 		case OP_IMUL_OVF_UN: {
4112 			s390_lhi  (code, s390_r0, 0);
4113 			s390_lr   (code, s390_r1, ins->sreg1);
4114 			s390_mlr  (code, s390_r0, ins->sreg2);
4115 			s390_ltr  (code, s390_r0, s390_r0);
4116 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NZ, "OverflowException");
4117 			s390_lgfr (code, ins->dreg, s390_r1);
4118 		}
4119 			break;
4120 		case OP_ICONST:
4121 		case OP_I8CONST: {
4122 			S390_SET (code, ins->dreg, ins->inst_c0);
4123 		}
4124 			break;
4125 		case OP_AOTCONST: {
4126 			mono_add_patch_info (cfg, code - cfg->native_code,
4127 				(MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4128 			S390_LOAD_TEMPLATE (code, ins->dreg);
4129 		}
4130 			break;
4131 		case OP_JUMP_TABLE: {
4132 			mono_add_patch_info (cfg, code - cfg->native_code,
4133 				(MonoJumpInfoType)ins->inst_i1, ins->inst_p0);
4134 			S390_LOAD_TEMPLATE (code, ins->dreg);
4135 		}
4136 			break;
4137 		case OP_MOVE:
4138 			if (ins->dreg != ins->sreg1) {
4139 				s390_lgr (code, ins->dreg, ins->sreg1);
4140 			}
4141 			break;
4142 		case OP_LCONV_TO_I:
4143 		case OP_LCONV_TO_I8:
4144 		case OP_SEXT_I4:
4145 			s390_lgfr (code, ins->dreg, ins->sreg1);
4146 			break;
4147 		case OP_LCONV_TO_I4:
4148 			s390_lgfr (code, ins->dreg, ins->sreg1);
4149 			break;
4150 		case OP_LCONV_TO_U:
4151 		case OP_LCONV_TO_U8:
4152 		case OP_LCONV_TO_U4:
4153 		case OP_ZEXT_I4:
4154 			s390_llgfr (code, ins->dreg, ins->sreg1);
4155 			break;
4156 		case OP_LCONV_TO_OVF_U4:
4157 			S390_SET  (code, s390_r0, 4294967295);
4158 			s390_clgr (code, ins->sreg1, s390_r0);
4159 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4160 			s390_ltgr (code, ins->sreg1, ins->sreg1);
4161 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4162 			s390_llgfr(code, ins->dreg, ins->sreg1);
4163 			break;
4164 		case OP_LCONV_TO_OVF_I4_UN:
4165 			S390_SET  (code, s390_r0, 2147483647);
4166 			s390_cgr  (code, ins->sreg1, s390_r0);
4167 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, "OverflowException");
4168 			s390_ltgr (code, ins->sreg1, ins->sreg1);
4169 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException");
4170 			s390_lgfr (code, ins->dreg, ins->sreg1);
4171 			break;
4172 		case OP_FMOVE:
4173 			if (ins->dreg != ins->sreg1) {
4174 				s390_ldr   (code, ins->dreg, ins->sreg1);
4175 			}
4176 			break;
4177 		case OP_MOVE_F_TO_I8:
4178 			s390_lgdr (code, ins->dreg, ins->sreg1);
4179 			break;
4180 		case OP_MOVE_I8_TO_F:
4181 			s390_ldgr (code, ins->dreg, ins->sreg1);
4182 			break;
4183 		case OP_MOVE_F_TO_I4:
4184 			s390_ledbr (code, s390_f0, ins->sreg1);
4185 			s390_lgdr (code, ins->dreg, s390_f0);
4186 			s390_srag (code, ins->dreg, ins->dreg, 0, 32);
4187 			break;
4188 		case OP_MOVE_I4_TO_F:
4189 			s390_slag (code, s390_r0, ins->sreg1, 0, 32);
4190 			s390_ldgr (code, ins->dreg, s390_r0);
4191 			s390_ldebr (code, ins->dreg, ins->dreg);
4192 			break;
4193 		case OP_FCONV_TO_R4:
4194 			s390_ledbr (code, ins->dreg, ins->sreg1);
4195 			s390_ldebr (code, ins->dreg, ins->dreg);
4196 			break;
4197 		case OP_S390_SETF4RET:
4198 			s390_ledbr (code, ins->dreg, ins->sreg1);
4199 			break;
4200                 case OP_TLS_GET: {
4201 			if (s390_is_imm16 (ins->inst_offset)) {
4202 				s390_lghi (code, s390_r13, ins->inst_offset);
4203 			} else if (s390_is_imm32 (ins->inst_offset)) {
4204 				s390_lgfi (code, s390_r13, ins->inst_offset);
4205 			} else {
4206 				S390_SET  (code, s390_r13, ins->inst_offset);
4207 			}
4208 			s390_ear (code, s390_r1, 0);
4209 			s390_sllg(code, s390_r1, s390_r1, 0, 32);
4210 			s390_ear (code, s390_r1, 1);
4211 			s390_lg  (code, ins->dreg, s390_r13, s390_r1, 0);
4212 			}
4213 			break;
4214                 case OP_TLS_SET: {
4215 			if (s390_is_imm16 (ins->inst_offset)) {
4216 				s390_lghi (code, s390_r13, ins->inst_offset);
4217 			} else if (s390_is_imm32 (ins->inst_offset)) {
4218 				s390_lgfi (code, s390_r13, ins->inst_offset);
4219 			} else {
4220 				S390_SET  (code, s390_r13, ins->inst_offset);
4221 			}
4222 			s390_ear (code, s390_r1, 0);
4223 			s390_sllg(code, s390_r1, s390_r1, 0, 32);
4224 			s390_ear (code, s390_r1, 1);
4225 			s390_stg (code, ins->sreg1, s390_r13, s390_r1, 0);
4226 			}
4227 			break;
4228 		case OP_JMP: {
4229 			if (cfg->method->save_lmf)
4230 				restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
4231 
4232 			if (cfg->flags & MONO_CFG_HAS_TAIL) {
4233 				code =  emit_load_volatile_arguments (code, cfg);
4234 			}
4235 
4236 			code = backUpStackPtr(cfg, code);
4237 			s390_lg  (code, s390_r14, 0, cfg->frame_reg, S390_RET_ADDR_OFFSET);
4238 			mono_add_patch_info (cfg, code - cfg->native_code,
4239 					     MONO_PATCH_INFO_METHOD_JUMP,
4240 					     ins->inst_p0);
4241 			s390_jcl (code, S390_CC_UN, 0);
4242 		}
4243 			break;
4244 		case OP_CHECK_THIS: {
4245 			/* ensure ins->sreg1 is not NULL */
4246 			s390_lg   (code, s390_r0, 0, ins->sreg1, 0);
4247 			s390_ltgr (code, s390_r0, s390_r0);
4248 //			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_ZR, "NullReferenceException");
4249 		}
4250 			break;
4251 		case OP_ARGLIST: {
4252 			int offset = cfg->sig_cookie + cfg->stack_usage;
4253 
4254 			if (s390_is_imm16 (offset)) {
4255 				s390_lghi (code, s390_r0, offset);
4256 			} else if (s390_is_imm32 (offset)) {
4257 				s390_lgfi (code, s390_r0, offset);
4258 			} else {
4259 				S390_SET  (code, s390_r0, offset);
4260 			}
4261 			s390_agr  (code, s390_r0, cfg->frame_reg);
4262 			s390_stg  (code, s390_r0, 0, ins->sreg1, 0);
4263 		}
4264 			break;
4265 		case OP_FCALL: {
4266 			call = (MonoCallInst*)ins;
4267 			if (ins->flags & MONO_INST_HAS_METHOD)
4268 				mono_add_patch_info (cfg, code-cfg->native_code,
4269 						     MONO_PATCH_INFO_METHOD,
4270 						     call->method);
4271 			else
4272 				mono_add_patch_info (cfg, code-cfg->native_code,
4273 						     MONO_PATCH_INFO_ABS,
4274 						     call->fptr);
4275 			S390_CALL_TEMPLATE (code, s390_r14);
4276 			if (call->signature->ret->type == MONO_TYPE_R4)
4277 				s390_ldebr (code, s390_f0, s390_f0);
4278 		}
4279 			break;
4280 		case OP_LCALL:
4281 		case OP_VCALL:
4282 		case OP_VCALL2:
4283 		case OP_VOIDCALL:
4284 		case OP_CALL: {
4285 			call = (MonoCallInst*)ins;
4286 			if (ins->flags & MONO_INST_HAS_METHOD)
4287 				mono_add_patch_info (cfg, code-cfg->native_code,
4288 						     MONO_PATCH_INFO_METHOD,
4289 						     call->method);
4290 			else
4291 				mono_add_patch_info (cfg, code-cfg->native_code,
4292 						     MONO_PATCH_INFO_ABS,
4293 						     call->fptr);
4294 			S390_CALL_TEMPLATE (code, s390_r14);
4295 		}
4296 			break;
4297 		case OP_FCALL_REG: {
4298 			call = (MonoCallInst*)ins;
4299 			s390_lgr  (code, s390_r1, ins->sreg1);
4300 			s390_basr (code, s390_r14, s390_r1);
4301 			if (call->signature->ret->type == MONO_TYPE_R4)
4302 				s390_ldebr (code, s390_f0, s390_f0);
4303 		}
4304 			break;
4305 		case OP_LCALL_REG:
4306 		case OP_VCALL_REG:
4307 		case OP_VCALL2_REG:
4308 		case OP_VOIDCALL_REG:
4309 		case OP_CALL_REG: {
4310 			s390_lgr  (code, s390_r1, ins->sreg1);
4311 			s390_basr (code, s390_r14, s390_r1);
4312 		}
4313 			break;
4314 		case OP_FCALL_MEMBASE: {
4315 			call = (MonoCallInst*)ins;
4316 			s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4317 			s390_basr (code, s390_r14, s390_r1);
4318 			if (call->signature->ret->type == MONO_TYPE_R4)
4319 				s390_ldebr (code, s390_f0, s390_f0);
4320 		}
4321 			break;
4322 		case OP_LCALL_MEMBASE:
4323 		case OP_VCALL_MEMBASE:
4324 		case OP_VCALL2_MEMBASE:
4325 		case OP_VOIDCALL_MEMBASE:
4326 		case OP_CALL_MEMBASE: {
4327 			s390_lg   (code, s390_r1, 0, ins->sreg1, ins->inst_offset);
4328 			s390_basr (code, s390_r14, s390_r1);
4329 		}
4330 			break;
4331 		case OP_LOCALLOC: {
4332 			int alloca_skip;
4333 			int area_offset;
4334 
4335 			if (cfg->param_area == 0)
4336 				alloca_skip = S390_MINIMAL_STACK_SIZE;
4337 			else
4338 				alloca_skip = cfg->param_area;
4339 
4340 			area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT);
4341 			s390_lgr  (code, s390_r1, ins->sreg1);
4342 			if (ins->flags & MONO_INST_INIT)
4343 				s390_lgr  (code, s390_r0, ins->sreg1);
4344 			s390_aghi (code, s390_r1, 14);
4345 			s390_srlg (code, s390_r1, s390_r1, 0, 3);
4346 			s390_sllg (code, s390_r1, s390_r1, 0, 3);
4347 			if (cfg->method->save_lmf) {
4348 				/*----------------------------------*/
4349 				/* we have to adjust lmf ebp value  */
4350 				/*----------------------------------*/
4351 				int lmfOffset = cfg->stack_usage - sizeof(MonoLMF);
4352 
4353 				s390_lgr (code, s390_r13, cfg->frame_reg);
4354 				if (s390_is_imm16(lmfOffset)) {
4355 					s390_aghi (code, s390_r13, lmfOffset);
4356 				} else if (s390_is_imm32(lmfOffset)) {
4357 					s390_agfi (code, s390_r13, lmfOffset);
4358 				} else {
4359 					S390_SET  (code, s390_r13, lmfOffset);
4360 				}
4361 				s390_lgr (code, s390_r14, STK_BASE);
4362 				s390_sgr (code, s390_r14, s390_r1);
4363 				s390_stg (code, s390_r14, 0, s390_r13,
4364 					  G_STRUCT_OFFSET(MonoLMF, ebp));
4365                         }
4366 			s390_lg   (code, s390_r13, 0, STK_BASE, 0);
4367 			s390_sgr  (code, STK_BASE, s390_r1);
4368 			s390_stg  (code, s390_r13, 0, STK_BASE, 0);
4369 			s390_la   (code, ins->dreg, 0, STK_BASE, area_offset);
4370 			s390_srlg (code, ins->dreg, ins->dreg, 0, 3);
4371 			s390_sllg (code, ins->dreg, ins->dreg, 0, 3);
4372 			if (ins->flags & MONO_INST_INIT) {
4373 				s390_lgr  (code, s390_r1, s390_r0);
4374 				s390_lgr  (code, s390_r0, ins->dreg);
4375 				s390_lgr  (code, s390_r14, s390_r12);
4376 				s390_lghi (code, s390_r13, 0);
4377 				s390_mvcle(code, s390_r0, s390_r12, 0, 0);
4378 				s390_jo   (code, -2);
4379 				s390_lgr  (code, s390_r12, s390_r14);
4380 			}
4381 		}
4382 			break;
4383 		case OP_THROW: {
4384 			s390_lgr  (code, s390_r2, ins->sreg1);
4385 			mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4386 					     (gpointer) "mono_arch_throw_exception");
4387 			S390_CALL_TEMPLATE(code, s390_r14);
4388 		}
4389 			break;
4390 		case OP_RETHROW: {
4391 			s390_lgr  (code, s390_r2, ins->sreg1);
4392 			mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4393 					     (gpointer) "mono_arch_rethrow_exception");
4394 			S390_CALL_TEMPLATE(code, s390_r14);
4395 		}
4396 			break;
4397 		case OP_START_HANDLER: {
4398 			MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4399 
4400 			S390_LONG (code, stg, stg, s390_r14, 0,
4401 				   spvar->inst_basereg,
4402 				   spvar->inst_offset);
4403 		}
4404 			break;
4405 		case OP_ENDFILTER: {
4406 			MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4407 
4408 			if (ins->sreg1 != s390_r2)
4409 				s390_lgr(code, s390_r2, ins->sreg1);
4410 			S390_LONG (code, lg, lg, s390_r14, 0,
4411 				   spvar->inst_basereg,
4412 				   spvar->inst_offset);
4413 			s390_br  (code, s390_r14);
4414 		}
4415 			break;
4416 		case OP_ENDFINALLY: {
4417 			MonoInst *spvar = mono_find_spvar_for_region (cfg, bb->region);
4418 
4419 			S390_LONG (code, lg, lg, s390_r14, 0,
4420 				   spvar->inst_basereg,
4421 				   spvar->inst_offset);
4422 			s390_br  (code, s390_r14);
4423 		}
4424 			break;
4425 		case OP_CALL_HANDLER: {
4426 			mono_add_patch_info (cfg, code-cfg->native_code,
4427 					     MONO_PATCH_INFO_BB, ins->inst_target_bb);
4428 			s390_brasl (code, s390_r14, 0);
4429 			for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev)
4430 				mono_cfg_add_try_hole (cfg, (MonoExceptionClause *)tmp->data, code, bb);
4431 		}
4432 			break;
4433 		case OP_LABEL: {
4434 			ins->inst_c0 = code - cfg->native_code;
4435 		}
4436 			break;
4437 		case OP_RELAXED_NOP:
4438 		case OP_NOP:
4439 		case OP_DUMMY_USE:
4440 		case OP_DUMMY_STORE:
4441 		case OP_NOT_REACHED:
4442 		case OP_NOT_NULL: {
4443 		}
4444 			break;
4445 		case OP_IL_SEQ_POINT:
4446 			mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4447 			break;
4448 		case OP_SEQ_POINT: {
4449 			int i;
4450 
4451 			if (cfg->compile_aot)
4452 				NOT_IMPLEMENTED;
4453 
4454 			/*
4455 			 * Read from the single stepping trigger page. This will cause a
4456 			 * SIGSEGV when single stepping is enabled.
4457 			 * We do this _before_ the breakpoint, so single stepping after
4458 			 * a breakpoint is hit will step to the next IL offset.
4459 			 */
4460 			if (ins->flags & MONO_INST_SINGLE_STEP_LOC) {
4461 				breakpointCode.pTrigger = ss_trigger_page;
4462 				memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
4463 				code += BREAKPOINT_SIZE;
4464 			}
4465 
4466 			mono_add_seq_point (cfg, bb, ins, code - cfg->native_code);
4467 
4468 			/*
4469 			 * A placeholder for a possible breakpoint inserted by
4470 			 * mono_arch_set_breakpoint ().
4471 			 */
4472 			for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); ++i)
4473 				s390_nop (code);
4474 
4475 			/*
4476 			 * Add an additional nop so skipping the bp doesn't cause the ip to point
4477 			 * to another IL offset.
4478 			 */
4479 			s390_nop (code);
4480 
4481 			break;
4482 		}
4483 		case OP_GENERIC_CLASS_INIT: {
4484 			static int byte_offset = -1;
4485 			static guint8 bitmask;
4486 			short int *jump;
4487 
4488 			g_assert (ins->sreg1 == S390_FIRST_ARG_REG);
4489 
4490 			if (byte_offset < 0)
4491 				mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
4492 
4493 			s390_tm (code, ins->sreg1, byte_offset, bitmask);
4494 			s390_jo (code, 0); CODEPTR(code, jump);
4495 
4496 			mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_INTERNAL_METHOD,
4497 						"mono_generic_class_init");
4498 			S390_CALL_TEMPLATE(code, s390_r14);
4499 
4500 			PTRSLOT (code, jump);
4501 
4502 			ins->flags |= MONO_INST_GC_CALLSITE;
4503 			ins->backend.pc_offset = code - cfg->native_code;
4504 			break;
4505 		}
4506 		case OP_BR:
4507 			EMIT_UNCOND_BRANCH(ins);
4508 			break;
4509 		case OP_BR_REG: {
4510 			s390_br	 (code, ins->sreg1);
4511 		}
4512 			break;
4513 		case OP_CEQ:
4514 		case OP_ICEQ:
4515 		case OP_LCEQ: {
4516 			s390_lghi(code, ins->dreg, 1);
4517 			s390_jz  (code, 4);
4518 			s390_lghi(code, ins->dreg, 0);
4519 		}
4520 			break;
4521 		case OP_CLT:
4522 		case OP_ICLT:
4523 		case OP_LCLT: {
4524 			s390_lghi(code, ins->dreg, 1);
4525 			s390_jl  (code, 4);
4526 			s390_lghi(code, ins->dreg, 0);
4527 		}
4528 			break;
4529 		case OP_CLT_UN:
4530 		case OP_ICLT_UN:
4531 		case OP_LCLT_UN: {
4532 			s390_lghi(code, ins->dreg, 1);
4533 			s390_jlo (code, 4);
4534 			s390_lghi(code, ins->dreg, 0);
4535 		}
4536 			break;
4537 		case OP_CGT:
4538 		case OP_ICGT:
4539 		case OP_LCGT: {
4540 			s390_lghi(code, ins->dreg, 1);
4541 			s390_jh  (code, 4);
4542 			s390_lghi(code, ins->dreg, 0);
4543 		}
4544 			break;
4545 		case OP_CGT_UN:
4546 		case OP_ICGT_UN:
4547 		case OP_LCGT_UN: {
4548 			s390_lghi(code, ins->dreg, 1);
4549 			s390_jho (code, 4);
4550 			s390_lghi(code, ins->dreg, 0);
4551 		}
4552 			break;
4553 		case OP_ICNEQ: {
4554 			s390_lghi(code, ins->dreg, 1);
4555 			s390_jne (code, 4);
4556 			s390_lghi(code, ins->dreg, 0);
4557 		}
4558 			break;
4559 		case OP_ICGE: {
4560 			s390_lghi(code, ins->dreg, 1);
4561 			s390_jhe (code, 4);
4562 			s390_lghi(code, ins->dreg, 0);
4563 		}
4564 			break;
4565 		case OP_ICLE: {
4566 			s390_lghi(code, ins->dreg, 1);
4567 			s390_jle (code, 4);
4568 			s390_lghi(code, ins->dreg, 0);
4569 		}
4570 			break;
4571 		case OP_ICGE_UN: {
4572 			s390_lghi(code, ins->dreg, 1);
4573 			s390_jhe (code, 4);
4574 			s390_lghi(code, ins->dreg, 0);
4575 		}
4576 			break;
4577 		case OP_ICLE_UN: {
4578 			s390_lghi(code, ins->dreg, 1);
4579 			s390_jle (code, 4);
4580 			s390_lghi(code, ins->dreg, 0);
4581 		}
4582 			break;
4583 		case OP_COND_EXC_EQ:
4584 		case OP_COND_EXC_IEQ:
4585 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_EQ, ins->inst_p1);
4586 			break;
4587 		case OP_COND_EXC_NE_UN:
4588 		case OP_COND_EXC_INE_UN:
4589 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NE, ins->inst_p1);
4590 			break;
4591 		case OP_COND_EXC_LT:
4592 		case OP_COND_EXC_ILT:
4593 		case OP_COND_EXC_LT_UN:
4594 		case OP_COND_EXC_ILT_UN:
4595 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, ins->inst_p1);
4596 			break;
4597 		case OP_COND_EXC_GT:
4598 		case OP_COND_EXC_IGT:
4599 		case OP_COND_EXC_GT_UN:
4600 		case OP_COND_EXC_IGT_UN:
4601 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GT, ins->inst_p1);
4602 			break;
4603 		case OP_COND_EXC_GE:
4604 		case OP_COND_EXC_IGE:
4605 		case OP_COND_EXC_GE_UN:
4606 		case OP_COND_EXC_IGE_UN:
4607 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_GE, ins->inst_p1);
4608 			break;
4609 		case OP_COND_EXC_LE:
4610 		case OP_COND_EXC_ILE:
4611 		case OP_COND_EXC_LE_UN:
4612 		case OP_COND_EXC_ILE_UN:
4613 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LE, ins->inst_p1);
4614 			break;
4615 		case OP_COND_EXC_OV:
4616 		case OP_COND_EXC_IOV:
4617 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, ins->inst_p1);
4618 			break;
4619 		case OP_COND_EXC_NO:
4620 		case OP_COND_EXC_INO:
4621 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NO, ins->inst_p1);
4622 			break;
4623 		case OP_COND_EXC_C:
4624 		case OP_COND_EXC_IC:
4625 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, ins->inst_p1);
4626 			break;
4627 		case OP_COND_EXC_NC:
4628 		case OP_COND_EXC_INC:
4629 			EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, ins->inst_p1);
4630 			break;
4631 		case OP_LBEQ:
4632 		case OP_IBEQ:
4633 			EMIT_COND_BRANCH (ins, S390_CC_EQ);
4634 			break;
4635 		case OP_LBNE_UN:
4636 		case OP_IBNE_UN:
4637 			EMIT_COND_BRANCH (ins, S390_CC_NE);
4638 			break;
4639 		case OP_LBLT:
4640 		case OP_LBLT_UN:
4641 		case OP_IBLT:
4642 		case OP_IBLT_UN:
4643 			EMIT_COND_BRANCH (ins, S390_CC_LT);
4644 			break;
4645 		case OP_LBGT:
4646 		case OP_LBGT_UN:
4647 		case OP_IBGT:
4648 		case OP_IBGT_UN:
4649 			EMIT_COND_BRANCH (ins, S390_CC_GT);
4650 			break;
4651 		case OP_LBGE:
4652 		case OP_LBGE_UN:
4653 		case OP_IBGE:
4654 		case OP_IBGE_UN:
4655 			EMIT_COND_BRANCH (ins, S390_CC_GE);
4656 			break;
4657 		case OP_LBLE:
4658 		case OP_LBLE_UN:
4659 		case OP_IBLE:
4660 		case OP_IBLE_UN:
4661 			EMIT_COND_BRANCH (ins, S390_CC_LE);
4662 			break;
4663 
4664 		case OP_S390_CRJ:
4665 			EMIT_COMP_AND_BRANCH(ins, crj, cr);
4666 			break;
4667 
4668 		case OP_S390_CLRJ:
4669 			EMIT_COMP_AND_BRANCH(ins, clrj, clr);
4670 			break;
4671 
4672 		case OP_S390_CGRJ:
4673 			EMIT_COMP_AND_BRANCH(ins, cgrj, cgr);
4674 			break;
4675 
4676 		case OP_S390_CLGRJ:
4677 			EMIT_COMP_AND_BRANCH(ins, clgrj, clgr);
4678 			break;
4679 
4680 		case OP_S390_CIJ:
4681 			EMIT_COMP_AND_BRANCH_IMM(ins, crj, cr, ltr, FALSE);
4682 			break;
4683 
4684 		case OP_S390_CLIJ:
4685 			EMIT_COMP_AND_BRANCH_IMM(ins, clrj, clr, ltr, TRUE);
4686 			break;
4687 
4688 		case OP_S390_CGIJ:
4689 			EMIT_COMP_AND_BRANCH_IMM(ins, cgrj, cgr, ltgr, FALSE);
4690 			break;
4691 
4692 		case OP_S390_CLGIJ:
4693 			EMIT_COMP_AND_BRANCH_IMM(ins, clgrj, clgr, ltgr, TRUE);
4694 			break;
4695 
4696 		/* floating point opcodes */
4697 		case OP_R8CONST: {
4698 			if (*((double *) ins->inst_p0) == 0) {
4699 				s390_lzdr (code, ins->dreg);
4700 			} else {
4701 				S390_SET  (code, s390_r13, ins->inst_p0);
4702 				s390_ld	  (code, ins->dreg, 0, s390_r13, 0);
4703 			}
4704 		}
4705 			break;
4706 		case OP_R4CONST: {
4707 			if (*((float *) ins->inst_p0) == 0) {
4708 				s390_lzdr (code, ins->dreg);
4709 			} else {
4710 				S390_SET  (code, s390_r13, ins->inst_p0);
4711 				s390_ldeb (code, ins->dreg, 0, s390_r13, 0);
4712 			}
4713 		}
4714 			break;
4715 		case OP_STORER8_MEMBASE_REG: {
4716 			S390_LONG (code, stdy, std, ins->sreg1, 0,
4717 				   ins->inst_destbasereg, ins->inst_offset);
4718 		}
4719 			break;
4720 		case OP_LOADR8_MEMBASE: {
4721 			S390_LONG (code, ldy, ld, ins->dreg, 0,
4722 				   ins->inst_basereg, ins->inst_offset);
4723 		}
4724 			break;
4725 		case OP_STORER4_MEMBASE_REG: {
4726 			s390_ledbr (code, s390_f15, ins->sreg1);
4727 			S390_LONG (code, stey, ste, s390_f15, 0,
4728 				   ins->inst_destbasereg, ins->inst_offset);
4729 		}
4730 			break;
4731 		case OP_LOADR4_MEMBASE: {
4732 			S390_LONG (code, ley, le, s390_f15, 0,
4733 				   ins->inst_basereg, ins->inst_offset);
4734 			s390_ldebr (code, ins->dreg, s390_f15);
4735 		}
4736 			break;
4737 		case OP_ICONV_TO_R_UN: {
4738 			if (mono_hwcap_s390x_has_fpe) {
4739 				s390_cdlfbr (code, ins->dreg, 5, ins->sreg1, 0);
4740 			} else {
4741 				s390_llgfr (code, s390_r0, ins->sreg1);
4742 				s390_cdgbr (code, ins->dreg, s390_r0);
4743 			}
4744 		}
4745 			break;
4746 		case OP_LCONV_TO_R_UN: {
4747 			if (mono_hwcap_s390x_has_fpe) {
4748 				s390_cdlgbr (code, ins->dreg, 5, ins->sreg1, 0);
4749 			} else {
4750 				short int *jump;
4751 				s390_cxgbr (code, s390_f12, ins->sreg1);
4752 				s390_ltgr  (code, ins->sreg1, ins->sreg1);
4753 				s390_jnl   (code, 0); CODEPTR(code, jump);
4754 				S390_SET   (code, s390_r13, 0x403f000000000000llu);
4755 				s390_lgdr  (code, s390_f13, s390_r13);
4756 				s390_lzdr  (code, s390_f15);
4757 				s390_axbr  (code, s390_f12, s390_f13);
4758 				PTRSLOT(code, jump);
4759 				s390_ldxbr (code, s390_f13, s390_f12);
4760 				s390_ldr   (code, ins->dreg, s390_f13);
4761 			}
4762 		}
4763 			break;
4764 		case OP_LCONV_TO_R4:
4765 		case OP_ICONV_TO_R4: {
4766 			s390_cegbr (code, ins->dreg, ins->sreg1);
4767 			s390_ldebr (code, ins->dreg, ins->dreg);
4768 		}
4769 			break;
4770 		case OP_LCONV_TO_R8:
4771 		case OP_ICONV_TO_R8: {
4772 			s390_cdgbr (code, ins->dreg, ins->sreg1);
4773 		}
4774 			break;
4775 		case OP_FCONV_TO_I1:
4776 			s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4777 			s390_ltgr  (code, ins->dreg, ins->dreg);
4778 			s390_jnl   (code, 4);
4779 			s390_oill  (code, ins->dreg, 0x80);
4780 			s390_lghi  (code, s390_r0, 0xff);
4781 			s390_ngr   (code, ins->dreg, s390_r0);
4782 			break;
4783 		case OP_FCONV_TO_U1:
4784 			if (mono_hwcap_s390x_has_fpe) {
4785 				s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4786 				s390_lghi  (code, s390_r0, 0xff);
4787 				s390_ngr   (code, ins->dreg, s390_r0);
4788 			} else {
4789 				code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 1, FALSE);
4790 			}
4791 			break;
4792 		case OP_FCONV_TO_I2:
4793 			s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4794 			s390_ltgr  (code, ins->dreg, ins->dreg);
4795 			s390_jnl   (code, 4);
4796 			s390_oill  (code, ins->dreg, 0x8000);
4797 			s390_llill (code, s390_r0, 0xffff);
4798 			s390_ngr   (code, ins->dreg, s390_r0);
4799 			break;
4800 		case OP_FCONV_TO_U2:
4801 			if (mono_hwcap_s390x_has_fpe) {
4802 				s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4803 				s390_llill  (code, s390_r0, 0xffff);
4804 				s390_ngr    (code, ins->dreg, s390_r0);
4805 			} else {
4806 				code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 2, FALSE);
4807 			}
4808 			break;
4809 		case OP_FCONV_TO_I4:
4810 		case OP_FCONV_TO_I:
4811 			s390_cfdbr (code, ins->dreg, 5, ins->sreg1);
4812 			break;
4813 		case OP_FCONV_TO_U4:
4814 		case OP_FCONV_TO_U:
4815 			if (mono_hwcap_s390x_has_fpe) {
4816 				s390_clfdbr (code, ins->dreg, 5, ins->sreg1, 0);
4817 			} else {
4818 				code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 4, FALSE);
4819 			}
4820 			break;
4821 		case OP_FCONV_TO_I8:
4822 			s390_cgdbr (code, ins->dreg, 5, ins->sreg1);
4823 			break;
4824 		case OP_FCONV_TO_U8:
4825 			if (mono_hwcap_s390x_has_fpe) {
4826 				s390_clgdbr (code, ins->dreg, 5, ins->sreg1, 0);
4827 			} else {
4828 				code = emit_float_to_int (cfg, code, ins->dreg, ins->sreg1, 8, FALSE);
4829 			}
4830 			break;
4831 		case OP_LCONV_TO_OVF_I: {
4832 			/* Valid ints: 0xffffffff:8000000 to 00000000:0x7f000000 */
4833 			short int *o[5];
4834 			s390_ltgr (code, ins->sreg2, ins->sreg2);
4835 			s390_jnl  (code, 0); CODEPTR(code, o[0]);
4836 			s390_ltgr (code, ins->sreg1, ins->sreg1);
4837 			s390_jnl  (code, 0); CODEPTR(code, o[1]);
4838 			s390_lhi  (code, s390_r13, -1);
4839 			s390_cgr  (code, ins->sreg1, s390_r13);
4840 			s390_jnz  (code, 0); CODEPTR(code, o[2]);
4841 			if (ins->dreg != ins->sreg2)
4842 				s390_lgr  (code, ins->dreg, ins->sreg2);
4843 			s390_j	  (code, 0); CODEPTR(code, o[3]);
4844 			PTRSLOT(code, o[0]);
4845 			s390_jz   (code, 0); CODEPTR(code, o[4]);
4846 			PTRSLOT(code, o[1]);
4847 			PTRSLOT(code, o[2]);
4848 			mono_add_patch_info (cfg, code - cfg->native_code,
4849 					     MONO_PATCH_INFO_EXC, "OverflowException");
4850 			s390_brasl (code, s390_r14, 0);
4851 			PTRSLOT(code, o[3]);
4852 			PTRSLOT(code, o[4]);
4853 		}
4854 			break;
4855 		case OP_ABS: {
4856 			s390_lpdbr (code, ins->dreg, ins->sreg1);
4857 		}
4858 			break;
4859 		case OP_SQRT: {
4860 			s390_sqdbr (code, ins->dreg, ins->sreg1);
4861 		}
4862 			break;
4863 		case OP_FADD: {
4864 			CHECK_SRCDST_COM_F;
4865 			s390_adbr (code, ins->dreg, src2);
4866 		}
4867 			break;
4868 		case OP_FSUB: {
4869 			CHECK_SRCDST_NCOM_F;
4870 			s390_sdbr (code, ins->dreg, src2);
4871 		}
4872 			break;
4873 		case OP_FMUL: {
4874 			CHECK_SRCDST_COM_F;
4875 			s390_mdbr (code, ins->dreg, src2);
4876 		}
4877 			break;
4878 		case OP_FDIV: {
4879 			CHECK_SRCDST_NCOM_F;
4880 			s390_ddbr (code, ins->dreg, src2);
4881 		}
4882 			break;
4883 		case OP_FNEG: {
4884 			s390_lcdbr (code, ins->dreg, ins->sreg1);
4885 		}
4886 			break;
4887 		case OP_FREM: {
4888 			CHECK_SRCDST_NCOM_F;
4889 			s390_didbr (code, ins->dreg, src2, 5, s390_f15);
4890 		}
4891 			break;
4892 		case OP_FCOMPARE: {
4893 			s390_cdbr (code, ins->sreg1, ins->sreg2);
4894 		}
4895 			break;
4896 		case OP_FCEQ: {
4897 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4898 			s390_lghi  (code, ins->dreg, 1);
4899 			s390_je    (code, 4);
4900 			s390_lghi  (code, ins->dreg, 0);
4901 		}
4902 			break;
4903 		case OP_FCLT: {
4904 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4905 			s390_lghi  (code, ins->dreg, 1);
4906 			s390_jl    (code, 4);
4907 			s390_lghi  (code, ins->dreg, 0);
4908 		}
4909 			break;
4910 		case OP_FCLT_UN: {
4911 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4912 			s390_lghi  (code, ins->dreg, 1);
4913 			s390_jlo   (code, 4);
4914 			s390_lghi  (code, ins->dreg, 0);
4915 		}
4916 			break;
4917 		case OP_FCGT: {
4918 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4919 			s390_lghi  (code, ins->dreg, 1);
4920 			s390_jh    (code, 4);
4921 			s390_lghi  (code, ins->dreg, 0);
4922 		}
4923 			break;
4924 		case OP_FCGT_UN: {
4925 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4926 			s390_lghi  (code, ins->dreg, 1);
4927 			s390_jho   (code, 4);
4928 			s390_lghi  (code, ins->dreg, 0);
4929 		}
4930 			break;
4931 		case OP_FCNEQ: {
4932 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4933 			s390_lghi  (code, ins->dreg, 1);
4934 			s390_jne   (code, 4);
4935 			s390_lghi  (code, ins->dreg, 0);
4936 		}
4937 			break;
4938 		case OP_FCGE: {
4939 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4940 			s390_lghi  (code, ins->dreg, 1);
4941 			s390_jhe   (code, 4);
4942 			s390_lghi  (code, ins->dreg, 0);
4943 		}
4944 			break;
4945 		case OP_FCLE: {
4946 			s390_cdbr  (code, ins->sreg1, ins->sreg2);
4947 			s390_lghi  (code, ins->dreg, 1);
4948 			s390_jle   (code, 4);
4949 			s390_lghi  (code, ins->dreg, 0);
4950 		}
4951 			break;
4952 		case OP_FBEQ: {
4953 			short *o;
4954 			s390_jo (code, 0); CODEPTR(code, o);
4955 			EMIT_COND_BRANCH (ins, S390_CC_EQ);
4956 			PTRSLOT (code, o);
4957 		}
4958 			break;
4959 		case OP_FBNE_UN:
4960 			EMIT_COND_BRANCH (ins, S390_CC_NE|S390_CC_OV);
4961 			break;
4962 		case OP_FBLT: {
4963 			short *o;
4964 			s390_jo (code, 0); CODEPTR(code, o);
4965 			EMIT_COND_BRANCH (ins, S390_CC_LT);
4966 			PTRSLOT (code, o);
4967 		}
4968 			break;
4969 		case OP_FBLT_UN:
4970 			EMIT_COND_BRANCH (ins, S390_CC_LT|S390_CC_OV);
4971 			break;
4972 		case OP_FBGT: {
4973 			short *o;
4974 			s390_jo (code, 0); CODEPTR(code, o);
4975 			EMIT_COND_BRANCH (ins, S390_CC_GT);
4976 			PTRSLOT (code, o);
4977 		}
4978 			break;
4979 		case OP_FBGT_UN:
4980 			EMIT_COND_BRANCH (ins, S390_CC_GT|S390_CC_OV);
4981 			break;
4982 		case OP_FBGE: {
4983 			short *o;
4984 			s390_jo (code, 0); CODEPTR(code, o);
4985 			EMIT_COND_BRANCH (ins, S390_CC_GE);
4986 			PTRSLOT (code, o);
4987 		}
4988 			break;
4989 		case OP_FBGE_UN:
4990 			EMIT_COND_BRANCH (ins, S390_CC_GE|S390_CC_OV);
4991 			break;
4992 		case OP_FBLE: {
4993 			short *o;
4994 			s390_jo (code, 0); CODEPTR(code, o);
4995 			EMIT_COND_BRANCH (ins, S390_CC_LE);
4996 			PTRSLOT (code, o);
4997 		}
4998 			break;
4999 		case OP_FBLE_UN:
5000 			EMIT_COND_BRANCH (ins, S390_CC_LE|S390_CC_OV);
5001 			break;
5002 		case OP_CKFINITE: {
5003 			short *o;
5004 			s390_lhi  (code, s390_r13, 0x7f);
5005 			s390_tcdb (code, ins->sreg1, 0, s390_r13, 0);
5006 			s390_jz   (code, 0); CODEPTR(code, o);
5007 			mono_add_patch_info (cfg, code - cfg->native_code,
5008 					     MONO_PATCH_INFO_EXC, "OverflowException");
5009 			s390_brasl (code, s390_r14,0);
5010 			PTRSLOT(code, o);
5011 		}
5012 			break;
5013 		case OP_S390_MOVE: {
5014 			if (ins->backend.size > 0) {
5015 				if (ins->backend.size <= 256) {
5016 					s390_mvc  (code, ins->backend.size, ins->dreg,
5017 						   ins->inst_offset, ins->sreg1, ins->inst_imm);
5018 				} else {
5019 					s390_lgr  (code, s390_r0, ins->dreg);
5020 					if (ins->inst_offset > 0) {
5021 						if (s390_is_imm16 (ins->inst_offset)) {
5022 							s390_aghi (code, s390_r0, ins->inst_offset);
5023 						} else if (s390_is_imm32 (ins->inst_offset)) {
5024 							s390_agfi (code, s390_r0, ins->inst_offset);
5025 						} else {
5026 							S390_SET  (code, s390_r13, ins->inst_offset);
5027 							s390_agr  (code, s390_r0, s390_r13);
5028 						}
5029 					}
5030 					s390_lgr  (code, s390_r12, ins->sreg1);
5031 					if (ins->inst_imm > 0) {
5032 						if (s390_is_imm16 (ins->inst_imm)) {
5033 							s390_aghi (code, s390_r12, ins->inst_imm);
5034 						} else if (s390_is_imm32 (ins->inst_imm)) {
5035 							s390_agfi (code, s390_r12, ins->inst_imm);
5036 						} else {
5037 							S390_SET  (code, s390_r13, ins->inst_imm);
5038 							s390_agr  (code, s390_r12, s390_r13);
5039 						}
5040 					}
5041 					if (s390_is_imm16 (ins->backend.size)) {
5042 						s390_lghi (code, s390_r1, ins->backend.size);
5043 					} else if (s390_is_imm32 (ins->inst_offset)) {
5044 						s390_agfi (code, s390_r1, ins->backend.size);
5045 					} else {
5046 						S390_SET  (code, s390_r13, ins->backend.size);
5047 						s390_agr  (code, s390_r1, s390_r13);
5048 					}
5049 					s390_lgr  (code, s390_r13, s390_r1);
5050 					s390_mvcle(code, s390_r0, s390_r12, 0, 0);
5051 					s390_jo   (code, -2);
5052 				}
5053 			}
5054 		}
5055 			break;
5056 		case OP_ATOMIC_ADD_I8: {
5057 			if (mono_hwcap_s390x_has_ia) {
5058 				s390_laag (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5059 				s390_agr  (code, ins->dreg, ins->sreg2);
5060 			} else {
5061 				s390_lgr (code, s390_r1, ins->sreg2);
5062 				s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5063 				s390_agr (code, s390_r1, s390_r0);
5064 				s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5065 				s390_jnz (code, -10);
5066 				s390_lgr (code, ins->dreg, s390_r1);
5067 			}
5068 		}
5069 			break;
5070 		case OP_ATOMIC_EXCHANGE_I8: {
5071 			s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5072 			s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5073 			s390_jnz (code, -6);
5074 			s390_lgr (code, ins->dreg, s390_r0);
5075 		}
5076 			break;
5077 		case OP_ATOMIC_ADD_I4: {
5078 			if (mono_hwcap_s390x_has_ia) {
5079 				s390_laa (code, ins->dreg, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5080 				s390_ar  (code, ins->dreg, ins->sreg2);
5081 			} else {
5082 				s390_lgfr(code, s390_r1, ins->sreg2);
5083 				s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5084 				s390_agr (code, s390_r1, s390_r0);
5085 				s390_cs  (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
5086 				s390_jnz (code, -9);
5087 				s390_lgfr(code, ins->dreg, s390_r1);
5088 			}
5089 		}
5090 			break;
5091 		case OP_ATOMIC_EXCHANGE_I4: {
5092 			s390_l   (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
5093 			s390_cs  (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
5094 			s390_jnz (code, -4);
5095 			s390_lgfr(code, ins->dreg, s390_r0);
5096 		}
5097 			break;
5098 		case OP_S390_BKCHAIN: {
5099 			s390_lgr  (code, ins->dreg, ins->sreg1);
5100 			if (s390_is_imm16 (cfg->stack_offset)) {
5101 				s390_aghi (code, ins->dreg, cfg->stack_offset);
5102 			} else if (s390_is_imm32 (cfg->stack_offset)) {
5103 				s390_agfi (code, ins->dreg, cfg->stack_offset);
5104 			} else {
5105 				S390_SET  (code, s390_r13, cfg->stack_offset);
5106 				s390_agr  (code, ins->dreg, s390_r13);
5107 			}
5108 		}
5109 			break;
5110 		case OP_MEMORY_BARRIER:
5111 			s390_mem (code);
5112 			break;
5113 		case OP_GC_SAFE_POINT: {
5114 			short *br;
5115 
5116 			g_assert (mono_threads_is_coop_enabled ());
5117 
5118 			s390_ltg (code, s390_r0, 0, ins->sreg1, 0);
5119 			s390_jz  (code, 0); CODEPTR(code, br);
5120 			mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_ABS,
5121 					     mono_threads_state_poll);
5122 			S390_CALL_TEMPLATE (code, s390_r14);
5123 			PTRSLOT (code, br);
5124 			break;
5125 		}
5126 		case OP_GC_LIVENESS_DEF:
5127 		case OP_GC_LIVENESS_USE:
5128 		case OP_GC_PARAM_SLOT_LIVENESS_DEF:
5129 			ins->backend.pc_offset = code - cfg->native_code;
5130 			break;
5131 		case OP_GC_SPILL_SLOT_LIVENESS_DEF:
5132 			ins->backend.pc_offset = code - cfg->native_code;
5133 			bb->spill_slot_defs = g_slist_prepend_mempool (cfg->mempool, bb->spill_slot_defs, ins);
5134 			break;
5135 #ifdef MONO_ARCH_SIMD_INTRINSICS
5136 		case OP_ADDPS:
5137 			s390x_addps (code, ins->sreg1, ins->sreg2);
5138 			break;
5139 		case OP_DIVPS:
5140 			s390x_divps (code, ins->sreg1, ins->sreg2);
5141 			break;
5142 		case OP_MULPS:
5143 			s390x_mulps (code, ins->sreg1, ins->sreg2);
5144 			break;
5145 		case OP_SUBPS:
5146 			s390x_subps (code, ins->sreg1, ins->sreg2);
5147 			break;
5148 		case OP_MAXPS:
5149 			s390x_maxps (code, ins->sreg1, ins->sreg2);
5150 			break;
5151 		case OP_MINPS:
5152 			s390x_minps (code, ins->sreg1, ins->sreg2);
5153 			break;
5154 		case OP_COMPPS:
5155 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5156 			s390x_cmpps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5157 			break;
5158 		case OP_ANDPS:
5159 			s390x_andps (code, ins->sreg1, ins->sreg2);
5160 			break;
5161 		case OP_ANDNPS:
5162 			s390x_andnps (code, ins->sreg1, ins->sreg2);
5163 			break;
5164 		case OP_ORPS:
5165 			s390x_orps (code, ins->sreg1, ins->sreg2);
5166 			break;
5167 		case OP_XORPS:
5168 			s390x_xorps (code, ins->sreg1, ins->sreg2);
5169 			break;
5170 		case OP_SQRTPS:
5171 			s390x_sqrtps (code, ins->dreg, ins->sreg1);
5172 			break;
5173 		case OP_RSQRTPS:
5174 			s390x_rsqrtps (code, ins->dreg, ins->sreg1);
5175 			break;
5176 		case OP_RCPPS:
5177 			s390x_rcpps (code, ins->dreg, ins->sreg1);
5178 			break;
5179 		case OP_ADDSUBPS:
5180 			s390x_addsubps (code, ins->sreg1, ins->sreg2);
5181 			break;
5182 		case OP_HADDPS:
5183 			s390x_haddps (code, ins->sreg1, ins->sreg2);
5184 			break;
5185 		case OP_HSUBPS:
5186 			s390x_hsubps (code, ins->sreg1, ins->sreg2);
5187 			break;
5188 		case OP_DUPPS_HIGH:
5189 			s390x_movshdup (code, ins->dreg, ins->sreg1);
5190 			break;
5191 		case OP_DUPPS_LOW:
5192 			s390x_movsldup (code, ins->dreg, ins->sreg1);
5193 			break;
5194 
5195 		case OP_PSHUFLEW_HIGH:
5196 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5197 			s390x_pshufhw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5198 			break;
5199 		case OP_PSHUFLEW_LOW:
5200 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5201 			s390x_pshuflw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5202 			break;
5203 		case OP_PSHUFLED:
5204 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5205 			s390x_pshufd_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5206 			break;
5207 		case OP_SHUFPS:
5208 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0xFF);
5209 			s390x_shufps_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5210 			break;
5211 		case OP_SHUFPD:
5212 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 0x3);
5213 			s390x_shufpd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5214 			break;
5215 
5216 		case OP_ADDPD:
5217 			s390x_addpd (code, ins->sreg1, ins->sreg2);
5218 			break;
5219 		case OP_DIVPD:
5220 			s390x_divpd (code, ins->sreg1, ins->sreg2);
5221 			break;
5222 		case OP_MULPD:
5223 			s390x_mulpd (code, ins->sreg1, ins->sreg2);
5224 			break;
5225 		case OP_SUBPD:
5226 			s390x_subpd (code, ins->sreg1, ins->sreg2);
5227 			break;
5228 		case OP_MAXPD:
5229 			s390x_maxpd (code, ins->sreg1, ins->sreg2);
5230 			break;
5231 		case OP_MINPD:
5232 			s390x_minpd (code, ins->sreg1, ins->sreg2);
5233 			break;
5234 		case OP_COMPPD:
5235 			g_assert (ins->inst_c0 >= 0 && ins->inst_c0 <= 7);
5236 			s390x_cmppd_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5237 			break;
5238 		case OP_ANDPD:
5239 			s390x_andpd (code, ins->sreg1, ins->sreg2);
5240 			break;
5241 		case OP_ANDNPD:
5242 			s390x_andnpd (code, ins->sreg1, ins->sreg2);
5243 			break;
5244 		case OP_ORPD:
5245 			s390x_orpd (code, ins->sreg1, ins->sreg2);
5246 			break;
5247 		case OP_XORPD:
5248 			s390x_xorpd (code, ins->sreg1, ins->sreg2);
5249 			break;
5250 		case OP_SQRTPD:
5251 			s390x_sqrtpd (code, ins->dreg, ins->sreg1);
5252 			break;
5253 		case OP_ADDSUBPD:
5254 			s390x_addsubpd (code, ins->sreg1, ins->sreg2);
5255 			break;
5256 		case OP_HADDPD:
5257 			s390x_haddpd (code, ins->sreg1, ins->sreg2);
5258 			break;
5259 		case OP_HSUBPD:
5260 			s390x_hsubpd (code, ins->sreg1, ins->sreg2);
5261 			break;
5262 		case OP_DUPPD:
5263 			s390x_movddup (code, ins->dreg, ins->sreg1);
5264 			break;
5265 
5266 		case OP_EXTRACT_MASK:
5267 			s390x_pmovmskb (code, ins->dreg, ins->sreg1);
5268 			break;
5269 
5270 		case OP_PAND:
5271 			s390x_pand (code, ins->sreg1, ins->sreg2);
5272 			break;
5273 		case OP_POR:
5274 			s390x_por (code, ins->sreg1, ins->sreg2);
5275 			break;
5276 		case OP_PXOR:
5277 			s390x_pxor (code, ins->sreg1, ins->sreg2);
5278 			break;
5279 
5280 		case OP_PADDB:
5281 			s390x_paddb (code, ins->sreg1, ins->sreg2);
5282 			break;
5283 		case OP_PADDW:
5284 			s390x_paddw (code, ins->sreg1, ins->sreg2);
5285 			break;
5286 		case OP_PADDD:
5287 			s390x_paddd (code, ins->sreg1, ins->sreg2);
5288 			break;
5289 		case OP_PADDQ:
5290 			s390x_paddq (code, ins->sreg1, ins->sreg2);
5291 			break;
5292 
5293 		case OP_PSUBB:
5294 			s390x_psubb (code, ins->sreg1, ins->sreg2);
5295 			break;
5296 		case OP_PSUBW:
5297 			s390x_psubw (code, ins->sreg1, ins->sreg2);
5298 			break;
5299 		case OP_PSUBD:
5300 			s390x_psubd (code, ins->sreg1, ins->sreg2);
5301 			break;
5302 		case OP_PSUBQ:
5303 			s390x_psubq (code, ins->sreg1, ins->sreg2);
5304 			break;
5305 
5306 		case OP_PMAXB_UN:
5307 			s390x_pmaxub (code, ins->sreg1, ins->sreg2);
5308 			break;
5309 		case OP_PMAXW_UN:
5310 			s390x_pmaxuw (code, ins->sreg1, ins->sreg2);
5311 			break;
5312 		case OP_PMAXD_UN:
5313 			s390x_pmaxud (code, ins->sreg1, ins->sreg2);
5314 			break;
5315 
5316 		case OP_PMAXB:
5317 			s390x_pmaxsb (code, ins->sreg1, ins->sreg2);
5318 			break;
5319 		case OP_PMAXW:
5320 			s390x_pmaxsw (code, ins->sreg1, ins->sreg2);
5321 			break;
5322 		case OP_PMAXD:
5323 			s390x_pmaxsd (code, ins->sreg1, ins->sreg2);
5324 			break;
5325 
5326 		case OP_PAVGB_UN:
5327 			s390x_pavgb (code, ins->sreg1, ins->sreg2);
5328 			break;
5329 		case OP_PAVGW_UN:
5330 			s390x_pavgw (code, ins->sreg1, ins->sreg2);
5331 			break;
5332 
5333 		case OP_PMINB_UN:
5334 			s390x_pminub (code, ins->sreg1, ins->sreg2);
5335 			break;
5336 		case OP_PMINW_UN:
5337 			s390x_pminuw (code, ins->sreg1, ins->sreg2);
5338 			break;
5339 		case OP_PMIND_UN:
5340 			s390x_pminud (code, ins->sreg1, ins->sreg2);
5341 			break;
5342 
5343 		case OP_PMINB:
5344 			s390x_pminsb (code, ins->sreg1, ins->sreg2);
5345 			break;
5346 		case OP_PMINW:
5347 			s390x_pminsw (code, ins->sreg1, ins->sreg2);
5348 			break;
5349 		case OP_PMIND:
5350 			s390x_pminsd (code, ins->sreg1, ins->sreg2);
5351 			break;
5352 
5353 		case OP_PCMPEQB:
5354 			s390x_pcmpeqb (code, ins->sreg1, ins->sreg2);
5355 			break;
5356 		case OP_PCMPEQW:
5357 			s390x_pcmpeqw (code, ins->sreg1, ins->sreg2);
5358 			break;
5359 		case OP_PCMPEQD:
5360 			s390x_pcmpeqd (code, ins->sreg1, ins->sreg2);
5361 			break;
5362 		case OP_PCMPEQQ:
5363 			s390x_pcmpeqq (code, ins->sreg1, ins->sreg2);
5364 			break;
5365 
5366 		case OP_PCMPGTB:
5367 			s390x_pcmpgtb (code, ins->sreg1, ins->sreg2);
5368 			break;
5369 		case OP_PCMPGTW:
5370 			s390x_pcmpgtw (code, ins->sreg1, ins->sreg2);
5371 			break;
5372 		case OP_PCMPGTD:
5373 			s390x_pcmpgtd (code, ins->sreg1, ins->sreg2);
5374 			break;
5375 		case OP_PCMPGTQ:
5376 			s390x_pcmpgtq (code, ins->sreg1, ins->sreg2);
5377 			break;
5378 
5379 		case OP_PSUM_ABS_DIFF:
5380 			s390x_psadbw (code, ins->sreg1, ins->sreg2);
5381 			break;
5382 
5383 		case OP_UNPACK_LOWB:
5384 			s390x_punpcklbw (code, ins->sreg1, ins->sreg2);
5385 			break;
5386 		case OP_UNPACK_LOWW:
5387 			s390x_punpcklwd (code, ins->sreg1, ins->sreg2);
5388 			break;
5389 		case OP_UNPACK_LOWD:
5390 			s390x_punpckldq (code, ins->sreg1, ins->sreg2);
5391 			break;
5392 		case OP_UNPACK_LOWQ:
5393 			s390x_punpcklqdq (code, ins->sreg1, ins->sreg2);
5394 			break;
5395 		case OP_UNPACK_LOWPS:
5396 			s390x_unpcklps (code, ins->sreg1, ins->sreg2);
5397 			break;
5398 		case OP_UNPACK_LOWPD:
5399 			s390x_unpcklpd (code, ins->sreg1, ins->sreg2);
5400 			break;
5401 
5402 		case OP_UNPACK_HIGHB:
5403 			s390x_punpckhbw (code, ins->sreg1, ins->sreg2);
5404 			break;
5405 		case OP_UNPACK_HIGHW:
5406 			s390x_punpckhwd (code, ins->sreg1, ins->sreg2);
5407 			break;
5408 		case OP_UNPACK_HIGHD:
5409 			s390x_punpckhdq (code, ins->sreg1, ins->sreg2);
5410 			break;
5411 		case OP_UNPACK_HIGHQ:
5412 			s390x_punpckhqdq (code, ins->sreg1, ins->sreg2);
5413 			break;
5414 		case OP_UNPACK_HIGHPS:
5415 			s390x_unpckhps (code, ins->sreg1, ins->sreg2);
5416 			break;
5417 		case OP_UNPACK_HIGHPD:
5418 			s390x_unpckhpd (code, ins->sreg1, ins->sreg2);
5419 			break;
5420 
5421 		case OP_PACKW:
5422 			s390x_packsswb (code, ins->sreg1, ins->sreg2);
5423 			break;
5424 		case OP_PACKD:
5425 			s390x_packssdw (code, ins->sreg1, ins->sreg2);
5426 			break;
5427 		case OP_PACKW_UN:
5428 			s390x_packuswb (code, ins->sreg1, ins->sreg2);
5429 			break;
5430 		case OP_PACKD_UN:
5431 			s390x_packusdw (code, ins->sreg1, ins->sreg2);
5432 			break;
5433 
5434 		case OP_PADDB_SAT_UN:
5435 			s390x_paddusb (code, ins->sreg1, ins->sreg2);
5436 			break;
5437 		case OP_PSUBB_SAT_UN:
5438 			s390x_psubusb (code, ins->sreg1, ins->sreg2);
5439 			break;
5440 		case OP_PADDW_SAT_UN:
5441 			s390x_paddusw (code, ins->sreg1, ins->sreg2);
5442 			break;
5443 		case OP_PSUBW_SAT_UN:
5444 			s390x_psubusw (code, ins->sreg1, ins->sreg2);
5445 			break;
5446 
5447 		case OP_PADDB_SAT:
5448 			s390x_paddsb (code, ins->sreg1, ins->sreg2);
5449 			break;
5450 		case OP_PSUBB_SAT:
5451 			s390x_psubsb (code, ins->sreg1, ins->sreg2);
5452 			break;
5453 		case OP_PADDW_SAT:
5454 			s390x_paddsw (code, ins->sreg1, ins->sreg2);
5455 			break;
5456 		case OP_PSUBW_SAT:
5457 			s390x_psubsw (code, ins->sreg1, ins->sreg2);
5458 			break;
5459 
5460 		case OP_PMULW:
5461 			s390x_pmullw (code, ins->sreg1, ins->sreg2);
5462 			break;
5463 		case OP_PMULD:
5464 			s390x_pmulld (code, ins->sreg1, ins->sreg2);
5465 			break;
5466 		case OP_PMULQ:
5467 			s390x_pmuludq (code, ins->sreg1, ins->sreg2);
5468 			break;
5469 		case OP_PMULW_HIGH_UN:
5470 			s390x_pmulhuw (code, ins->sreg1, ins->sreg2);
5471 			break;
5472 		case OP_PMULW_HIGH:
5473 			s390x_pmulhw (code, ins->sreg1, ins->sreg2);
5474 			break;
5475 
5476 		case OP_PSHRW:
5477 			s390x_psrlw_reg_imm (code, ins->dreg, ins->inst_imm);
5478 			break;
5479 		case OP_PSHRW_REG:
5480 			s390x_psrlw (code, ins->dreg, ins->sreg2);
5481 			break;
5482 
5483 		case OP_PSARW:
5484 			s390x_psraw_reg_imm (code, ins->dreg, ins->inst_imm);
5485 			break;
5486 		case OP_PSARW_REG:
5487 			s390x_psraw (code, ins->dreg, ins->sreg2);
5488 			break;
5489 
5490 		case OP_PSHLW:
5491 			s390x_psllw_reg_imm (code, ins->dreg, ins->inst_imm);
5492 			break;
5493 		case OP_PSHLW_REG:
5494 			s390x_psllw (code, ins->dreg, ins->sreg2);
5495 			break;
5496 
5497 		case OP_PSHRD:
5498 			s390x_psrld_reg_imm (code, ins->dreg, ins->inst_imm);
5499 			break;
5500 		case OP_PSHRD_REG:
5501 			s390x_psrld (code, ins->dreg, ins->sreg2);
5502 			break;
5503 
5504 		case OP_PSARD:
5505 			s390x_psrad_reg_imm (code, ins->dreg, ins->inst_imm);
5506 			break;
5507 		case OP_PSARD_REG:
5508 			s390x_psrad (code, ins->dreg, ins->sreg2);
5509 			break;
5510 
5511 		case OP_PSHLD:
5512 			s390x_pslld_reg_imm (code, ins->dreg, ins->inst_imm);
5513 			break;
5514 		case OP_PSHLD_REG:
5515 			s390x_pslld (code, ins->dreg, ins->sreg2);
5516 			break;
5517 
5518 		case OP_PSHRQ:
5519 			s390x_psrlq_reg_imm (code, ins->dreg, ins->inst_imm);
5520 			break;
5521 		case OP_PSHRQ_REG:
5522 			s390x_psrlq (code, ins->dreg, ins->sreg2);
5523 			break;
5524 
5525 		/*TODO: This is appart of the sse spec but not added
5526 		case OP_PSARQ:
5527 			s390x_psraq_reg_imm (code, ins->dreg, ins->inst_imm);
5528 			break;
5529 		case OP_PSARQ_REG:
5530 			s390x_psraq (code, ins->dreg, ins->sreg2);
5531 			break;
5532 		*/
5533 
5534 		case OP_PSHLQ:
5535 			s390x_psllq_reg_imm (code, ins->dreg, ins->inst_imm);
5536 			break;
5537 		case OP_PSHLQ_REG:
5538 			s390x_psllq (code, ins->dreg, ins->sreg2);
5539 			break;
5540 		case OP_CVTDQ2PD:
5541 			s390x_cvtdq2pd (code, ins->dreg, ins->sreg1);
5542 			break;
5543 		case OP_CVTDQ2PS:
5544 			s390x_cvtdq2ps (code, ins->dreg, ins->sreg1);
5545 			break;
5546 		case OP_CVTPD2DQ:
5547 			s390x_cvtpd2dq (code, ins->dreg, ins->sreg1);
5548 			break;
5549 		case OP_CVTPD2PS:
5550 			s390x_cvtpd2ps (code, ins->dreg, ins->sreg1);
5551 			break;
5552 		case OP_CVTPS2DQ:
5553 			s390x_cvtps2dq (code, ins->dreg, ins->sreg1);
5554 			break;
5555 		case OP_CVTPS2PD:
5556 			s390x_cvtps2pd (code, ins->dreg, ins->sreg1);
5557 			break;
5558 		case OP_CVTTPD2DQ:
5559 			s390x_cvttpd2dq (code, ins->dreg, ins->sreg1);
5560 			break;
5561 		case OP_CVTTPS2DQ:
5562 			s390x_cvttps2dq (code, ins->dreg, ins->sreg1);
5563 			break;
5564 
5565 		case OP_ICONV_TO_X:
5566 			amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5567 			break;
5568 		case OP_EXTRACT_I4:
5569 			amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5570 			break;
5571 		case OP_EXTRACT_I8:
5572 			if (ins->inst_c0) {
5573 				amd64_movhlps (code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg1);
5574 				amd64_movd_reg_xreg_size (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG, 8);
5575 			} else {
5576 				amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 8);
5577 			}
5578 			break;
5579 		case OP_EXTRACT_I1:
5580 		case OP_EXTRACT_U1:
5581 			amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5582 			if (ins->inst_c0)
5583 				amd64_shift_reg_imm (code, X86_SHR, ins->dreg, ins->inst_c0 * 8);
5584 			amd64_widen_reg (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I1, FALSE);
5585 			break;
5586 		case OP_EXTRACT_I2:
5587 		case OP_EXTRACT_U2:
5588 			/*amd64_movd_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5589 			if (ins->inst_c0)
5590 				amd64_shift_reg_imm_size (code, X86_SHR, ins->dreg, 16, 4);*/
5591 			s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5592 			amd64_widen_reg_size (code, ins->dreg, ins->dreg, ins->opcode == OP_EXTRACT_I2, TRUE, 4);
5593 			break;
5594 		case OP_EXTRACT_R8:
5595 			if (ins->inst_c0)
5596 				amd64_movhlps (code, ins->dreg, ins->sreg1);
5597 			else
5598 				s390x_movsd (code, ins->dreg, ins->sreg1);
5599 			break;
5600 		case OP_INSERT_I2:
5601 			s390x_pinsrw_imm (code, ins->sreg1, ins->sreg2, ins->inst_c0);
5602 			break;
5603 		case OP_EXTRACTX_U2:
5604 			s390x_pextrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0);
5605 			break;
5606 		case OP_INSERTX_U1_SLOW:
5607 			/*sreg1 is the extracted ireg (scratch)
5608 			/sreg2 is the to be inserted ireg (scratch)
5609 			/dreg is the xreg to receive the value*/
5610 
5611 			/*clear the bits from the extracted word*/
5612 			amd64_alu_reg_imm (code, X86_AND, ins->sreg1, ins->inst_c0 & 1 ? 0x00FF : 0xFF00);
5613 			/*shift the value to insert if needed*/
5614 			if (ins->inst_c0 & 1)
5615 				amd64_shift_reg_imm_size (code, X86_SHL, ins->sreg2, 8, 4);
5616 			/*join them together*/
5617 			amd64_alu (code, X86_OR, ins->sreg1, ins->sreg2);
5618 			s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, ins->inst_c0 / 2);
5619 			break;
5620 		case OP_INSERTX_I4_SLOW:
5621 			s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2);
5622 			amd64_shift_reg_imm (code, X86_SHR, ins->sreg2, 16);
5623 			s390x_pinsrw_imm (code, ins->dreg, ins->sreg2, ins->inst_c0 * 2 + 1);
5624 			break;
5625 		case OP_INSERTX_I8_SLOW:
5626 			amd64_movd_xreg_reg_size(code, MONO_ARCH_FP_SCRATCH_REG, ins->sreg2, 8);
5627 			if (ins->inst_c0)
5628 				amd64_movlhps (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5629 			else
5630 				s390x_movsd (code, ins->dreg, MONO_ARCH_FP_SCRATCH_REG);
5631 			break;
5632 
5633 		case OP_INSERTX_R4_SLOW:
5634 			switch (ins->inst_c0) {
5635 			case 0:
5636 				if (cfg->r4fp)
5637 					s390x_movss (code, ins->dreg, ins->sreg2);
5638 				else
5639 					s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5640 				break;
5641 			case 1:
5642 				s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5643 				if (cfg->r4fp)
5644 					s390x_movss (code, ins->dreg, ins->sreg2);
5645 				else
5646 					s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5647 				s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(1, 0, 2, 3));
5648 				break;
5649 			case 2:
5650 				s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5651 				if (cfg->r4fp)
5652 					s390x_movss (code, ins->dreg, ins->sreg2);
5653 				else
5654 					s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5655 				s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(2, 1, 0, 3));
5656 				break;
5657 			case 3:
5658 				s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5659 				if (cfg->r4fp)
5660 					s390x_movss (code, ins->dreg, ins->sreg2);
5661 				else
5662 					s390x_cvtsd2ss (code, ins->dreg, ins->sreg2);
5663 				s390x_pshufd_imm (code, ins->dreg, ins->dreg, mono_simd_shuffle_mask(3, 1, 2, 0));
5664 				break;
5665 			}
5666 			break;
5667 		case OP_INSERTX_R8_SLOW:
5668 			if (ins->inst_c0)
5669 				amd64_movlhps (code, ins->dreg, ins->sreg2);
5670 			else
5671 				s390x_movsd (code, ins->dreg, ins->sreg2);
5672 			break;
5673 		case OP_STOREX_MEMBASE_REG:
5674 		case OP_STOREX_MEMBASE:
5675 			s390x_movups_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5676 			break;
5677 		case OP_LOADX_MEMBASE:
5678 			s390x_movups_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5679 			break;
5680 		case OP_LOADX_ALIGNED_MEMBASE:
5681 			s390x_movaps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5682 			break;
5683 		case OP_STOREX_ALIGNED_MEMBASE_REG:
5684 			s390x_movaps_membase_reg (code, ins->dreg, ins->inst_offset, ins->sreg1);
5685 			break;
5686 		case OP_STOREX_NTA_MEMBASE_REG:
5687 			s390x_movntps_reg_membase (code, ins->dreg, ins->sreg1, ins->inst_offset);
5688 			break;
5689 		case OP_PREFETCH_MEMBASE:
5690 			s390x_prefetch_reg_membase (code, ins->backend.arg_info, ins->sreg1, ins->inst_offset);
5691 			break;
5692 
5693 		case OP_XMOVE:
5694 			/*FIXME the peephole pass should have killed this*/
5695 			if (ins->dreg != ins->sreg1)
5696 				s390x_movaps (code, ins->dreg, ins->sreg1);
5697 			break;
5698 		case OP_XZERO:
5699 			s390x_pxor (code, ins->dreg, ins->dreg);
5700 			break;
5701 		case OP_ICONV_TO_R4_RAW:
5702 			amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5703 			break;
5704 
5705 		case OP_FCONV_TO_R8_X:
5706 			s390x_movsd (code, ins->dreg, ins->sreg1);
5707 			break;
5708 
5709 		case OP_XCONV_R8_TO_I4:
5710 			s390x_cvttsd2si_reg_xreg_size (code, ins->dreg, ins->sreg1, 4);
5711 			switch (ins->backend.source_opcode) {
5712 			case OP_FCONV_TO_I1:
5713 				amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, FALSE);
5714 				break;
5715 			case OP_FCONV_TO_U1:
5716 				amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, FALSE);
5717 				break;
5718 			case OP_FCONV_TO_I2:
5719 				amd64_widen_reg (code, ins->dreg, ins->dreg, TRUE, TRUE);
5720 				break;
5721 			case OP_FCONV_TO_U2:
5722 				amd64_widen_reg (code, ins->dreg, ins->dreg, FALSE, TRUE);
5723 				break;
5724 			}
5725 			break;
5726 
5727 		case OP_EXPAND_I2:
5728 			s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 0);
5729 			s390x_pinsrw_imm (code, ins->dreg, ins->sreg1, 1);
5730 			s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5731 			break;
5732 		case OP_EXPAND_I4:
5733 			amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 4);
5734 			s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5735 			break;
5736 		case OP_EXPAND_I8:
5737 			amd64_movd_xreg_reg_size (code, ins->dreg, ins->sreg1, 8);
5738 			s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5739 			break;
5740 		case OP_EXPAND_R4:
5741 			if (cfg->r4fp) {
5742 				s390x_movsd (code, ins->dreg, ins->sreg1);
5743 			} else {
5744 				s390x_movsd (code, ins->dreg, ins->sreg1);
5745 				s390x_cvtsd2ss (code, ins->dreg, ins->dreg);
5746 			}
5747 			s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0);
5748 			break;
5749 		case OP_EXPAND_R8:
5750 			s390x_movsd (code, ins->dreg, ins->sreg1);
5751 			s390x_pshufd_imm (code, ins->dreg, ins->dreg, 0x44);
5752 			break;
5753 #endif
5754 		default:
5755 			g_warning ("unknown opcode %s in %s()\n", mono_inst_name (ins->opcode), __FUNCTION__);
5756 			g_assert_not_reached ();
5757 		}
5758 
5759 		if ((cfg->opt & MONO_OPT_BRANCH) && ((code - cfg->native_code - offset) > max_len)) {
5760 			g_warning ("wrong maximal instruction length of instruction %s (expected %d, got %ld)",
5761 				   mono_inst_name (ins->opcode), max_len, code - cfg->native_code - offset);
5762 			g_assert_not_reached ();
5763 		}
5764 
5765 		last_offset = offset;
5766 	}
5767 
5768 	cfg->code_len = code - cfg->native_code;
5769 }
5770 
5771 /*========================= End of Function ========================*/
5772 
5773 /*------------------------------------------------------------------*/
5774 /*                                                                  */
5775 /* Name		- mono_arch_register_lowlevel_calls                 */
5776 /*                                                                  */
5777 /* Function	- Register routines to help with --trace operation. */
5778 /*		                               			    */
5779 /*------------------------------------------------------------------*/
5780 
5781 void
mono_arch_register_lowlevel_calls(void)5782 mono_arch_register_lowlevel_calls (void)
5783 {
5784 }
5785 
5786 /*========================= End of Function ========================*/
5787 
5788 /*------------------------------------------------------------------*/
5789 /*                                                                  */
5790 /* Name		- mono_arch_patch_code                              */
5791 /*                                                                  */
5792 /* Function	- Process the patch data created during the         */
5793 /*		  instruction build process. This resolves jumps,   */
5794 /*		  calls, variables etc.        			    */
5795 /*		                               			    */
5796 /*------------------------------------------------------------------*/
5797 
5798 void
mono_arch_patch_code(MonoCompile * cfg,MonoMethod * method,MonoDomain * domain,guint8 * code,MonoJumpInfo * ji,gboolean run_cctors,MonoError * error)5799 mono_arch_patch_code (MonoCompile *cfg, MonoMethod *method, MonoDomain *domain,
5800 		      guint8 *code, MonoJumpInfo *ji, gboolean run_cctors,
5801 		      MonoError *error)
5802 {
5803 	MonoJumpInfo *patch_info;
5804 
5805 	error_init (error);
5806 
5807 	for (patch_info = ji; patch_info; patch_info = patch_info->next) {
5808 		unsigned char *ip = patch_info->ip.i + code;
5809 		gconstpointer target = NULL;
5810 
5811 		target = mono_resolve_patch_target (method, domain, code,
5812 						    patch_info, run_cctors, error);
5813 		return_if_nok (error);
5814 
5815 		switch (patch_info->type) {
5816 			case MONO_PATCH_INFO_IP:
5817 			case MONO_PATCH_INFO_LDSTR:
5818 			case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
5819 			case MONO_PATCH_INFO_LDTOKEN:
5820 			case MONO_PATCH_INFO_EXC:
5821 				s390_patch_addr (ip, (guint64) target);
5822 				continue;
5823 			case MONO_PATCH_INFO_METHOD:
5824 			case MONO_PATCH_INFO_INTERNAL_METHOD:
5825 			case MONO_PATCH_INFO_JIT_ICALL_ADDR:
5826 			case MONO_PATCH_INFO_RGCTX_FETCH:
5827 			case MONO_PATCH_INFO_ABS: {
5828 				S390_EMIT_CALL (ip, target);
5829 				continue;
5830 			}
5831 			case MONO_PATCH_INFO_SWITCH:
5832 				/*----------------------------------*/
5833 				/* ip points at the basr r13,0/j +4 */
5834 				/* instruction the vtable value     */
5835 				/* follows this (i.e. ip+6)	    */
5836 				/*----------------------------------*/
5837 				S390_EMIT_LOAD (ip, target);
5838 				continue;
5839 			case MONO_PATCH_INFO_METHODCONST:
5840 			case MONO_PATCH_INFO_CLASS:
5841 			case MONO_PATCH_INFO_IMAGE:
5842 			case MONO_PATCH_INFO_FIELD:
5843 			case MONO_PATCH_INFO_IID:
5844 			case MONO_PATCH_INFO_EXC_NAME:
5845 				target = S390_RELATIVE(target, ip);
5846 				s390_patch_rel (ip, (guint64) target);
5847 				continue;
5848 			case MONO_PATCH_INFO_R4:
5849 			case MONO_PATCH_INFO_R8:
5850 			case MONO_PATCH_INFO_METHOD_REL:
5851 				g_assert_not_reached ();
5852 				continue;
5853 			default:
5854 				target = S390_RELATIVE(target, ip);
5855 				ip += 2;
5856 				s390_patch_rel (ip, (guint64) target);
5857 		}
5858 	}
5859 }
5860 
5861 /*========================= End of Function ========================*/
5862 
5863 /*------------------------------------------------------------------*/
5864 /*                                                                  */
5865 /* Name         - emit_load_volatile_arguments                      */
5866 /*                                                                  */
5867 /* Function     - Emit the instructions to reload parameter regist- */
5868 /*                registers for use with "tail" operations.         */
5869 /*                                                                  */
5870 /*                The register loading operations performed here    */
5871 /*                are the mirror of the store operations performed  */
5872 /*                in mono_arch_emit_prolog and need to be kept in   */
5873 /*                synchronization with it.                          */
5874 /*                                                                  */
5875 /*------------------------------------------------------------------*/
5876 
5877 guint8 *
emit_load_volatile_arguments(guint8 * code,MonoCompile * cfg)5878 emit_load_volatile_arguments (guint8 *code, MonoCompile *cfg)
5879 {
5880 	MonoInst *inst;
5881 	MonoMethod *method = cfg->method;
5882 	MonoMethodSignature *sig = mono_method_signature(method);
5883 	int pos = 0, i;
5884 	CallInfo *cinfo;
5885 
5886 	cinfo = get_call_info (NULL, NULL, sig);
5887 
5888 	if (cinfo->struct_ret) {
5889 		ArgInfo *ainfo = &cinfo->ret;
5890 		inst         = cfg->vret_addr;
5891 		s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5892 	}
5893 
5894 	for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
5895 		ArgInfo *ainfo = cinfo->args + i;
5896 		inst = cfg->args [pos];
5897 
5898 		if (inst->opcode == OP_REGVAR) {
5899 			if (ainfo->regtype == RegTypeGeneral)
5900 				s390_lgr (code, ainfo->reg, inst->dreg);
5901 			else if (ainfo->regtype == RegTypeFP) {
5902 				if (inst->dreg != ainfo->reg) {
5903 					if (ainfo->size == 4) {
5904 						s390_ldebr (code, ainfo->reg, inst->dreg);
5905 					} else {
5906 						s390_ldr   (code, ainfo->reg, inst->dreg);
5907 					}
5908 				}
5909 			}
5910 			else if (ainfo->regtype == RegTypeBase) {
5911 			} else
5912 				g_assert_not_reached ();
5913 		} else {
5914 			if (ainfo->regtype == RegTypeGeneral) {
5915 				if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
5916 					g_assert_not_reached();
5917 				switch (ainfo->size) {
5918 				case 1:
5919 					s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5920 					break;
5921 				case 2:
5922 					s390_lgh  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5923 					break;
5924 				case 4:
5925 					s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5926 					break;
5927 				case 8:
5928 					s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5929 					break;
5930 				}
5931 			} else if (ainfo->regtype == RegTypeBase) {
5932 			} else if (ainfo->regtype == RegTypeFP) {
5933 				if (ainfo->size == 8)
5934 					s390_ld  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5935 				else if (ainfo->size == 4)
5936 					s390_le  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5937 				else
5938 					g_assert_not_reached ();
5939 			} else if (ainfo->regtype == RegTypeStructByVal) {
5940 				if (ainfo->reg != STK_BASE) {
5941 					switch (ainfo->size) {
5942 					case 1:
5943 						s390_llgc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5944 						break;
5945 					case 2:
5946 						s390_lgh (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5947 						break;
5948 					case 4:
5949 						s390_lgf (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5950 						break;
5951 					case 8:
5952 						s390_lg  (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5953 						break;
5954 					}
5955 				}
5956 			} else if (ainfo->regtype == RegTypeStructByAddr) {
5957 				if (ainfo->reg != STK_BASE) {
5958 					s390_lg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
5959 				}
5960 			} else
5961 				g_assert_not_reached ();
5962 		}
5963 		pos++;
5964 	}
5965 
5966 	return code;
5967 }
5968 
5969 /*========================= End of Function ========================*/
5970 
5971 /*------------------------------------------------------------------*/
5972 /*                                                                  */
5973 /* Name		- mono_arch_emit_prolog                             */
5974 /*                                                                  */
5975 /* Function	- Create the instruction sequence for a function    */
5976 /*		  prolog.                      			    */
5977 /*		                               			    */
5978 /*------------------------------------------------------------------*/
5979 
5980 guint8 *
mono_arch_emit_prolog(MonoCompile * cfg)5981 mono_arch_emit_prolog (MonoCompile *cfg)
5982 {
5983 	MonoMethod *method = cfg->method;
5984 	MonoBasicBlock *bb;
5985 	MonoMethodSignature *sig;
5986 	MonoInst *inst;
5987 	long alloc_size, pos, max_offset, i, cfa_offset = 0;
5988 	guint8 *code;
5989 	guint32 size;
5990 	CallInfo *cinfo;
5991 	int tracing = 0,
5992             argsClobbered = 0,
5993 	    lmfOffset,
5994 	    fpOffset;
5995 
5996 	cfg->code_size   = 512;
5997 
5998 	if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
5999 		tracing         = 1;
6000 		cfg->code_size += 256;
6001 	}
6002 
6003 	if (method->save_lmf)
6004 		cfg->code_size += 200;
6005 
6006 	cfg->native_code = code = g_malloc (cfg->code_size);
6007 
6008 	mono_emit_unwind_op_def_cfa (cfg, code, STK_BASE, 0);
6009 	emit_unwind_regs(cfg, code, s390_r6, s390_r14, S390_REG_SAVE_OFFSET);
6010 	s390_stmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6011 	mono_emit_unwind_op_offset (cfg, code, s390_r14, S390_RET_ADDR_OFFSET);
6012 	mini_gc_set_slot_type_from_cfa (cfg, S390_RET_ADDR_OFFSET, SLOT_NOREF);
6013 
6014 	if (cfg->arch.bkchain_reg != -1)
6015 		s390_lgr (code, cfg->arch.bkchain_reg, STK_BASE);
6016 
6017 	if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6018 		cfg->used_int_regs |= 1 << 11;
6019 	}
6020 
6021 	alloc_size = cfg->stack_offset;
6022 
6023 	cfg->stack_usage = cfa_offset = alloc_size;
6024 	mono_emit_unwind_op_def_cfa_offset (cfg, code, alloc_size);
6025 	s390_lgr  (code, s390_r11, STK_BASE);
6026 	if (s390_is_imm16 (alloc_size)) {
6027 		s390_aghi (code, STK_BASE, -alloc_size);
6028 	} else if (s390_is_imm32 (alloc_size)) {
6029 		s390_agfi (code, STK_BASE, -alloc_size);
6030 	} else {
6031 		int stackSize = alloc_size;
6032 		while (stackSize > INT_MAX) {
6033 			s390_agfi (code, STK_BASE, -INT_MAX);
6034 			stackSize -= INT_MAX;
6035 		}
6036 		s390_agfi (code, STK_BASE, -stackSize);
6037 	}
6038 	s390_stg  (code, s390_r11, 0, STK_BASE, 0);
6039 
6040 	if (cfg->frame_reg != STK_BASE)
6041 		s390_lgr (code, s390_r11, STK_BASE);
6042 
6043 	mono_emit_unwind_op_def_cfa_reg (cfg, code, cfg->frame_reg);
6044 
6045 	/* store runtime generic context */
6046 	if (cfg->rgctx_var) {
6047 		g_assert (cfg->rgctx_var->opcode == OP_REGOFFSET);
6048 
6049 		s390_stg  (code, MONO_ARCH_RGCTX_REG, 0,
6050 			   cfg->rgctx_var->inst_basereg,
6051 			   cfg->rgctx_var->inst_offset);
6052 	}
6053 
6054         /* compute max_offset in order to use short forward jumps
6055 	 * we always do it on s390 because the immediate displacement
6056 	 * for jumps is too small
6057 	 */
6058 	max_offset = 0;
6059 	for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
6060 		MonoInst *ins;
6061 		bb->max_offset = max_offset;
6062 
6063 		MONO_BB_FOR_EACH_INS (bb, ins)
6064 			max_offset += ((guint8 *)ins_get_spec (ins->opcode))[MONO_INST_LEN];
6065 	}
6066 
6067 	/* load arguments allocated to register from the stack */
6068 	sig = mono_method_signature (method);
6069 	pos = 0;
6070 
6071 	cinfo = get_call_info (cfg, cfg->mempool, sig);
6072 
6073 	if (cinfo->struct_ret) {
6074 		ArgInfo *ainfo     = &cinfo->ret;
6075 		inst               = cfg->vret_addr;
6076 		inst->backend.size = ainfo->vtsize;
6077 		s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6078 	}
6079 
6080 	for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6081 		ArgInfo *ainfo = cinfo->args + i;
6082 		inst = cfg->args [pos];
6083 
6084 		if (inst->opcode == OP_VTARG_ADDR)
6085 			inst = inst->inst_left;
6086 
6087 		if (inst->opcode == OP_REGVAR) {
6088 			if (ainfo->regtype == RegTypeGeneral)
6089 				s390_lgr (code, inst->dreg, ainfo->reg);
6090 			else if (ainfo->regtype == RegTypeFP) {
6091 				if (inst->dreg != ainfo->reg) {
6092 					if (ainfo->size == 4) {
6093 						s390_ledbr (code, inst->dreg, ainfo->reg);
6094 					} else {
6095 						s390_ldr   (code, inst->dreg, ainfo->reg);
6096 					}
6097 				}
6098 			}
6099 			else if (ainfo->regtype == RegTypeBase) {
6100 				s390_lgr  (code, s390_r13, STK_BASE);
6101 				s390_aghi (code, s390_r13, alloc_size);
6102 				s390_lg   (code, inst->dreg, 0, s390_r13, ainfo->offset);
6103 			} else
6104 				g_assert_not_reached ();
6105 
6106 			if (cfg->verbose_level > 2)
6107 				g_print ("Argument %d assigned to register %s\n",
6108 					 pos, mono_arch_regname (inst->dreg));
6109 		} else {
6110 			if (ainfo->regtype == RegTypeGeneral) {
6111 				if (!((ainfo->reg >= 2) && (ainfo->reg <= 6)))
6112 					g_assert_not_reached();
6113 				switch (ainfo->size) {
6114 				case 1:
6115 					s390_stc (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6116 					break;
6117 				case 2:
6118 					s390_sth (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6119 					break;
6120 				case 4:
6121 					s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6122 					break;
6123 				case 8:
6124 					s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6125 					break;
6126 				}
6127 			} else if (ainfo->regtype == RegTypeBase) {
6128 			} else if (ainfo->regtype == RegTypeFP) {
6129 				if (ainfo->size == 8)
6130 					s390_std (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6131 				else if (ainfo->size == 4)
6132 					s390_ste (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6133 				else
6134 					g_assert_not_reached ();
6135 			} else if (ainfo->regtype == RegTypeStructByVal) {
6136 				int doffset = inst->inst_offset;
6137 				int reg;
6138 				if (ainfo->reg != STK_BASE)
6139 					reg = ainfo->reg;
6140 				else {
6141 					reg = s390_r0;
6142 					s390_lgr  (code, s390_r13, STK_BASE);
6143 					s390_aghi (code, s390_r13, alloc_size);
6144 				}
6145 
6146 				size = (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE
6147 					? mono_class_native_size(mono_class_from_mono_type(inst->inst_vtype), NULL)
6148 					: ainfo->size);
6149 
6150 				switch (size) {
6151 					case 1:
6152 						if (ainfo->reg == STK_BASE)
6153 				                	s390_ic (code, reg, 0, s390_r13, ainfo->offset+7);
6154 						s390_stc (code, reg, 0, inst->inst_basereg, doffset);
6155 						break;
6156 					case 2:
6157 						if (ainfo->reg == STK_BASE)
6158 				                	s390_lh (code, reg, 0, s390_r13, ainfo->offset+6);
6159 						s390_sth (code, reg, 0, inst->inst_basereg, doffset);
6160 						break;
6161 					case 4:
6162 						if (ainfo->reg == STK_BASE)
6163 				                	s390_l  (code, reg, 0, s390_r13, ainfo->offset+4);
6164 						s390_st (code, reg, 0, inst->inst_basereg, doffset);
6165 						break;
6166 					case 8:
6167 						if (ainfo->reg == STK_BASE)
6168 				                	s390_lg  (code, reg, 0, s390_r13, ainfo->offset);
6169 						s390_stg (code, reg, 0, inst->inst_basereg, doffset);
6170 						break;
6171 				}
6172 			} else if (ainfo->regtype == RegTypeStructByAddr) {
6173 				s390_stg (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset);
6174 			} else if (ainfo->regtype == RegTypeStructByAddrOnStack) {
6175 			} else
6176 				g_assert_not_reached ();
6177 		}
6178 		pos++;
6179 	}
6180 
6181 	if (method->save_lmf) {
6182 		/*---------------------------------------------------------------*/
6183 		/* build the MonoLMF structure on the stack - see mini-s390x.h   */
6184 		/*---------------------------------------------------------------*/
6185 		lmfOffset = alloc_size - sizeof(MonoLMF);
6186 
6187 		s390_lgr   (code, s390_r13, cfg->frame_reg);
6188 		s390_aghi  (code, s390_r13, lmfOffset);
6189 
6190 		/*---------------------------------------------------------------*/
6191 		/* Preserve the parameter registers while we fix up the lmf	 */
6192 		/*---------------------------------------------------------------*/
6193 		s390_stmg  (code, s390_r2, s390_r6, s390_r13,
6194 			    G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6195 
6196 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[0]), SLOT_NOREF);
6197 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[1]), SLOT_NOREF);
6198 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[2]), SLOT_NOREF);
6199 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[3]), SLOT_NOREF);
6200 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, pregs[4]), SLOT_NOREF);
6201 
6202 		/*---------------------------------------------------------------*/
6203 		/* On return from this call r2 have the address of the &lmf	 */
6204 		/*---------------------------------------------------------------*/
6205 		mono_add_patch_info (cfg, code - cfg->native_code,
6206 				MONO_PATCH_INFO_INTERNAL_METHOD,
6207 				(gpointer)"mono_tls_get_lmf_addr");
6208 		S390_CALL_TEMPLATE(code, s390_r1);
6209 
6210 		/*---------------------------------------------------------------*/
6211 		/* Set lmf.lmf_addr = jit_tls->lmf				 */
6212 		/*---------------------------------------------------------------*/
6213 		s390_stg   (code, s390_r2, 0, s390_r13,
6214 			    G_STRUCT_OFFSET(MonoLMF, lmf_addr));
6215 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, lmf_addr), SLOT_NOREF);
6216 
6217 		/*---------------------------------------------------------------*/
6218 		/* Get current lmf						 */
6219 		/*---------------------------------------------------------------*/
6220 		s390_lg    (code, s390_r0, 0, s390_r2, 0);
6221 
6222 		/*---------------------------------------------------------------*/
6223 		/* Set our lmf as the current lmf				 */
6224 		/*---------------------------------------------------------------*/
6225 		s390_stg   (code, s390_r13, 0, s390_r2, 0);
6226 
6227 		/*---------------------------------------------------------------*/
6228 		/* Have our lmf.previous_lmf point to the last lmf		 */
6229 		/*---------------------------------------------------------------*/
6230 		s390_stg   (code, s390_r0, 0, s390_r13,
6231 			    G_STRUCT_OFFSET(MonoLMF, previous_lmf));
6232 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), SLOT_NOREF);
6233 
6234 		/*---------------------------------------------------------------*/
6235 		/* save method info						 */
6236 		/*---------------------------------------------------------------*/
6237 		S390_SET   (code, s390_r1, method);
6238 		s390_stg   (code, s390_r1, 0, s390_r13,
6239 			    G_STRUCT_OFFSET(MonoLMF, method));
6240 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, method), SLOT_NOREF);
6241 
6242 		/*---------------------------------------------------------------*/
6243 		/* save the current IP						 */
6244 		/*---------------------------------------------------------------*/
6245 		s390_stg   (code, STK_BASE, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp));
6246 		s390_basr  (code, s390_r1, 0);
6247 		s390_stg   (code, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip));
6248 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, ebp), SLOT_NOREF);
6249 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, eip), SLOT_NOREF);
6250 
6251 		/*---------------------------------------------------------------*/
6252 		/* Save general and floating point registers			 */
6253 		/*---------------------------------------------------------------*/
6254 		s390_stmg  (code, s390_r2, s390_r12, s390_r13,
6255 			    G_STRUCT_OFFSET(MonoLMF, gregs[2]));
6256 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[0]), SLOT_NOREF);
6257 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[1]), SLOT_NOREF);
6258 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[2]), SLOT_NOREF);
6259 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[3]), SLOT_NOREF);
6260 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[4]), SLOT_NOREF);
6261 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[5]), SLOT_NOREF);
6262 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[6]), SLOT_NOREF);
6263 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[7]), SLOT_NOREF);
6264 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[8]), SLOT_NOREF);
6265 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[9]), SLOT_NOREF);
6266 		mini_gc_set_slot_type_from_fp (cfg, lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, gregs[10]), SLOT_NOREF);
6267 
6268 		fpOffset = lmfOffset + MONO_STRUCT_OFFSET (MonoLMF, fregs[0]);
6269 		for (i = 0; i < 16; i++) {
6270 			s390_std  (code, i, 0, s390_r13,
6271 				   G_STRUCT_OFFSET(MonoLMF, fregs[i]));
6272 			mini_gc_set_slot_type_from_fp (cfg, fpOffset, SLOT_NOREF);
6273 			fpOffset += sizeof(double);
6274 		}
6275 
6276 		/*---------------------------------------------------------------*/
6277 		/* Restore the parameter registers now that we've set up the lmf */
6278 		/*---------------------------------------------------------------*/
6279 		s390_lmg   (code, s390_r2, s390_r6, s390_r13,
6280 			    G_STRUCT_OFFSET(MonoLMF, pregs[0]));
6281 	}
6282 
6283 	if (cfg->method->save_lmf)
6284 		argsClobbered = TRUE;
6285 
6286 	if (tracing) {
6287 		argsClobbered = TRUE;
6288 		code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE);
6289 	}
6290 
6291 	/*
6292 	 * Optimize the common case of the first bblock making a call with the same
6293 	 * arguments as the method. This works because the arguments are still in their
6294 	 * original argument registers.
6295 	 */
6296 	if (!argsClobbered) {
6297 		MonoBasicBlock *first_bb = cfg->bb_entry;
6298 		MonoInst *next;
6299 		int filter = FILTER_IL_SEQ_POINT;
6300 
6301 		next = mono_bb_first_inst (first_bb, filter);
6302 		if (!next && first_bb->next_bb) {
6303 			first_bb = first_bb->next_bb;
6304 			next = mono_bb_first_inst (first_bb, filter);
6305 		}
6306 
6307 		if (first_bb->in_count > 1)
6308 			next = NULL;
6309 
6310 		for (i = 0; next && i < sig->param_count + sig->hasthis; ++i) {
6311 			ArgInfo *ainfo = cinfo->args + i;
6312 			gboolean match = FALSE;
6313 
6314 			inst = cfg->args [i];
6315 			if (inst->opcode != OP_REGVAR) {
6316 				switch (ainfo->regtype) {
6317 				case RegTypeGeneral: {
6318 					if (((next->opcode == OP_LOAD_MEMBASE) ||
6319 					     (next->opcode == OP_LOADI4_MEMBASE)) &&
6320 					     next->inst_basereg == inst->inst_basereg &&
6321 					     next->inst_offset == inst->inst_offset) {
6322 						if (next->dreg == ainfo->reg) {
6323 							NULLIFY_INS (next);
6324 							match = TRUE;
6325 						} else {
6326 							next->opcode = OP_MOVE;
6327 							next->sreg1 = ainfo->reg;
6328 							/* Only continue if the instruction doesn't change argument regs */
6329 							if (next->dreg == ainfo->reg)
6330 								match = TRUE;
6331 						}
6332 					}
6333 					break;
6334 				}
6335 				default:
6336 					break;
6337 				}
6338 			} else {
6339 				/* Argument allocated to (non-volatile) register */
6340 				switch (ainfo->regtype) {
6341 				case RegTypeGeneral:
6342 					if (next->opcode == OP_MOVE &&
6343 					    next->sreg1 == inst->dreg &&
6344 					    next->dreg == ainfo->reg) {
6345 						NULLIFY_INS (next);
6346 						match = TRUE;
6347 					}
6348 					break;
6349 				default:
6350 					break;
6351 				}
6352 			}
6353 
6354 			if (match) {
6355 				next = mono_inst_next (next, filter);
6356 				if (!next)
6357 					break;
6358 			}
6359 		}
6360 	}
6361 
6362 	cfg->code_len = code - cfg->native_code;
6363 	g_assert (cfg->code_len < cfg->code_size);
6364 
6365 	return code;
6366 }
6367 
6368 /*========================= End of Function ========================*/
6369 
6370 /*------------------------------------------------------------------*/
6371 /*                                                                  */
6372 /* Name		- mono_arch_emit_epilog                             */
6373 /*                                                                  */
6374 /* Function	- Emit the instructions for a function epilog.      */
6375 /*		                               			    */
6376 /*------------------------------------------------------------------*/
6377 
6378 void
mono_arch_emit_epilog(MonoCompile * cfg)6379 mono_arch_emit_epilog (MonoCompile *cfg)
6380 {
6381 	MonoMethod *method = cfg->method;
6382 	int tracing = 0;
6383 	guint8 *code;
6384 	int max_epilog_size = 96;
6385 
6386 	if (cfg->method->save_lmf)
6387 		max_epilog_size += 128;
6388 
6389 	if (mono_jit_trace_calls != NULL)
6390 		max_epilog_size += 128;
6391 
6392 	while ((cfg->code_len + max_epilog_size) > (cfg->code_size - 16)) {
6393 		cfg->code_size  *= 2;
6394 		cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6395 		cfg->stat_code_reallocs++;
6396 	}
6397 
6398 	code = cfg->native_code + cfg->code_len;
6399 
6400 	if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) {
6401 		code = mono_arch_instrument_epilog (cfg, leave_method, code, TRUE);
6402 		tracing = 1;
6403 	}
6404 
6405 	if (method->save_lmf)
6406 		restoreLMF(code, cfg->frame_reg, cfg->stack_usage);
6407 
6408 	if (cfg->flags & MONO_CFG_HAS_ALLOCA) {
6409 		s390_lg  (code, STK_BASE, 0, STK_BASE, 0);
6410 	} else
6411 		code = backUpStackPtr(cfg, code);
6412 
6413 	s390_lmg (code, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
6414 	s390_br  (code, s390_r14);
6415 
6416 	cfg->code_len = code - cfg->native_code;
6417 
6418 	g_assert (cfg->code_len < cfg->code_size);
6419 
6420 }
6421 
6422 /*========================= End of Function ========================*/
6423 
6424 /*------------------------------------------------------------------*/
6425 /*                                                                  */
6426 /* Name		- mono_arch_emit_exceptions                         */
6427 /*                                                                  */
6428 /* Function	- Emit the blocks to handle exception conditions.   */
6429 /*		                               			    */
6430 /*------------------------------------------------------------------*/
6431 
6432 void
mono_arch_emit_exceptions(MonoCompile * cfg)6433 mono_arch_emit_exceptions (MonoCompile *cfg)
6434 {
6435 	MonoJumpInfo 	*patch_info;
6436 	guint8		*code;
6437 	int		nThrows = 0,
6438 			exc_count = 0,
6439 			iExc;
6440 	guint32		code_size;
6441 	MonoClass	*exc_classes [MAX_EXC];
6442 	guint8		*exc_throw_start [MAX_EXC];
6443 
6444 	for (patch_info = cfg->patch_info;
6445 	     patch_info;
6446 	     patch_info = patch_info->next) {
6447 		if (patch_info->type == MONO_PATCH_INFO_EXC)
6448 			exc_count++;
6449 	}
6450 
6451 	code_size = exc_count * 48;
6452 
6453 	while ((cfg->code_len + code_size) > (cfg->code_size - 16)) {
6454 		cfg->code_size  *= 2;
6455 		cfg->native_code = g_realloc (cfg->native_code, cfg->code_size);
6456 		cfg->stat_code_reallocs++;
6457 	}
6458 
6459 	code = cfg->native_code + cfg->code_len;
6460 
6461 	/*---------------------------------------------------------------------*/
6462 	/* Add code to raise exceptions 				       */
6463 	/*---------------------------------------------------------------------*/
6464 	for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
6465 		switch (patch_info->type) {
6466 		case MONO_PATCH_INFO_EXC: {
6467 			guint8 *ip = patch_info->ip.i + cfg->native_code;
6468 			MonoClass *exc_class;
6469 			guint64 throw_ip;
6470 
6471 			/*-----------------------------------------------------*/
6472 			/* Patch the branch in epilog to come here	       */
6473 			/*-----------------------------------------------------*/
6474 			s390_patch_rel (ip + 2, (guint64) S390_RELATIVE(code,ip));
6475 
6476 			exc_class = mono_class_load_from_name (mono_defaults.corlib,
6477 							  "System",
6478 							  patch_info->data.name);
6479 			throw_ip = patch_info->ip.i;
6480 
6481 			for (iExc = 0; iExc < nThrows; ++iExc)
6482 				if (exc_classes [iExc] == exc_class)
6483 					break;
6484 
6485 			if (iExc < nThrows) {
6486 				s390_jcl (code, S390_CC_UN,
6487 					  (guint64) exc_throw_start [iExc]);
6488 				patch_info->type = MONO_PATCH_INFO_NONE;
6489 			} else {
6490 
6491 				if (nThrows < MAX_EXC) {
6492 					exc_classes [nThrows]     = exc_class;
6493 					exc_throw_start [nThrows] = code;
6494 				}
6495 
6496 				/*---------------------------------------------*/
6497 				/* Patch the parameter passed to the handler   */
6498 				/*---------------------------------------------*/
6499 				S390_SET  (code, s390_r2, exc_class->type_token);
6500 				/*---------------------------------------------*/
6501 				/* Load return address & parameter register    */
6502 				/*---------------------------------------------*/
6503 				s390_larl (code, s390_r14, (guint64)S390_RELATIVE((patch_info->ip.i +
6504 							   cfg->native_code + 8), code));
6505 				/*---------------------------------------------*/
6506 				/* Reuse the current patch to set the jump     */
6507 				/*---------------------------------------------*/
6508 				patch_info->type      = MONO_PATCH_INFO_INTERNAL_METHOD;
6509 				patch_info->data.name = "mono_arch_throw_corlib_exception";
6510 				patch_info->ip.i      = code - cfg->native_code;
6511 				S390_BR_TEMPLATE (code, s390_r1);
6512 			}
6513 			break;
6514 		}
6515 		default:
6516 			/* do nothing */
6517 			break;
6518 		}
6519 	}
6520 
6521 	cfg->code_len = code - cfg->native_code;
6522 
6523 	g_assert (cfg->code_len < cfg->code_size);
6524 
6525 }
6526 
6527 /*========================= End of Function ========================*/
6528 
6529 /*------------------------------------------------------------------*/
6530 /*                                                                  */
6531 /* Name		- mono_arch_finish_init                             */
6532 /*                                                                  */
6533 /* Function	- Setup the JIT's Thread Level Specific Data.       */
6534 /*		                               			    */
6535 /*------------------------------------------------------------------*/
6536 
6537 void
mono_arch_finish_init(void)6538 mono_arch_finish_init (void)
6539 {
6540 }
6541 
6542 /*========================= End of Function ========================*/
6543 
6544 /*------------------------------------------------------------------*/
6545 /*                                                                  */
6546 /* Name		- mono_arch_free_jit_tls_data                       */
6547 /*                                                                  */
6548 /* Function	- Free tls data.                                    */
6549 /*		                               			    */
6550 /*------------------------------------------------------------------*/
6551 
6552 void
mono_arch_free_jit_tls_data(MonoJitTlsData * tls)6553 mono_arch_free_jit_tls_data (MonoJitTlsData *tls)
6554 {
6555 }
6556 
6557 /*========================= End of Function ========================*/
6558 
6559 /*------------------------------------------------------------------*/
6560 /*                                                                  */
6561 /* Name		- mono_arch_emit_inst_for_method                    */
6562 /*                                                                  */
6563 /*------------------------------------------------------------------*/
6564 
6565 MonoInst*
mono_arch_emit_inst_for_method(MonoCompile * cfg,MonoMethod * cmethod,MonoMethodSignature * fsig,MonoInst ** args)6566 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
6567 {
6568 	return NULL;
6569 }
6570 
6571 /*========================= End of Function ========================*/
6572 
6573 /*------------------------------------------------------------------*/
6574 /*                                                                  */
6575 /* Name		- mono_arch_decompose_opts                          */
6576 /*                                                                  */
6577 /* Function	- Decompose opcode into a System z opcode.          */
6578 /*		                               			    */
6579 /*------------------------------------------------------------------*/
6580 
6581 void
mono_arch_decompose_opts(MonoCompile * cfg,MonoInst * ins)6582 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
6583 {
6584 	/*
6585 	 * Have to rename these to avoid being decomposed normally, since the normal
6586 	 * decomposition does not work on S390.
6587 	 */
6588 	switch (ins->opcode) {
6589 	case OP_ISUB_OVF:
6590 		ins->opcode = OP_S390_ISUB_OVF;
6591 		break;
6592 	case OP_ISUB_OVF_UN:
6593 		ins->opcode = OP_S390_ISUB_OVF_UN;
6594 		break;
6595 	case OP_IADD_OVF:
6596 		ins->opcode = OP_S390_IADD_OVF;
6597 		break;
6598 	case OP_IADD_OVF_UN:
6599 		ins->opcode = OP_S390_IADD_OVF_UN;
6600 		break;
6601 	case OP_LADD_OVF:
6602 		ins->opcode = OP_S390_LADD_OVF;
6603 		break;
6604 	case OP_LADD_OVF_UN:
6605 		ins->opcode = OP_S390_LADD_OVF_UN;
6606 		break;
6607 	case OP_LSUB_OVF:
6608 		ins->opcode = OP_S390_LSUB_OVF;
6609 		break;
6610 	case OP_LSUB_OVF_UN:
6611 		ins->opcode = OP_S390_LSUB_OVF_UN;
6612 		break;
6613 	default:
6614 		break;
6615 	}
6616 }
6617 
6618 /*========================= End of Function ========================*/
6619 
6620 /*------------------------------------------------------------------*/
6621 /*                                                                  */
6622 /* Name		- mono_arch_regalloc_cost                           */
6623 /*                                                                  */
6624 /* Function	- Determine the cost, in the number of memory       */
6625 /*		  references, of the action of allocating the var-  */
6626 /*		  iable VMV into a register during global register  */
6627 /*		  allocation.					    */
6628 /*		                               			    */
6629 /* Returns	- Cost						    */
6630 /*                                                                  */
6631 /*------------------------------------------------------------------*/
6632 
6633 guint32
mono_arch_regalloc_cost(MonoCompile * cfg,MonoMethodVar * vmv)6634 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
6635 {
6636 	/* FIXME: */
6637 	return 2;
6638 }
6639 
6640 /*========================= End of Function ========================*/
6641 
6642 /*------------------------------------------------------------------*/
6643 /*                                                                  */
6644 /* Name		- mono_arch_flush_register_windows                  */
6645 /*                                                                  */
6646 /* Function	- 						    */
6647 /*		                               			    */
6648 /* Returns	-     						    */
6649 /*                                                                  */
6650 /*------------------------------------------------------------------*/
6651 
6652 void
mono_arch_flush_register_windows(void)6653 mono_arch_flush_register_windows (void)
6654 {
6655 }
6656 
6657 /*========================= End of Function ========================*/
6658 
6659 /*------------------------------------------------------------------*/
6660 /*                                                                  */
6661 /* Name		- mono_arch_is_inst_imm                             */
6662 /*                                                                  */
6663 /* Function	- Determine if operand qualifies as an immediate    */
6664 /*		  value. For s390 this is a value -32768-32768      */
6665 /*		                               			    */
6666 /* Returns	- True|False - is [not] immediate value.	    */
6667 /*                                                                  */
6668 /*------------------------------------------------------------------*/
6669 
6670 gboolean
mono_arch_is_inst_imm(gint64 imm)6671 mono_arch_is_inst_imm (gint64 imm)
6672 {
6673 	return s390_is_imm32 (imm);
6674 }
6675 
6676 /*========================= End of Function ========================*/
6677 
6678 /*------------------------------------------------------------------*/
6679 /*                                                                  */
6680 /* Name		- mono_arch_get_patch_offset                        */
6681 /*                                                                  */
6682 /* Function	- Dummy entry point until s390x supports aot.       */
6683 /*		                               			    */
6684 /* Returns	- Offset for patch.				    */
6685 /*                                                                  */
6686 /*------------------------------------------------------------------*/
6687 
6688 guint32
mono_arch_get_patch_offset(guint8 * code)6689 mono_arch_get_patch_offset (guint8 *code)
6690 {
6691 	return 0;
6692 }
6693 
6694 /*========================= End of Function ========================*/
6695 
6696 /*------------------------------------------------------------------*/
6697 /*                                                                  */
6698 /* Name		- mono_arch_context_get_int_reg.                    */
6699 /*                                                                  */
6700 /* Function	- 						    */
6701 /*		                               			    */
6702 /* Returns	- Return a register from the context.		    */
6703 /*                                                                  */
6704 /*------------------------------------------------------------------*/
6705 
6706 mgreg_t
mono_arch_context_get_int_reg(MonoContext * ctx,int reg)6707 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
6708 {
6709 	return ((mgreg_t) ctx->uc_mcontext.gregs[reg]);
6710 }
6711 
6712 /*========================= End of Function ========================*/
6713 
6714 /*------------------------------------------------------------------*/
6715 /*                                                                  */
6716 /* Name		- mono_arch_context_set_int_reg.                    */
6717 /*                                                                  */
6718 /* Function	- Set a value in a specified register.              */
6719 /*		                               			    */
6720 /*------------------------------------------------------------------*/
6721 
6722 void
mono_arch_context_set_int_reg(MonoContext * ctx,int reg,mgreg_t val)6723 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, mgreg_t val)
6724 {
6725 	ctx->uc_mcontext.gregs[reg] = val;
6726 }
6727 
6728 /*========================= End of Function ========================*/
6729 
6730 /*------------------------------------------------------------------*/
6731 /*                                                                  */
6732 /* Name		- mono_arch_get_this_arg_from_call.                 */
6733 /*                                                                  */
6734 /* Function	- 						    */
6735 /*		                               			    */
6736 /*------------------------------------------------------------------*/
6737 
6738 gpointer
mono_arch_get_this_arg_from_call(mgreg_t * regs,guint8 * code)6739 mono_arch_get_this_arg_from_call (mgreg_t *regs, guint8 *code)
6740 {
6741 	return (gpointer) regs [s390_r2];
6742 }
6743 
6744 /*========================= End of Function ========================*/
6745 
6746 /*------------------------------------------------------------------*/
6747 /*                                                                  */
6748 /* Name		- get_delegate_invoke_impl.                         */
6749 /*                                                                  */
6750 /* Function	- 						    */
6751 /*		                               			    */
6752 /*------------------------------------------------------------------*/
6753 
6754 static gpointer
get_delegate_invoke_impl(MonoTrampInfo ** info,gboolean has_target,guint32 param_count,gboolean aot)6755 get_delegate_invoke_impl (MonoTrampInfo **info, gboolean has_target, guint32 param_count, gboolean aot)
6756 {
6757 	guint8 *code, *start;
6758 
6759 	if (has_target) {
6760 		int size = 32;
6761 
6762 		start = code = mono_global_codeman_reserve (size);
6763 
6764 		/* Replace the this argument with the target */
6765 		s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6766 		s390_lg   (code, s390_r2, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, target));
6767 		s390_br   (code, s390_r1);
6768 		g_assert ((code - start) <= size);
6769 
6770 		mono_arch_flush_icache (start, size);
6771 	} else {
6772 		int size, i;
6773 
6774 		size = 32 + param_count * 8;
6775 		start = code = mono_global_codeman_reserve (size);
6776 
6777 		s390_lg   (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr));
6778 		/* slide down the arguments */
6779 		for (i = 0; i < param_count; ++i) {
6780 			s390_lgr (code, (s390_r2 + i), (s390_r2 + i + 1));
6781 		}
6782 		s390_br   (code, s390_r1);
6783 
6784 		g_assert ((code - start) <= size);
6785 
6786 		mono_arch_flush_icache (start, size);
6787 	}
6788 
6789 	if (has_target) {
6790 		*info = mono_tramp_info_create ("delegate_invoke_impl_has_target", start, code - start, NULL, NULL);
6791 	} else {
6792 		char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", param_count);
6793 		*info = mono_tramp_info_create (name, start, code - start, NULL, NULL);
6794 		g_free (name);
6795 	}
6796 
6797 	return start;
6798 }
6799 
6800 /*========================= End of Function ========================*/
6801 
6802 /*------------------------------------------------------------------*/
6803 /*                                                                  */
6804 /* Name		- mono_arch_get_delegate_invoke_impls.              */
6805 /*                                                                  */
6806 /* Function	- 						    */
6807 /*		                               			    */
6808 /*------------------------------------------------------------------*/
6809 
6810 GSList*
mono_arch_get_delegate_invoke_impls(void)6811 mono_arch_get_delegate_invoke_impls (void)
6812 {
6813 	GSList *res = NULL;
6814 	MonoTrampInfo *info;
6815 	int i;
6816 
6817 	get_delegate_invoke_impl (&info, TRUE, 0, TRUE);
6818 	res = g_slist_prepend (res, info);
6819 
6820 	for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) {
6821 		get_delegate_invoke_impl (&info, FALSE, i, TRUE);
6822 		res = g_slist_prepend (res, info);
6823 	}
6824 
6825 	return res;
6826 }
6827 
6828 /*========================= End of Function ========================*/
6829 
6830 /*------------------------------------------------------------------*/
6831 /*                                                                  */
6832 /* Name		- mono_arch_get_delegate_invoke_impl.               */
6833 /*                                                                  */
6834 /* Function	- 						    */
6835 /*		                               			    */
6836 /*------------------------------------------------------------------*/
6837 
6838 gpointer
mono_arch_get_delegate_invoke_impl(MonoMethodSignature * sig,gboolean has_target)6839 mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_target)
6840 {
6841 	guint8 *code, *start;
6842 
6843 	/* FIXME: Support more cases */
6844 	if (MONO_TYPE_ISSTRUCT (sig->ret))
6845 		return NULL;
6846 
6847 	if (has_target) {
6848 		static guint8* cached = NULL;
6849 
6850 		if (cached)
6851 			return cached;
6852 
6853 		if (mono_aot_only) {
6854 			start = mono_aot_get_trampoline ("delegate_invoke_impl_has_target");
6855 		} else {
6856 			MonoTrampInfo *info;
6857 			start = get_delegate_invoke_impl (&info, TRUE, 0, FALSE);
6858 			mono_tramp_info_register (info, NULL);
6859 		}
6860 
6861 		mono_memory_barrier ();
6862 
6863 		cached = start;
6864 	} else {
6865 		static guint8* cache [MAX_ARCH_DELEGATE_PARAMS + 1] = {NULL};
6866 		int i;
6867 
6868 		if (sig->param_count > MAX_ARCH_DELEGATE_PARAMS)
6869 			return NULL;
6870 		for (i = 0; i < sig->param_count; ++i)
6871 			if (!mono_is_regsize_var (sig->params [i]))
6872 				return NULL;
6873 
6874 
6875 		code = cache [sig->param_count];
6876 		if (code)
6877 			return code;
6878 
6879 		if (mono_aot_only) {
6880 			char *name = g_strdup_printf ("delegate_invoke_impl_target_%d", sig->param_count);
6881 			start = mono_aot_get_trampoline (name);
6882 			g_free (name);
6883 		} else {
6884 			MonoTrampInfo *info;
6885 			start = get_delegate_invoke_impl (&info, FALSE, sig->param_count, FALSE);
6886 			mono_tramp_info_register (info, NULL);
6887 		}
6888 
6889 		mono_memory_barrier ();
6890 
6891 		cache [sig->param_count] = start;
6892 	}
6893 	return start;
6894 }
6895 
6896 /*========================= End of Function ========================*/
6897 
6898 /*------------------------------------------------------------------*/
6899 /*                                                                  */
6900 /* Name		- mono_arch_get_delegate_virtual_invoke_impl.       */
6901 /*                                                                  */
6902 /* Function	- 						    */
6903 /*		                               			    */
6904 /*------------------------------------------------------------------*/
6905 
6906 gpointer
mono_arch_get_delegate_virtual_invoke_impl(MonoMethodSignature * sig,MonoMethod * method,int offset,gboolean load_imt_reg)6907 mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method,
6908 					    int offset, gboolean load_imt_reg)
6909 {
6910 	guint8 *code, *start;
6911 	int size = 40;
6912 
6913 	start = code = mono_global_codeman_reserve (size);
6914 
6915 	/*
6916 	* Replace the "this" argument with the target
6917 	*/
6918 	s390_lgr  (code, s390_r1, s390_r2);
6919 	s390_lg   (code, s390_r2, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, target));
6920 
6921 	/*
6922 	* Load the IMT register, if needed
6923 	*/
6924 	if (load_imt_reg) {
6925 		s390_lg  (code, MONO_ARCH_IMT_REG, 0, s390_r1, MONO_STRUCT_OFFSET(MonoDelegate, method));
6926 	}
6927 
6928 	/*
6929 	* Load the vTable
6930 	*/
6931 	s390_lg  (code, s390_r1, 0, s390_r2, MONO_STRUCT_OFFSET(MonoObject, vtable));
6932 	if (offset != 0) {
6933 		s390_agfi(code, s390_r1, offset);
6934 	}
6935 	s390_lg  (code, s390_r1, 0, s390_r1, 0);
6936 	s390_br  (code, s390_r1);
6937 
6938 	return(start);
6939 }
6940 
6941 /*========================= End of Function ========================*/
6942 
6943 /*------------------------------------------------------------------*/
6944 /*                                                                  */
6945 /* Name		- mono_arch_build_imt_trampoline.                       */
6946 /*                                                                  */
6947 /* Function	- 						    */
6948 /*		                               			    */
6949 /*------------------------------------------------------------------*/
6950 
6951 gpointer
mono_arch_build_imt_trampoline(MonoVTable * vtable,MonoDomain * domain,MonoIMTCheckItem ** imt_entries,int count,gpointer fail_tramp)6952 mono_arch_build_imt_trampoline (MonoVTable *vtable, MonoDomain *domain,
6953 								MonoIMTCheckItem **imt_entries, int count,
6954 								gpointer fail_tramp)
6955 {
6956 	int i;
6957 	int size = 0;
6958 	guchar *code, *start;
6959 	char trampName[64];
6960 
6961 	for (i = 0; i < count; ++i) {
6962 		MonoIMTCheckItem *item = imt_entries [i];
6963 		if (item->is_equals) {
6964 			if (item->check_target_idx) {
6965 				if (!item->compare_done)
6966 					item->chunk_size += CMP_SIZE + JUMP_SIZE;
6967 				if (item->has_target_code)
6968 					item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE;
6969 				else
6970 					item->chunk_size += BR_SIZE + JUMP_SIZE + LOADCON_SIZE +
6971 							    LOAD_SIZE;
6972 			} else {
6973 				if (fail_tramp) {
6974 					item->chunk_size += CMP_SIZE + 2 * BR_SIZE + JUMP_SIZE +
6975 							    2 * LOADCON_SIZE;
6976 					if (!item->has_target_code)
6977 						item->chunk_size += LOAD_SIZE;
6978 				} else {
6979 					item->chunk_size += LOADCON_SIZE + LOAD_SIZE + BR_SIZE;
6980 #if ENABLE_WRONG_METHOD_CHECK
6981 					item->chunk_size += CMP_SIZE + JUMP_SIZE;
6982 #endif
6983 				}
6984 			}
6985 		} else {
6986 			item->chunk_size += CMP_SIZE + JUMP_SIZE;
6987 			imt_entries [item->check_target_idx]->compare_done = TRUE;
6988 		}
6989 		size += item->chunk_size;
6990 	}
6991 
6992 	if (fail_tramp)
6993 		code = mono_method_alloc_generic_virtual_trampoline (domain, size);
6994 	else
6995 		code = mono_domain_code_reserve (domain, size);
6996 
6997 	start = code;
6998 
6999 	for (i = 0; i < count; ++i) {
7000 		MonoIMTCheckItem *item = imt_entries [i];
7001 		item->code_target = (guint8 *) code;
7002 		if (item->is_equals) {
7003 			if (item->check_target_idx) {
7004 				if (!item->compare_done) {
7005 					S390_SET  (code, s390_r0, item->key);
7006 					s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
7007 				}
7008 				item->jmp_code = (guint8*) code;
7009 				s390_jcl (code, S390_CC_NE, 0);
7010 
7011 				if (item->has_target_code) {
7012 					S390_SET (code, s390_r1, item->value.target_code);
7013 				} else {
7014 					S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7015 					s390_lg	 (code, s390_r1, 0, s390_r1, 0);
7016 				}
7017 				s390_br	  (code, s390_r1);
7018 			} else {
7019 				if (fail_tramp) {
7020 					gint64  target;
7021 
7022 					S390_SET  (code, s390_r0, item->key);
7023 					s390_cgr  (code, s390_r0, MONO_ARCH_IMT_REG);
7024 					item->jmp_code = (guint8*) code;
7025 					s390_jcl  (code, S390_CC_NE, 0);
7026 					if (item->has_target_code) {
7027 						S390_SET (code, s390_r1, item->value.target_code);
7028 					} else {
7029 						g_assert (vtable);
7030 						S390_SET  (code, s390_r1,
7031 							   (&(vtable->vtable [item->value.vtable_slot])));
7032 						s390_lg	  (code, s390_r1, 0, s390_r1, 0);
7033 					}
7034 					s390_br	  (code, s390_r1);
7035 					target = (gint64) S390_RELATIVE(code, item->jmp_code);
7036 					s390_patch_rel(item->jmp_code+2, target);
7037 					S390_SET  (code, s390_r1, fail_tramp);
7038 					s390_br	  (code, s390_r1);
7039 					item->jmp_code = NULL;
7040 				} else {
7041 				/* enable the commented code to assert on wrong method */
7042 #if ENABLE_WRONG_METHOD_CHECK
7043 					g_assert_not_reached ();
7044 #endif
7045 					S390_SET (code, s390_r1, (&(vtable->vtable [item->value.vtable_slot])));
7046 					s390_lg	  (code, s390_r1, 0, s390_r1, 0);
7047 					s390_br	  (code, s390_r1);
7048 				}
7049 			}
7050 		} else {
7051 			S390_SET  (code, s390_r0, item->key);
7052 			s390_cgr  (code, MONO_ARCH_IMT_REG, s390_r0);
7053 			item->jmp_code = (guint8 *) code;
7054 			s390_jcl  (code, S390_CC_GE, 0);
7055 		}
7056 	}
7057 	/*
7058 	 * patch the branches to get to the target items
7059 	 */
7060 	for (i = 0; i < count; ++i) {
7061 		MonoIMTCheckItem *item = imt_entries [i];
7062 		if (item->jmp_code) {
7063 			if (item->check_target_idx) {
7064 				gint64 offset;
7065 				offset = (gint64) S390_RELATIVE(imt_entries [item->check_target_idx]->code_target,
7066 						       item->jmp_code);
7067 				s390_patch_rel ((guchar *) item->jmp_code + 2, (guint64) offset);
7068 			}
7069 		}
7070 	}
7071 
7072 	mono_arch_flush_icache ((guint8*)start, (code - start));
7073 
7074 	if (!fail_tramp)
7075 		UnlockedAdd (&mono_stats.imt_trampolines_size, code - start);
7076 
7077 	g_assert (code - start <= size);
7078 
7079 	snprintf(trampName, sizeof(trampName), "%d_imt_trampoline", domain->domain_id);
7080 	mono_tramp_info_register (mono_tramp_info_create (trampName, start, code - start, NULL, NULL), domain);
7081 
7082 	return (start);
7083 }
7084 
7085 /*========================= End of Function ========================*/
7086 
7087 /*------------------------------------------------------------------*/
7088 /*                                                                  */
7089 /* Name		- mono_arch_find_imt_method.                        */
7090 /*                                                                  */
7091 /* Function	- Get the method address from MONO_ARCH_IMT_REG     */
7092 /*		  found in the save area.      			    */
7093 /*		                               			    */
7094 /*------------------------------------------------------------------*/
7095 
7096 MonoMethod*
mono_arch_find_imt_method(mgreg_t * regs,guint8 * code)7097 mono_arch_find_imt_method (mgreg_t *regs, guint8 *code)
7098 {
7099 	return ((MonoMethod *) regs [MONO_ARCH_IMT_REG]);
7100 }
7101 
7102 /*========================= End of Function ========================*/
7103 
7104 /*------------------------------------------------------------------*/
7105 /*                                                                  */
7106 /* Name		- mono_arch_find_static_call_vtable                 */
7107 /*                                                                  */
7108 /* Function	- Find the static call vtable.                      */
7109 /*		                               			    */
7110 /*------------------------------------------------------------------*/
7111 
7112 MonoVTable*
mono_arch_find_static_call_vtable(mgreg_t * regs,guint8 * code)7113 mono_arch_find_static_call_vtable (mgreg_t *regs, guint8 *code)
7114 {
7115 	mgreg_t *r = (mgreg_t*)regs;
7116 
7117 	return (MonoVTable*)(gsize) r [MONO_ARCH_RGCTX_REG];
7118 }
7119 
7120 /*========================= End of Function ========================*/
7121 
7122 /*------------------------------------------------------------------*/
7123 /*                                                                  */
7124 /* Name		- mono_arch_get_cie_program                         */
7125 /*                                                                  */
7126 /* Function	- Find the static call vtable.                      */
7127 /*		                               			    */
7128 /*------------------------------------------------------------------*/
7129 
7130 GSList*
mono_arch_get_cie_program(void)7131 mono_arch_get_cie_program (void)
7132 {
7133 	GSList *l = NULL;
7134 
7135 	mono_add_unwind_op_def_cfa (l, 0, 0, STK_BASE, 0);
7136 
7137 	return(l);
7138 }
7139 
7140 /*========================= End of Function ========================*/
7141 
7142 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
7143 
7144 /*------------------------------------------------------------------*/
7145 /*                                                                  */
7146 /* Name		- mono_arch_set_breakpoint.                         */
7147 /*                                                                  */
7148 /* Function	- Set a breakpoint at the native code corresponding */
7149 /*		  to JI at NATIVE_OFFSET.  The location should 	    */
7150 /*		  contain code emitted by OP_SEQ_POINT.		    */
7151 /*		                               			    */
7152 /*------------------------------------------------------------------*/
7153 
7154 void
mono_arch_set_breakpoint(MonoJitInfo * ji,guint8 * ip)7155 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
7156 {
7157 	guint8 *code = ip;
7158 
7159 	breakpointCode.pTrigger = bp_trigger_page;
7160 	memcpy(code, (void *) &breakpointCode, BREAKPOINT_SIZE);
7161 	code += BREAKPOINT_SIZE;
7162 }
7163 
7164 /*========================= End of Function ========================*/
7165 
7166 /*------------------------------------------------------------------*/
7167 /*                                                                  */
7168 /* Name		- mono_arch_clear_breakpoint.                       */
7169 /*                                                                  */
7170 /* Function	- Clear the breakpoint at IP.			    */
7171 /*		                               			    */
7172 /*------------------------------------------------------------------*/
7173 
7174 void
mono_arch_clear_breakpoint(MonoJitInfo * ji,guint8 * ip)7175 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
7176 {
7177 	guint8 *code = ip;
7178 	int i;
7179 
7180 	for (i = 0; i < (BREAKPOINT_SIZE / S390X_NOP_SIZE); i++)
7181 		s390_nop(code);
7182 }
7183 
7184 /*========================= End of Function ========================*/
7185 
7186 /*------------------------------------------------------------------*/
7187 /*                                                                  */
7188 /* Name		- mono_arch_is_breakpoint_event.                    */
7189 /*                                                                  */
7190 /* Function	- 						    */
7191 /*		                               			    */
7192 /*------------------------------------------------------------------*/
7193 
7194 gboolean
mono_arch_is_breakpoint_event(void * info,void * sigctx)7195 mono_arch_is_breakpoint_event (void *info, void *sigctx)
7196 {
7197 	siginfo_t* sinfo = (siginfo_t*) info;
7198 
7199 	/*
7200 	 * Sometimes the address is off by 4
7201 	 */
7202 	if (sinfo->si_addr >= bp_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)bp_trigger_page + 128)
7203 		return TRUE;
7204 	else
7205 		return FALSE;
7206 }
7207 
7208 /*========================= End of Function ========================*/
7209 
7210 /*------------------------------------------------------------------*/
7211 /*                                                                  */
7212 /* Name		- mono_arch_skip_breakpoint.                        */
7213 /*                                                                  */
7214 /* Function	- Modify the CTX so the IP is placed after the 	    */
7215 /*                breakpoint instruction, so when we resume, the    */
7216 /*		  instruction is not executed again.		    */
7217 /*		                               			    */
7218 /*------------------------------------------------------------------*/
7219 
7220 void
mono_arch_skip_breakpoint(MonoContext * ctx,MonoJitInfo * ji)7221 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
7222 {
7223 	MONO_CONTEXT_SET_IP (ctx, ((guint8*)MONO_CONTEXT_GET_IP (ctx) + sizeof(RXY_Format)));
7224 }
7225 
7226 /*========================= End of Function ========================*/
7227 
7228 /*------------------------------------------------------------------*/
7229 /*                                                                  */
7230 /* Name		- mono_arch_start_single_stepping.                  */
7231 /*                                                                  */
7232 /* Function	- Start single stepping.			    */
7233 /*		                               			    */
7234 /*------------------------------------------------------------------*/
7235 
7236 void
mono_arch_start_single_stepping(void)7237 mono_arch_start_single_stepping (void)
7238 {
7239 	mono_mprotect (ss_trigger_page, mono_pagesize (), 0);
7240 }
7241 
7242 /*========================= End of Function ========================*/
7243 
7244 /*------------------------------------------------------------------*/
7245 /*                                                                  */
7246 /* Name		- mono_arch_stop_single_stepping.                   */
7247 /*                                                                  */
7248 /* Function	- Stop single stepping.			   	    */
7249 /*		                               			    */
7250 /*------------------------------------------------------------------*/
7251 
7252 void
mono_arch_stop_single_stepping(void)7253 mono_arch_stop_single_stepping (void)
7254 {
7255 	mono_mprotect (ss_trigger_page, mono_pagesize (), MONO_MMAP_READ);
7256 }
7257 
7258 /*========================= End of Function ========================*/
7259 
7260 /*------------------------------------------------------------------*/
7261 /*                                                                  */
7262 /* Name		- mono_arch_is_single_step_event.                   */
7263 /*                                                                  */
7264 /* Function	- Return whether the machine state in sigctx cor-   */
7265 /*		  responds to a single step event.		    */
7266 /*		                               			    */
7267 /*------------------------------------------------------------------*/
7268 
7269 gboolean
mono_arch_is_single_step_event(void * info,void * sigctx)7270 mono_arch_is_single_step_event (void *info, void *sigctx)
7271 {
7272 	siginfo_t* sinfo = (siginfo_t*) info;
7273 
7274 	/*
7275 	 * Sometimes the address is off by 4
7276 	 */
7277 	if (sinfo->si_addr >= ss_trigger_page && (guint8*)sinfo->si_addr <= (guint8*)ss_trigger_page + 128)
7278 		return TRUE;
7279 	else
7280 		return FALSE;
7281 }
7282 
7283 /*========================= End of Function ========================*/
7284 
7285 /*------------------------------------------------------------------*/
7286 /*                                                                  */
7287 /* Name		- mono_arch_skip_single_step.                       */
7288 /*                                                                  */
7289 /* Function	- Modify the ctx so the IP is placed after the      */
7290 /*		  single step trigger instruction, so that the 	    */
7291 /*		  instruction is not executed again.		    */
7292 /*		                               			    */
7293 /*------------------------------------------------------------------*/
7294 
7295 void
mono_arch_skip_single_step(MonoContext * ctx)7296 mono_arch_skip_single_step (MonoContext *ctx)
7297 {
7298 	MONO_CONTEXT_SET_IP (ctx, (guint8*)MONO_CONTEXT_GET_IP (ctx) + BREAKPOINT_SIZE);
7299 }
7300 
7301 /*========================= End of Function ========================*/
7302 
7303 /*------------------------------------------------------------------*/
7304 /*                                                                  */
7305 /* Name		- mono_arch_create_seq_point_info.                  */
7306 /*                                                                  */
7307 /* Function	- Return a pointer to a data struction which is     */
7308 /*		  used by the sequence point implementation in      */
7309 /*		  AOTed code.                       	 	    */
7310 /*		                               			    */
7311 /*------------------------------------------------------------------*/
7312 
7313 gpointer
mono_arch_get_seq_point_info(MonoDomain * domain,guint8 * code)7314 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
7315 {
7316 	NOT_IMPLEMENTED;
7317 	return NULL;
7318 }
7319 
7320 /*========================= End of Function ========================*/
7321 
7322 #endif
7323 
7324 /*------------------------------------------------------------------*/
7325 /*                                                                  */
7326 /* Name	    - mono_arch_cpu_enumerate_simd_versions.                */
7327 /*                                                                  */
7328 /* Function - If this CPU supports vector operations then it        */
7329 /*            supports the equivalent of SSE1-4.                    */
7330 /*                                                                  */
7331 /*------------------------------------------------------------------*/
7332 
7333 guint32
mono_arch_cpu_enumerate_simd_versions(void)7334 mono_arch_cpu_enumerate_simd_versions (void)
7335 {
7336 	guint32 sseOpts = 0;
7337 
7338 	if (mono_hwcap_s390x_has_vec)
7339 		sseOpts = (SIMD_VERSION_SSE1  | SIMD_VERSION_SSE2 |
7340 		           SIMD_VERSION_SSE3  | SIMD_VERSION_SSSE3 |
7341 		           SIMD_VERSION_SSE41 | SIMD_VERSION_SSE42 |
7342 			   SIMD_VERSION_SSE4a);
7343 
7344 	return (sseOpts);
7345 }
7346 
7347 /*========================= End of Function ========================*/
7348 
7349 /*------------------------------------------------------------------*/
7350 /*                                                                  */
7351 /* Name	    - mono_arch_opcode_supported.                           */
7352 /*                                                                  */
7353 /* Function - Check if a given return code is supported.            */
7354 /*                                                                  */
7355 /*------------------------------------------------------------------*/
7356 
7357 gboolean
mono_arch_opcode_supported(int opcode)7358 mono_arch_opcode_supported (int opcode)
7359 {
7360 	switch (opcode) {
7361 	case OP_ATOMIC_ADD_I4:
7362 	case OP_ATOMIC_ADD_I8:
7363 	case OP_ATOMIC_EXCHANGE_I4:
7364 	case OP_ATOMIC_EXCHANGE_I8:
7365 		return TRUE;
7366 	default:
7367 		return FALSE;
7368 	}
7369 }
7370 
7371 /*========================= End of Function ========================*/
7372