Bring s390 JIT up to current level
[mono-project.git] / mono / mini / inssel-s390.brg
bloba62bcfa6f047fc9d908b0989a10b7c85a92e7eba
1 %%
4 # inssel-s390.brg: burg file for special s390 instructions
6 # Author:
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 lreg: OP_LADD_OVF (lreg, lreg) "0" {
34         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
37 lreg: OP_LADD_OVF_UN (lreg, lreg) "0" {
38         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
41 #reg: OP_LSUB_OVF (lreg, lreg) "0" {
42 #       /* SBB sets the condition code */
43 #       MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
44 #       MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2);
47 lreg: OP_LSUB_OVF (lreg, lreg) "0" {
48         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
51 lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" {
52         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
55 reg: CEE_ADD_OVF (reg, reg) "0" {
56         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
59 reg: CEE_ADD_OVF_UN (reg, reg) "0" {
60         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
63 reg: CEE_SUB_OVF (reg, reg) "0" {
64         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
67 reg: CEE_SUB_OVF_UN (reg, reg) "0" {
68         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
71 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
72         /*------------------------------------------------------*/
73         /* this should only happen for methods returning a long */
74         /* S/390 ABI uses r2/r3 for returning 64-bit integers   */
75         /*------------------------------------------------------*/
76         MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r2, state->right->reg1);
77         MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r3, state->right->reg2);
80 freg: OP_LCONV_TO_R8 (lreg) {
81         tree->dreg = state->reg1;
82         tree->sreg1 = state->left->reg1;
83         tree->sreg2 = state->left->reg2;
84         mono_bblock_add_inst (s->cbb, tree);
87 freg: OP_LCONV_TO_R4 (lreg) {
88         tree->dreg = state->reg1;
89         tree->sreg1 = state->left->reg1;
90         tree->sreg2 = state->left->reg2;
91         mono_bblock_add_inst (s->cbb, tree);
94 freg: CEE_CONV_R_UN (reg) {
95         tree->dreg = state->reg1;
96         tree->sreg1 = state->left->reg1;
97         mono_bblock_add_inst (s->cbb, tree);
100 freg: CEE_CONV_R_UN (reg) {
101         mono_bblock_add_inst (s->cbb, tree);
104 stmt: OP_MEMCPY (reg, reg) "0" {
105         int size = tree->unused;
106         if (size > 0) 
107                 MONO_EMIT_NEW_MOVE (s, state->left->reg1, 0, 
108                                     state->right->reg1, 0, size);
111 stmt: OP_MEMCPY (base, base) "0" {
112         int size = tree->unused;
113         if (size > 0)  
114                 MONO_EMIT_NEW_MOVE (s, state->left->tree->sreg1, 
115                                     state->left->tree->inst_offset, 
116                                     state->right->tree->sreg1,
117                                     state->right->tree->inst_offset,
118                                     size);
121 reg: OP_LOCALLOC (OP_ICONST) {
122         /* microcoded in mini-s390.c */
123         tree->sreg1 = mono_regstate_next_int (s->rs);
124         tree->dreg  = state->reg1;
125         MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
126         mono_bblock_add_inst (s->cbb, tree);
129 reg: OP_LOCALLOC (reg) {
130         tree->dreg = state->reg1;
131         tree->sreg1 = state->left->reg1;
132         mono_bblock_add_inst (s->cbb, tree);
135 stmt: OP_SETRET (reg) {
136         tree->opcode = OP_MOVE;
137         tree->sreg1 = state->left->reg1;
138         tree->dreg = s390_r2;
139         mono_bblock_add_inst (s->cbb, tree);
142 stmt: OP_SETRET (lreg) {
143         tree->opcode = OP_SETLRET;
144         tree->sreg1 = state->left->reg1;
145         tree->sreg2 = state->left->reg2;
146         mono_bblock_add_inst (s->cbb, tree);
149 stmt: OP_SETRET (freg) {
150         if (mono_method_signature (s->method)->ret->type == MONO_TYPE_R4) {
151                 tree->opcode = OP_S390_SETF4RET;
152                 tree->sreg1  = state->left->reg1;
153                 tree->dreg   = s390_f0;
154         } else {
155                 tree->opcode = OP_FMOVE;
156                 tree->sreg1  = state->left->reg1;
157                 tree->dreg   = s390_f0;
158         }
159         mono_bblock_add_inst (s->cbb, tree);
162 stmt: OP_SETRET (OP_ICONST) {
163         tree->opcode = OP_ICONST;
164         tree->inst_c0 = state->left->tree->inst_c0;
165         tree->dreg = s390_r2;
166         mono_bblock_add_inst (s->cbb, tree);
169 #lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" {
170 #       /*----------------------------------------------------------------------*/
171 #       /* SBB sets the condition code - CC 0 or 1 indicates Borrow == Overflow */
172 #       /*----------------------------------------------------------------------*/
173 #       MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
174 #       MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
175 #       MONO_EMIT_NEW_COND_EXC (s, NC, "OverflowException");
178 stmt: OP_OUTARG (reg) {
179         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
181         tree->opcode = OP_SETREG;
182         tree->dreg   = mono_regstate_next_int (s->rs);
183         tree->sreg1  = state->left->reg1;
184         mono_bblock_add_inst (s->cbb, tree);
186         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
189 stmt: OP_OUTARG_MEMBASE (reg) {
190         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
192         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
193                                      argParm->offset, state->left->reg1);
195         g_free(argParm);
198 stmt: OP_OUTARG (OP_REGVAR) {
199         MonoCallInst *call = (MonoCallInst*) tree->inst_right;
200         tree->opcode       = OP_SETREG;
201         tree->dreg         = mono_regstate_next_int (s->rs);
202         tree->sreg1        = state->left->tree->dreg;
203         mono_bblock_add_inst (s->cbb, tree);
205         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
208 stmt: OP_OUTARG_MEMBASE (OP_REGVAR) {
209         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
211         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
212                                      argParm->offset, state->left->tree->dreg);
214         g_free(argParm);
217 #stmt: OP_OUTARG (reg) {
218 #       if (tree->inst_imm) {
219 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg1);
220 #               return;
221 #       }
222 #       tree->opcode = OP_SETREG;
223 #       tree->dreg = tree->unused;
224 #       tree->sreg1 = state->left->reg1;
225 #       mono_bblock_add_inst (s->cbb, tree);
228 #stmt: OP_OUTARG (OP_REGVAR) {
229 #       if (tree->inst_imm) {
230 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->tree->dreg);
231 #               return;
232 #       }
233 #       tree->opcode = OP_SETREG;
234 #       tree->dreg = tree->unused;
235 #       tree->sreg1 = state->left->tree->dreg;
236 #       mono_bblock_add_inst (s->cbb, tree);
239 stmt: OP_OUTARG (lreg) {
240         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
241         int tdreg;
242         tdreg = mono_regstate_next_int (s->rs);
243         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
244         
245         mono_call_inst_add_outarg_reg (call, tdreg, tree->unused, FALSE);
247         tree->opcode = OP_SETREG;
248         tree->dreg = mono_regstate_next_int (s->rs);
249         tree->sreg1 = state->left->reg1;
250         mono_bblock_add_inst (s->cbb, tree);
251         
252         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused + 1, FALSE);
253 #       tree->dreg = tree->unused + 1;
256 stmt: OP_OUTARG_MEMBASE (lreg) {
257         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
258         
259         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
260                                      argParm->offset, state->left->reg2);
261         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
262                                      argParm->offset + 4, state->left->reg1);
263         g_free(argParm);
266 #stmt: OP_OUTARG (lreg) {
267 #       if (tree->inst_imm) {
268 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg2);
269 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm + 4, state->left->reg1);
270 #               return;
271 #       }
272 #       MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
273 #       tree->opcode = OP_SETREG;
274 #       tree->dreg = tree->unused + 1;
275 #       tree->sreg1 = state->left->reg1;
276 #       mono_bblock_add_inst (s->cbb, tree);
279 stmt: OP_OUTARG (OP_ICONST) {
280         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
281         tree->opcode       = OP_ICONST;
282         tree->dreg         = mono_regstate_next_int (s->rs);
283         tree->inst_c0      = state->left->tree->inst_c0;
284         mono_bblock_add_inst (s->cbb, tree);
286         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
289 stmt: OP_OUTARG_MEMBASE (OP_ICONST) {
290         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
292         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, 
293                                          argParm->offset, state->left->tree->inst_c0);
295         g_free (argParm);
298 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
299         MonoCallInst *call = (MonoCallInst*) tree->inst_right;
300         tree->opcode       = OP_SETREG;
301         tree->sreg1        = state->left->left->tree->dreg;
302         tree->dreg         = mono_regstate_next_int (s->rs);
303         mono_bblock_add_inst (s->cbb, tree);
305         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
308 stmt: OP_OUTARG_MEMBASE (CEE_LDIND_REF (OP_REGVAR)) {
309         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
311         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, 
312                                          argParm->offset, state->left->tree->inst_c0);
314         g_free(argParm);
317 #stmt: OP_OUTARG (OP_ICONST) {
318 #       if (tree->inst_imm) {
319 #               MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, tree->inst_imm, state->left->tree->inst_c0);
320 #               return;
321 #       }
322 #       tree->opcode = OP_SETREGIMM;
323 #       tree->dreg = tree->unused;
324 #       tree->inst_c0 = state->left->tree->inst_c0;
325 #       mono_bblock_add_inst (s->cbb, tree);
328 #stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
329 #       if (tree->inst_imm) {
330 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->left->tree->dreg);
331 #               return;
332 #       }
333 #       tree->opcode = OP_SETREG;
334 #       tree->sreg1 = state->left->left->tree->dreg;
335 #       tree->dreg = tree->unused;
336 #       mono_bblock_add_inst (s->cbb, tree);
339 stmt: OP_OUTARG (OP_LDADDR (OP_S390_LOADARG)) {
340         MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, tree->unused,
341                              state->left->left->tree->sreg1,
342                              state->left->left->tree->inst_offset);
345 stmt: OP_OUTARG_MEMBASE (OP_LDADDR (OP_S390_LOADARG)) {
346         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
348         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
349                                      argParm->offset, state->left->left->tree->dreg);
351         g_free(argParm);
354 #stmt: OP_OUTARG (OP_LDADDR (OP_S390_LOADARG)) {
355 #       if (tree->inst_imm) {
356 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->left->tree->dreg);
357 #               return;
358 #       }
359 #       MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, tree->unused,
360 #                            state->left->left->tree->sreg1,
361 #                            state->left->left->tree->inst_offset);
364 stmt: OP_OUTARG_R4 (freg) {
365         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
367         tree->opcode = OP_FCONV_TO_R4;
368         tree->dreg   = mono_regstate_next_float (s->rs);
369         tree->sreg1  = state->left->reg1;
370         mono_bblock_add_inst (s->cbb, tree);
372         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
375 stmt: OP_OUTARG_R8 (freg),
376 stmt: OP_OUTARG (freg) {
377         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
379         tree->opcode = OP_SETFREG;
380         tree->dreg   = mono_regstate_next_float (s->rs);
381         tree->sreg1  = state->left->reg1;
382         mono_bblock_add_inst (s->cbb, tree);
384         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
387 stmt: OP_OUTARG_MEMBASE (freg) {
388         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
389         
390         /*----------------------------------------------*/
391         /* The length stored in size tells us whether   */
392         /* we need to store a float or a double         */
393         /*----------------------------------------------*/
394         if (argParm->size == 4) {
395                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, 
396                                              STK_BASE, argParm->offset,
397                                              state->left->reg1);
398         } else {
399                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, 
400                                              STK_BASE, argParm->offset,
401                                              state->left->reg1);
402         }
403         g_free(argParm);
406 #stmt: OP_OUTARG_R4 (freg) {
407 #       if (tree->inst_imm) {
408 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg1);
409 #               return;
410 #       }
411 #       tree->opcode = OP_SETFREG;
412 #       tree->sreg1 = state->left->reg1;
413 #       tree->dreg = tree->unused;
414 #       mono_bblock_add_inst (s->cbb, tree);
417 #stmt: OP_OUTARG_R8 (freg) {
418 #       if (tree->inst_imm) {
419 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, STK_BASE, 
420 #                                            tree->inst_imm, state->left->reg1);
421 #               return;
422 #       }
423 #       tree->opcode = OP_SETFREG;
424 #       tree->sreg1 = state->left->reg1;
425 #       tree->dreg = tree->unused;
426 #       mono_bblock_add_inst (s->cbb, tree);
429 stmt: OP_OUTARG_R4 (CEE_LDOBJ (OP_REGOFFSET)),
430 stmt: OP_OUTARG_R8 (CEE_LDOBJ (OP_REGOFFSET)) {
431         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
433         tree->opcode = OP_SETFREG;
434         tree->dreg   = mono_regstate_next_float (s->rs);
435         tree->sreg1  = state->left->reg1;
436         mono_bblock_add_inst (s->cbb, tree);
438         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
441 #stmt: OP_OUTARG_R8 (CEE_LDOBJ (OP_REGOFFSET)) {
442 #       if (tree->inst_imm) {
443 #               MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, STK_BASE, 
444 #                                            tree->inst_imm, state->left->reg1);
445 #               return;
446 #       }
447 #       tree->opcode = OP_SETFREG;
448 #       tree->sreg1 = state->left->reg1;
449 #       tree->dreg = tree->unused;
450 #       mono_bblock_add_inst (s->cbb, tree);
453 freg: OP_FCONV_TO_R4 (CEE_LDOBJ (OP_REGOFFSET)) {
454         MonoInst *vt = state->left->left->tree;
456         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, state->reg1, vt->inst_basereg, 
457                                        vt->inst_offset);
458         MONO_EMIT_NEW_UNALU (s, OP_FCONV_TO_R4, state->reg1, state->reg1);
461 freg: OP_FCONV_TO_R8 (CEE_LDOBJ (OP_REGOFFSET)) {
462         tree->opcode = OP_SETFREG;
463         tree->sreg1 = state->left->reg1;
464         tree->dreg = tree->unused;
465         mono_bblock_add_inst (s->cbb, tree);
469 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
470         MonoCallInst *call       = (MonoCallInst*) tree->inst_right;
471         MonoInst *vt             = state->left->left->tree;
472         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
473         
474         int start_reg = tree->sreg1;
475         int size      = argParm->size;
476         int soffset   = vt->inst_offset;
477         int treg;
478         
479         if (size < 0) { 
480                 size = -size;
481                 treg = mono_regstate_next_int (s->rs);
482                 if (start_reg != STK_BASE) {
483                         MONO_EMIT_NEW_MOVE(s, STK_BASE, argParm->offPrm,
484                                            vt->inst_basereg, soffset, size);
485                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, 
486                                                  STK_BASE, argParm->offPrm);
487                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
488                 } else { 
489                         MONO_EMIT_NEW_MOVE(s, STK_BASE, argParm->offPrm+sizeof(gpointer),
490                                            vt->inst_basereg, soffset, size);
491                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, 
492                                                  argParm->offPrm+sizeof(gpointer));
493                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
494                                                      STK_BASE, argParm->offPrm, treg);
495                 }
496         } else {
497                 if (start_reg != STK_BASE) {
498                         MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset);
499                 } else {
500                         MONO_OUTPUT_VTS (s, size, STK_BASE, argParm->offset,
501                                          vt->inst_basereg, soffset);
502                 }       
503         }
504         g_free(argParm);
507 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGPTR)) {
508         MonoCallInst *call       = (MonoCallInst*) tree->inst_right;
509         MonoInst *vt             = state->left->left->tree;
510         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
511         
512         int start_reg = tree->sreg1;
513         int size      = argParm->size;
514         int soffset   = vt->inst_offset;
515         int treg;
517 //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_ARGPTR))\n");
518         if (size < 0) { 
519                 size = -size;
520                 treg = mono_regstate_next_int (s->rs);
521                 if (start_reg != STK_BASE) {
522                         MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offset,
523                                             vt->inst_basereg, soffset, size);
524                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
525                                                  STK_BASE, argParm->offPrm);
526                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
527                 } else {
528                         MONO_EMIT_NEW_MOVE (s, STK_BASE, 
529                                             argParm->offset+sizeof(gpointer),
530                                             vt->inst_basereg, soffset, size);
531                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE,
532                                                  argParm->offset+sizeof(gpointer));
533                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
534                                                      STK_BASE, argParm->offset, treg);
535                 }
536         } else {
537                 if (start_reg != STK_BASE) {
538                         MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset);
539                 } else {
540                         MONO_OUTPUT_VTS (s, size, STK_BASE, argParm->offset,
541                                          vt->inst_basereg, soffset);
542                 }       
543         }
544         g_free(argParm);
547 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_REGOFFSET)) "0" {
548         MonoCallInst *call       = (MonoCallInst*) tree->inst_right;
549         MonoInst *vt             = state->left->left->tree;
550         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
551         
552         int start_reg = tree->sreg1;
553         int size      = argParm->size;
554         int soffset   = vt->inst_offset;
555         int treg;
557 //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_REGOFFSET))\n");
558         if (size < 0) { 
559                 size = -size;
560                 treg = mono_regstate_next_int (s->rs);
561                 if (start_reg != STK_BASE) {
562 //                      MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
563 //                                               STK_BASE, soffset);
564                         MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm,
565                                             vt->inst_basereg, soffset, size);
566                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
567                                                  STK_BASE, argParm->offPrm);
568                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
569                 } else {
570                         MONO_EMIT_NEW_MOVE (s, STK_BASE, 
571                                             argParm->offPrm+sizeof(gpointer),
572                                             vt->inst_basereg, soffset, size);
573                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE,
574                                                  argParm->offPrm+sizeof(gpointer));
575                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
576                                                      STK_BASE, argParm->offPrm, treg);
577                 }
578         } else {
579                 if (start_reg != STK_BASE) {
580                         MONO_OUTPUT_VTR(s, size, start_reg, vt->inst_basereg, soffset);
581                 } else {
582                         MONO_OUTPUT_VTS(s, size, STK_BASE, argParm->offset,
583                                           vt->inst_basereg, soffset);
584                 }       
585         }
586         g_free(argParm);
589 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_LOADARG)) {
590         MonoCallInst *call       = (MonoCallInst*) tree->inst_right;
591         MonoInst *vt             = state->left->left->tree;
592         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
593         
594         int start_reg = tree->sreg1;
595         int size      = -argParm->size;
596         int soffset   = vt->inst_offset;
597         int treg;
599 //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_LOADARG))\n");
600         treg = mono_regstate_next_int (s->rs);
601         if (start_reg != STK_BASE) {
602                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, soffset);
603                 MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, treg, 0, size);
604                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
605                                          STK_BASE, argParm->offPrm);
606                 mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
607         } else {
608                 MONO_EMIT_NEW_MOVE (s, STK_BASE, 
609                                     argParm->offset+sizeof(gpointer),
610                                     vt->inst_basereg, soffset, size);
611                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE,
612                                          argParm->offset+sizeof(gpointer));
613                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
614                                              STK_BASE, argParm->offset, treg);
615         }
616         g_free(argParm);
619 stmt: OP_OUTARG_VT (OP_ICONST) {
620         MonoCallInst *call       = (MonoCallInst*) tree->inst_right;
621         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
622         int start_reg = tree->sreg1;
623         int size      = argParm->size;
624         int nregs     = size / 4;
626 //printf("OP_OUTARG_VT(OP_ICONST)\n");
627         if (start_reg != STK_BASE) {
628                 if (nregs) {
629                         tree->opcode  = OP_SETREGIMM;
630                         tree->dreg    = mono_regstate_next_int (s->rs);
631                         tree->inst_c0 = state->left->tree->inst_c0;
632                         mono_bblock_add_inst (s->cbb, tree);
633                         mono_call_inst_add_outarg_reg (call, tree->dreg, start_reg, FALSE);
634                 }
635         } else {
636                 MONO_OUTPUT_VTS (s, size, STK_BASE, tree->inst_c0, 
637                                  s->frame_reg, tree->inst_offset);
638         }
639         g_free(argParm);
642 stmt: OP_OUTARG_VT (reg) {
643         MonoCallInst *call       = (MonoCallInst*) tree->inst_right;
644         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
645         MonoInst *vt             = state->left->left->tree;
646         int start_reg = tree->sreg1;
647         int size      = argParm->size;
648         int soffset   = vt->inst_offset;
649         int treg;
651         if (size < 0) { 
652                 size = -size;
653                 treg = mono_regstate_next_int (s->rs);
654                 if (start_reg != STK_BASE) {
655                         MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, state->left->reg1,
656                                             0, size);
657                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
658                                                  STK_BASE, argParm->offPrm);
659                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
660                 } else {
661                         MONO_EMIT_NEW_MOVE (s, STK_BASE, soffset+size, state->left->reg1,
662                                             0, size);
663                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE,
664                                                  soffset+size);
665                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
666                                                      STK_BASE, argParm->offset, treg);
667                 }
668         } else {
669                 if (start_reg != STK_BASE) {
670                         MONO_OUTPUT_VTR (s, size, start_reg, STK_BASE, soffset);
671                 } else {
672                         MONO_OUTPUT_VTS (s, size, STK_BASE, soffset, treg,
673                                          state->left->tree->inst_offset);
674                         treg = mono_regstate_next_int (s->rs);
675                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, 
676                                                  s->stack_offset);
677                 }
678         }
679         g_free(argParm);
682 stmt: OP_OUTARG_VT (OP_REFANYTYPE (reg)) "0" {
683         MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused;
685 //printf("OP_OUTARG_VT (OP_REFANYTYPE (base))\n");
686         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->tree->sreg1, state->left->left->reg1, 
687                                     G_STRUCT_OFFSET (MonoTypedRef, type));
688         g_free(argParm);
689 }       
691 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
692         /* nothing to do: the value is already on the FP stack */
695 stmt: CEE_BNE_UN (fpcflags) {
696         tree->opcode = OP_FBNE_UN;
697         mono_bblock_add_inst (s->cbb, tree);
700 stmt: CEE_BEQ (fpcflags) {
701         tree->opcode = OP_FBEQ;
702         mono_bblock_add_inst (s->cbb, tree);
705 stmt: CEE_BLT (fpcflags) {
706         tree->opcode = OP_FBLT;
707         mono_bblock_add_inst (s->cbb, tree);
710 stmt: CEE_BLT_UN (fpcflags) {
711         tree->opcode = OP_FBLT_UN;
712         mono_bblock_add_inst (s->cbb, tree);
715 stmt: CEE_BGT (fpcflags) {
716         tree->opcode = OP_FBGT;
717         mono_bblock_add_inst (s->cbb, tree);
720 stmt: CEE_BGT_UN (fpcflags) {
721         tree->opcode = OP_FBGT_UN;
722         mono_bblock_add_inst (s->cbb, tree);
725 stmt: CEE_BGE  (fpcflags) {
726         tree->opcode = OP_FBGE;
727         mono_bblock_add_inst (s->cbb, tree);
730 stmt: CEE_BGE_UN (fpcflags) {
731         tree->opcode = OP_FBGE_UN;
732         mono_bblock_add_inst (s->cbb, tree);
735 stmt: CEE_BLE  (fpcflags) {
736         tree->opcode = OP_FBLE;
737         mono_bblock_add_inst (s->cbb, tree);
740 stmt: CEE_BLE_UN (fpcflags) {
741         tree->opcode = OP_FBLE_UN;
742         mono_bblock_add_inst (s->cbb, tree);
745 stmt: CEE_POP (freg) "0" {
746         /* nothing to do */
747 }     
749 freg: OP_LCONV_TO_R8 (lreg) {
750         /* nothing to do - emulated */
753 freg: OP_LCONV_TO_R4 (lreg) {
754         /* nothing to do - emulated */
757 freg: OP_LCONV_TO_R_UN (lreg) {
758         /* nothing to do - emulated */
761 freg: OP_FREM (freg, freg) {
762         /* nothing to do - emulated */
765 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
766         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
767                          state->left->right->reg1);
770 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
771         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
772                          state->left->right->reg1);
775 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
776         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
777                          state->left->right->reg1);
780 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
781         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
782                          state->left->right->reg1);
785 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
786         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
787                          state->left->right->reg1);
790 base: OP_S390_STKARG "0" {
791         int treg;
793         treg = mono_regstate_next_int (s->rs);
794         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, STK_BASE, 0);
795 //      MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, s->frame_reg, 0);
796         tree->inst_offset  = state->tree->inst_offset;
797         tree->inst_basereg = treg;
800 reg: OP_LDADDR (OP_S390_ARGREG),
801 reg: CEE_LDOBJ (OP_S390_ARGREG) "0" {
802         int treg;
804         MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, s->frame_reg, state->left->tree->inst_offset);
807 base: OP_LDADDR (OP_S390_LOADARG) "0" {
808         int treg;
810         treg = mono_regstate_next_int (s->rs);
811         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, 
812                                  state->left->tree->inst_offset);
813         tree->inst_offset  = 0;
814         tree->inst_basereg = treg;
817 base: OP_LDADDR (OP_S390_ARGPTR) "0" {
818         int treg;
820         treg = mono_regstate_next_int (s->rs);
821         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, 
822                                  state->left->tree->inst_offset);
823         tree->inst_offset  = 0;
824         tree->inst_basereg = treg;
827 base: OP_LDADDR (OP_S390_STKARG) "0" {
828         int treg;
830         treg = mono_regstate_next_int (s->rs);
831         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, STK_BASE, 0);
832         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, treg, 
833                                  state->left->tree->inst_offset);
834         tree->inst_offset  = 0;
835         tree->inst_basereg = treg;
838 reg: OP_LDADDR (OP_S390_LOADARG) "2" {
839         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
840                                  state->left->tree->inst_offset);
841         tree->inst_offset  = 0;
842         tree->inst_basereg = state->reg1;
845 reg: OP_LDADDR (OP_S390_ARGPTR) "2" {
846         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
847                                  state->left->tree->inst_offset);
848         tree->inst_offset  = 0;
849         tree->inst_basereg = state->reg1;
852 reg: OP_LDADDR (OP_S390_STKARG) "2" {
853         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
854                                  (s->stack_offset + state->left->tree->unused));
855         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1, 
856                                  state->left->tree->inst_offset);
857         tree->inst_offset  = 0;
858         tree->inst_basereg = state->reg1;
861 reg: CEE_LDOBJ (OP_S390_LOADARG) "1" {
862         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
863                                  state->left->tree->inst_offset);
866 reg: CEE_LDOBJ (OP_S390_ARGPTR) "1" {
867         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
868                              state->left->tree->inst_offset);
871 reg: CEE_LDOBJ (OP_S390_STKARG) "1" {
872         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg,
873                                  (s->stack_offset + state->left->tree->unused));
874         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1,
875                                  state->left->tree->inst_offset);
876         tree->inst_offset  = 0;
877         tree->inst_basereg = state->reg1;
880 base: CEE_LDOBJ (OP_S390_ARGPTR) "0" {
881         int treg;
883         treg = mono_regstate_next_int (s->rs);
884         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, 
885                                     state->left->tree->inst_offset);
886         tree->inst_offset  = 0;
887         tree->inst_basereg = treg;
890 base: CEE_LDOBJ (OP_S390_STKARG) "0" {
891         int treg;
893         treg = mono_regstate_next_int (s->rs);
894         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg,
895                                  (s->stack_offset + state->left->tree->unused));
896         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, state->left->tree->inst_offset);
897         tree->inst_offset  = 0;
898         tree->inst_basereg = treg;
901 reg: OP_ATOMIC_ADD_NEW_I4 (base, reg),
902 reg: OP_ATOMIC_ADD_I4 (base, reg) {
903         tree->opcode = tree->opcode;
904         tree->inst_basereg = state->left->tree->inst_basereg; 
905         tree->inst_offset = state->left->tree->inst_offset; 
906         tree->dreg = state->reg1;
907         tree->sreg2 = state->right->reg1;
908     
909         mono_bblock_add_inst (s->cbb, tree);
912 reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) {
913         tree->opcode = OP_ATOMIC_EXCHANGE_I4;
914         tree->dreg = state->reg1;
915         tree->sreg2 = state->right->reg1;
916         tree->inst_basereg = state->left->tree->inst_basereg; 
917         tree->inst_offset = state->left->tree->inst_offset; 
918     
919         mono_bblock_add_inst (s->cbb, tree);