4 # inssel-s390.brg: burg file for special s390 instructions
7 # Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
8 # Dietmar Maurer (dietmar@ximian.com)
9 # Paolo Molaro (lupus@ximian.com)
11 # (C) 2002 Ximian, Inc.
14 stmt: OP_START_HANDLER {
15 MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
16 tree->inst_left = spvar;
17 mono_bblock_add_inst (s->cbb, tree);
20 stmt: CEE_ENDFINALLY {
21 MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
22 tree->inst_left = spvar;
23 mono_bblock_add_inst (s->cbb, tree);
26 stmt: OP_ENDFILTER (reg) {
27 MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
28 tree->inst_left = spvar;
29 tree->sreg1 = state->left->reg1;
30 mono_bblock_add_inst (s->cbb, tree);
33 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
34 /* this should only happen for methods returning a long */
35 MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r2, state->right->reg1);
36 MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r3, state->right->reg2);
39 freg: OP_LCONV_TO_R8 (lreg) {
40 mono_bblock_add_inst (s->cbb, tree);
43 freg: OP_LCONV_TO_R4 (lreg) {
44 mono_bblock_add_inst (s->cbb, tree);
47 freg: CEE_CONV_R_UN (reg) {
48 mono_bblock_add_inst (s->cbb, tree);
51 reg: OP_LOCALLOC (OP_ICONST) {
52 /* microcoded in mini-s390.c */
53 tree->sreg1 = mono_regstate_next_int (s->rs);
54 tree->dreg = state->reg1;
55 MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
56 mono_bblock_add_inst (s->cbb, tree);
59 reg: OP_LOCALLOC (reg) {
60 tree->dreg = state->reg1;
61 tree->sreg1 = state->left->reg1;
62 mono_bblock_add_inst (s->cbb, tree);
65 stmt: OP_SETRET (reg) {
66 tree->opcode = OP_MOVE;
67 tree->sreg1 = state->left->reg1;
69 mono_bblock_add_inst (s->cbb, tree);
72 stmt: OP_SETRET (lreg) {
73 tree->opcode = OP_SETLRET;
74 tree->sreg1 = state->left->reg1;
75 tree->sreg2 = state->left->reg2;
76 mono_bblock_add_inst (s->cbb, tree);
79 stmt: OP_SETRET (freg) {
80 tree->opcode = OP_FMOVE;
81 tree->sreg1 = state->left->reg1;
83 mono_bblock_add_inst (s->cbb, tree);
86 stmt: OP_SETRET (OP_ICONST) {
87 tree->opcode = OP_ICONST;
88 tree->inst_c0 = state->left->tree->inst_c0;
90 mono_bblock_add_inst (s->cbb, tree);
93 stmt: OP_OUTARG (reg) {
95 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
98 tree->opcode = OP_SETREG;
99 tree->dreg = tree->unused;
100 tree->sreg1 = state->left->reg1;
101 mono_bblock_add_inst (s->cbb, tree);
104 stmt: OP_OUTARG (OP_REGVAR) {
105 if (tree->inst_imm) {
106 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->tree->dreg);
109 tree->opcode = OP_SETREG;
110 tree->dreg = tree->unused;
111 tree->sreg1 = state->left->tree->dreg;
112 mono_bblock_add_inst (s->cbb, tree);
115 stmt: OP_OUTARG (lreg) {
116 if (tree->inst_imm) {
117 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg2);
118 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm + 4, state->left->reg1);
121 MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
122 tree->opcode = OP_SETREG;
123 tree->dreg = tree->unused + 1;
124 tree->sreg1 = state->left->reg1;
125 mono_bblock_add_inst (s->cbb, tree);
128 stmt: OP_OUTARG (OP_ICONST) {
129 if (tree->inst_imm) {
130 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, s->frame_reg, tree->inst_imm, state->left->tree->inst_c0);
133 tree->opcode = OP_SETREGIMM;
134 tree->dreg = tree->unused;
135 tree->inst_c0 = state->left->tree->inst_c0;
136 mono_bblock_add_inst (s->cbb, tree);
139 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
140 if (tree->inst_imm) {
141 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->left->tree->dreg);
144 tree->opcode = OP_SETREG;
145 tree->sreg1 = state->left->left->tree->dreg;
146 tree->dreg = tree->unused;
147 mono_bblock_add_inst (s->cbb, tree);
150 stmt: OP_OUTARG (OP_LDADDR (OP_S390_LOADARG)) {
151 if (tree->inst_imm) {
152 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->left->tree->dreg);
155 tree->opcode = OP_LOAD_MEMBASE;
156 tree->sreg1 = state->left->left->tree->sreg1;
157 tree->dreg = tree->unused;
158 tree->inst_offset = state->left->left->tree->inst_offset;
159 mono_bblock_add_inst (s->cbb, tree);
162 stmt: OP_OUTARG (freg) {
163 if (tree->inst_imm) {
164 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
167 tree->opcode = OP_SETFREG;
168 tree->sreg1 = state->left->reg1;
169 tree->dreg = tree->unused;
170 mono_bblock_add_inst (s->cbb, tree);
173 stmt: OP_OUTARG_R4 (freg) {
174 if (tree->inst_imm) {
175 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
178 tree->opcode = OP_SETFREG;
179 tree->sreg1 = state->left->reg1;
180 tree->dreg = tree->unused;
181 mono_bblock_add_inst (s->cbb, tree);
184 stmt: OP_OUTARG_R8 (freg) {
185 if (tree->inst_imm) {
186 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
189 tree->opcode = OP_SETFREG;
190 tree->sreg1 = state->left->reg1;
191 tree->dreg = tree->unused;
192 mono_bblock_add_inst (s->cbb, tree);
195 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
196 MonoInst *vt = state->left->left->tree;
197 int start_reg = tree->sreg1;
198 int size = tree->unused;
199 int nregs = size / 4;
200 int soffset = vt->inst_offset;
205 if (start_reg != STK_BASE) {
206 mini_emit_memcpy (s, s->frame_reg, tree->sreg2,
207 vt->inst_basereg, soffset, size, 0);
208 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg,
209 s->frame_reg, tree->sreg2);
211 mini_emit_memcpy (s, s->frame_reg, tree->sreg2+sizeof(gpointer),
212 vt->inst_basereg, soffset, size, 0);
213 tmpr = mono_regstate_next_int (s->rs);
214 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
215 tree->sreg2+sizeof(gpointer));
216 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG,
217 s->frame_reg, tree->sreg2, tmpr);
220 if (start_reg != STK_BASE) {
221 for (i = 0; i < nregs; ++i) {
222 tmpr = mono_regstate_next_int (s->rs);
223 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg,
225 MONO_EMIT_NEW_UNALU (s, OP_SETREG, start_reg + i, tmpr);
226 soffset += sizeof (gpointer);
229 mini_emit_memcpy (s, s->frame_reg, tree->inst_imm,
230 vt->inst_basereg, soffset, size, 0);
235 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGPTR)) {
236 MonoInst *vt = state->left->left->tree;
237 int start_reg = tree->sreg1;
238 int size = tree->unused;
239 int nregs = size / 4;
240 int soffset = vt->inst_offset;
245 mini_emit_memcpy (s, s->frame_reg, tree->inst_imm,
246 vt->inst_basereg, soffset, size, 0);
247 if (start_reg != STK_BASE) {
248 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg,
249 s->frame_reg, tree->sreg2);
252 if (start_reg != STK_BASE) {
253 for (i = 0; i < nregs; ++i) {
254 tmpr = mono_regstate_next_int (s->rs);
255 MONO_EMIT_NEW_LOAD_MEMBASE (s, start_reg + i,
256 vt->inst_basereg, soffset);
257 soffset += sizeof (gpointer);
260 tmpr = mono_regstate_next_int (s->rs);
261 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
262 tree->inst_imm+sizeof(gpointer));
263 mini_emit_memcpy (s, s->frame_reg,
264 tree->inst_imm+sizeof(gpointer),
265 vt->inst_basereg, soffset, size, 0);
266 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG,
267 s->frame_reg, tree->inst_imm,
273 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_REGOFFSET)) {
274 MonoInst *vt = state->left->left->tree;
275 int start_reg = tree->sreg1;
276 int size = tree->unused;
277 int nregs = size / 4;
278 int soffset = vt->inst_offset;
283 mini_emit_memcpy (s, s->frame_reg, tree->inst_imm,
284 vt->inst_basereg, soffset, size, 0);
285 if (start_reg != STK_BASE) {
286 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg,
287 s->frame_reg, tree->sreg2);
290 if (start_reg != STK_BASE) {
291 for (i = 0; i < nregs; ++i) {
292 tmpr = mono_regstate_next_int (s->rs);
293 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr,
296 MONO_EMIT_NEW_LOAD_MEMBASE (s, start_reg + i,
298 MONO_EMIT_NEW_UNALU (s, OP_SETREG, start_reg + i, tmpr);
299 soffset += sizeof (gpointer);
302 tmpr = mono_regstate_next_int (s->rs);
303 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr,
306 mini_emit_memcpy (s, s->frame_reg,
307 tree->inst_imm+sizeof(gpointer),
308 tmpr, soffset, size, 0);
309 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG,
310 s->frame_reg, tree->inst_imm, tmpr);
314 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_LOADARG)) {
315 MonoInst *vt = state->left->left->tree;
316 int start_reg = tree->sreg1;
317 int size = -tree->unused;
318 int soffset = vt->inst_offset;
320 MONO_EMIT_NEW_LOAD_MEMBASE (s, start_reg, s->frame_reg, soffset);
321 mini_emit_memcpy (s, s->frame_reg, tree->sreg2,
322 start_reg, 0, size, 0);
323 if (start_reg != STK_BASE) {
324 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg,
325 s->frame_reg, tree->sreg2);
329 stmt: OP_OUTARG_VT (OP_ICONST) {
330 int start_reg = tree->sreg1;
331 int size = tree->unused;
332 int nregs = size / 4;
335 if (start_reg != STK_BASE) {
337 tree->opcode = OP_SETREGIMM;
338 tree->dreg = start_reg;
339 tree->inst_c0 = state->left->tree->inst_c0;
340 mono_bblock_add_inst (s->cbb, tree);
343 mini_emit_memcpy (s, s->frame_reg, tree->inst_c0, STK_BASE,
344 tree->inst_offset, size, 0);
348 stmt: OP_OUTARG_VT (reg) {
349 int start_reg = tree->sreg1;
350 int size = tree->unused;
351 int nregs = size / 4;
352 int soffset = tree->sreg2;
358 mini_emit_memcpy (s, s->frame_reg, soffset,
359 state->left->tree->sreg1,
360 tree->inst_imm, size, 0);
361 if (start_reg != STK_BASE) {
362 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg,
363 s->frame_reg, soffset);
366 if (start_reg != STK_BASE) {
367 for (i = 0; i < nregs; ++i) {
368 MONO_EMIT_NEW_LOAD_MEMBASE(s, start_reg + i,
370 state->left->tree->inst_offset);
371 soffset += sizeof(gpointer);
374 tmpr = mono_regstate_next_int (s->rs);
375 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
377 mini_emit_memcpy (s, s->frame_reg, soffset, tmpr,
378 state->left->tree->inst_offset, size, 0);
383 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
384 /* nothing to do: the value is already on the FP stack */
387 stmt: CEE_BNE_UN (fpcflags) {
388 tree->opcode = OP_FBNE_UN;
389 mono_bblock_add_inst (s->cbb, tree);
392 stmt: CEE_BEQ (fpcflags) {
393 tree->opcode = OP_FBEQ;
394 mono_bblock_add_inst (s->cbb, tree);
397 stmt: CEE_BLT (fpcflags) {
398 tree->opcode = OP_FBLT;
399 mono_bblock_add_inst (s->cbb, tree);
402 stmt: CEE_BLT_UN (fpcflags) {
403 tree->opcode = OP_FBLT_UN;
404 mono_bblock_add_inst (s->cbb, tree);
407 stmt: CEE_BGT (fpcflags) {
408 tree->opcode = OP_FBGT;
409 mono_bblock_add_inst (s->cbb, tree);
412 stmt: CEE_BGT_UN (fpcflags) {
413 tree->opcode = OP_FBGT_UN;
414 mono_bblock_add_inst (s->cbb, tree);
417 stmt: CEE_BGE (fpcflags) {
418 tree->opcode = OP_FBGE;
419 mono_bblock_add_inst (s->cbb, tree);
422 stmt: CEE_BGE_UN (fpcflags) {
423 tree->opcode = OP_FBGE_UN;
424 mono_bblock_add_inst (s->cbb, tree);
427 stmt: CEE_BLE (fpcflags) {
428 tree->opcode = OP_FBLE;
429 mono_bblock_add_inst (s->cbb, tree);
432 stmt: CEE_BLE_UN (fpcflags) {
433 tree->opcode = OP_FBLE_UN;
434 mono_bblock_add_inst (s->cbb, tree);
437 stmt: CEE_POP (freg) "0" {
441 freg: OP_LCONV_TO_R8 (lreg) {
442 /* nothing to do - emulated */
445 freg: OP_LCONV_TO_R4 (lreg) {
446 /* nothing to do - emulated */
449 freg: OP_LCONV_TO_R_UN (lreg) {
450 /* nothing to do - emulated */
453 freg: OP_FREM (freg, freg) {
454 /* nothing to do - emulated */
457 reg: OP_CEQ (OP_COMPARE (freg, freg)) {
458 MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
459 state->left->right->reg1);
462 reg: OP_CLT (OP_COMPARE (freg, freg)) {
463 MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
464 state->left->right->reg1);
467 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {
468 MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
469 state->left->right->reg1);
472 reg: OP_CGT (OP_COMPARE (freg, freg)) {
473 MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
474 state->left->right->reg1);
477 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {
478 MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
479 state->left->right->reg1);
482 base: OP_S390_STKARG "0" {
485 tmpr = mono_regstate_next_int (s->rs);
486 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
487 (s->stack_offset+state->tree->unused));
488 tree->inst_offset = state->tree->inst_offset;
489 tree->inst_basereg = tmpr;
492 base: OP_LDADDR (OP_S390_LOADARG) "0" {
495 tmpr = mono_regstate_next_int (s->rs);
496 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, s->frame_reg,
497 state->left->tree->inst_offset);
498 tree->inst_offset = 0;
499 tree->inst_basereg = tmpr;
502 base: OP_LDADDR (OP_S390_ARGPTR) "0" {
505 tmpr = mono_regstate_next_int (s->rs);
506 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
507 state->left->tree->inst_offset);
508 tree->inst_offset = 0;
509 tree->inst_basereg = tmpr;
512 base: OP_LDADDR (OP_S390_STKARG) "0" {
515 tmpr = mono_regstate_next_int (s->rs);
516 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
517 (s->stack_offset + state->left->tree->unused));
518 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, tmpr,
519 state->left->tree->inst_offset);
520 tree->inst_offset = 0;
521 tree->inst_basereg = tmpr;
524 reg: OP_LDADDR (OP_S390_LOADARG) "2" {
525 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg,
526 state->left->tree->inst_offset);
527 tree->inst_offset = 0;
528 tree->inst_basereg = state->reg1;
531 reg: OP_LDADDR (OP_S390_ARGPTR) "2" {
532 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg,
533 state->left->tree->inst_offset);
534 tree->inst_offset = 0;
535 tree->inst_basereg = state->reg1;
538 reg: OP_LDADDR (OP_S390_STKARG) "2" {
539 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg,
540 (s->stack_offset + state->left->tree->unused));
541 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1,
542 state->left->tree->inst_offset);
543 tree->inst_offset = 0;
544 tree->inst_basereg = state->reg1;
547 reg: CEE_LDOBJ (OP_S390_LOADARG) "1" {
550 tmpr = mono_regstate_next_int (s->rs);
551 MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, s->frame_reg,
552 state->left->tree->inst_offset);
555 reg: CEE_LDOBJ (OP_S390_ARGPTR) "1" {
556 MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, s->frame_reg,
557 state->left->tree->inst_offset);
560 reg: CEE_LDOBJ (OP_S390_STKARG) "1" {
561 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg,
562 (s->stack_offset + state->left->tree->unused));
563 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1,
564 state->left->tree->inst_offset);
565 tree->inst_offset = 0;
566 tree->dreg = state->reg1;
569 base: CEE_LDOBJ (OP_S390_ARGPTR) "0" {
572 tmpr = mono_regstate_next_int (s->rs);
573 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, s->frame_reg,
574 state->left->tree->inst_offset);
575 tree->inst_offset = 0;
579 base: CEE_LDOBJ (OP_S390_STKARG) "0" {
582 tmpr = mono_regstate_next_int (s->rs);
583 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg,
584 (s->stack_offset + state->left->tree->unused));
585 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, state->left->tree->inst_offset);
586 tree->inst_offset = 0;
587 tree->inst_basereg = tmpr;