* support-test-*.cs: Rename from test-*-p2.cs.
[mono.git] / mono / mini / inssel-s390.brg
1 %%
2
3 #
4 # inssel-s390.brg: burg file for special s390 instructions
5 #
6 # Author:
7 #   Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com)
8 #   Dietmar Maurer (dietmar@ximian.com)
9 #   Paolo Molaro (lupus@ximian.com)
10 #
11 # (C) 2002 Ximian, Inc.
12 #
13
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);
18 }
19
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);
24 }
25
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);
31 }
32
33 lreg: OP_LADD (lreg, lreg),
34 lreg: OP_LADD_OVF (lreg, lreg),
35 lreg: OP_LADD_OVF_UN (lreg, lreg),
36 lreg: OP_LSUB (lreg, lreg),
37 lreg: OP_LSUB_OVF (lreg, lreg),
38 lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" {
39         MONO_EMIT_NEW_UNALU (s, OP_SETREG, s390_r0, state->left->reg1);
40         MONO_EMIT_NEW_UNALU (s, OP_SETREG, s390_r1, state->left->reg2);
41         tree->dreg    = state->reg1;
42         tree->sreg1   = state->right->reg1;
43         tree->sreg2   = state->right->reg2;
44         mono_bblock_add_inst (s->cbb, tree);
45 }
46
47 lreg: OP_LADD (lreg, i8con) "0" {
48         MONO_EMIT_NEW_ICONST (s, s390_r0, state->right->tree->inst_ls_word);
49         MONO_EMIT_NEW_ICONST (s, s390_r1, state->right->tree->inst_ms_word);
50         tree->dreg    = state->reg1;
51         tree->sreg1   = state->left->reg1;
52         tree->sreg2   = state->left->reg2;
53         mono_bblock_add_inst (s->cbb, tree);
54 }
55
56 lreg: OP_LSUB (lreg, i8con) "0" {
57         int rh,rl;
58
59         MONO_EMIT_NEW_UNALU (s, OP_SETREG, s390_r0, state->left->reg1);
60         MONO_EMIT_NEW_UNALU (s, OP_SETREG, s390_r1, state->left->reg2);
61         rh = mono_regstate_next_int (s->rs);
62         MONO_EMIT_NEW_ICONST (s, rh, state->right->tree->inst_ls_word);
63         rl = mono_regstate_next_int (s->rs);
64         MONO_EMIT_NEW_ICONST (s, rl, state->right->tree->inst_ms_word);
65         tree->dreg    = state->reg1;
66         tree->sreg1   = rh;
67         tree->sreg2   = rl;
68         mono_bblock_add_inst (s->cbb, tree);
69 }
70
71 reg: CEE_ADD_OVF (reg, reg) "0" {
72         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
73 }
74
75 reg: CEE_ADD_OVF_UN (reg, reg) "0" {
76         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
77 }
78
79 reg: CEE_SUB_OVF (reg, reg) "0" {
80         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
81 }
82
83 reg: CEE_SUB_OVF_UN (reg, reg) "0" {
84         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
85 }
86
87 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
88         /*------------------------------------------------------*/
89         /* this should only happen for methods returning a long */
90         /* S/390 ABI uses r2/r3 for returning 64-bit integers   */
91         /*------------------------------------------------------*/
92         MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r2, state->right->reg1);
93         MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r3, state->right->reg2);
94 }
95
96 freg: OP_LCONV_TO_R8 (lreg) {
97         tree->dreg = state->reg1;
98         tree->sreg1 = state->left->reg1;
99         tree->sreg2 = state->left->reg2;
100         mono_bblock_add_inst (s->cbb, tree);
101 }
102
103 freg: OP_LCONV_TO_R4 (lreg) {
104         tree->dreg = state->reg1;
105         tree->sreg1 = state->left->reg1;
106         tree->sreg2 = state->left->reg2;
107         mono_bblock_add_inst (s->cbb, tree);
108 }
109
110 freg: CEE_CONV_R_UN (reg) {
111         tree->dreg = state->reg1;
112         tree->sreg1 = state->left->reg1;
113         mono_bblock_add_inst (s->cbb, tree);
114 }
115
116 freg: CEE_CONV_R_UN (reg) {
117         mono_bblock_add_inst (s->cbb, tree);
118 }
119
120 stmt: OP_MEMCPY (reg, reg) "0" {
121         int size = tree->unused;
122         if (size > 0) 
123                 MONO_EMIT_NEW_MOVE (s, state->left->reg1, 0, 
124                                     state->right->reg1, 0, size);
125 }
126
127 stmt: OP_MEMCPY (base, base) "0" {
128         int size = tree->unused;
129         if (size > 0)  
130                 MONO_EMIT_NEW_MOVE (s, state->left->tree->sreg1, 
131                                     state->left->tree->inst_offset, 
132                                     state->right->tree->sreg1,
133                                     state->right->tree->inst_offset,
134                                     size);
135 }
136
137 reg: OP_LOCALLOC (OP_ICONST) {
138         /* microcoded in mini-s390.c */
139         tree->sreg1 = mono_regstate_next_int (s->rs);
140         tree->dreg  = state->reg1;
141         MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
142         mono_bblock_add_inst (s->cbb, tree);
143 }
144
145 reg: OP_LOCALLOC (reg) {
146         tree->dreg = state->reg1;
147         tree->sreg1 = state->left->reg1;
148         mono_bblock_add_inst (s->cbb, tree);
149 }
150
151 stmt: OP_SETRET (reg) {
152         tree->opcode = OP_MOVE;
153         tree->sreg1 = state->left->reg1;
154         tree->dreg = s390_r2;
155         mono_bblock_add_inst (s->cbb, tree);
156 }
157
158 stmt: OP_SETRET (lreg) {
159         tree->opcode = OP_SETLRET;
160         tree->sreg1 = state->left->reg1;
161         tree->sreg2 = state->left->reg2;
162         mono_bblock_add_inst (s->cbb, tree);
163 }
164
165 stmt: OP_SETRET (freg) {
166         if (mono_method_signature (s->method)->ret->type == MONO_TYPE_R4) {
167                 tree->opcode = OP_S390_SETF4RET;
168                 tree->sreg1  = state->left->reg1;
169 //              tree->dreg   = s390_f0;
170         } else {
171                 tree->opcode = OP_FMOVE;
172                 tree->sreg1  = state->left->reg1;
173 //              tree->dreg   = s390_f0;
174         }
175         mono_bblock_add_inst (s->cbb, tree);
176 }
177
178 stmt: OP_SETRET (OP_ICONST) {
179         tree->opcode = OP_ICONST;
180         tree->inst_c0 = state->left->tree->inst_c0;
181         tree->dreg = s390_r2;
182         mono_bblock_add_inst (s->cbb, tree);
183 }
184
185 stmt: OP_OUTARG (reg) {
186         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
187
188         tree->opcode = OP_SETREG;
189         tree->dreg   = mono_regstate_next_int (s->rs);
190         tree->sreg1  = state->left->reg1;
191         mono_bblock_add_inst (s->cbb, tree);
192
193         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
194 }
195
196 stmt: OP_OUTARG_MEMBASE (reg) {
197         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
198
199         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
200                                      arg->offset, state->left->reg1);
201 }
202
203 stmt: OP_OUTARG (OP_REGVAR) {
204         MonoCallInst *call = (MonoCallInst*) tree->inst_right;
205
206         tree->opcode       = OP_SETREG;
207         tree->dreg         = mono_regstate_next_int (s->rs);
208         tree->sreg1        = state->left->tree->dreg;
209         mono_bblock_add_inst (s->cbb, tree);
210
211         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
212 }
213
214 stmt: OP_OUTARG_MEMBASE (OP_REGVAR) {
215         MonoCallArgParm *arg = (MonoCallArgParm *)  tree;
216
217         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
218                                      arg->offset, state->left->tree->dreg);
219 }
220
221 stmt: OP_OUTARG (lreg) {
222         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
223         int tdreg;
224
225         tdreg = mono_regstate_next_int (s->rs);
226         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tdreg, state->left->reg2);
227         
228         mono_call_inst_add_outarg_reg (call, tdreg, tree->unused, FALSE);
229
230         tree->opcode = OP_SETREG;
231         tree->dreg = mono_regstate_next_int (s->rs);
232         tree->sreg1 = state->left->reg1;
233         mono_bblock_add_inst (s->cbb, tree);
234         
235         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused + 1, FALSE);
236 }
237
238 stmt: OP_OUTARG_MEMBASE (lreg) {
239         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
240
241         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
242                                      arg->offset, state->left->reg2);
243         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
244                                      arg->offset + 4, state->left->reg1);
245 }
246
247 stmt: OP_OUTARG (OP_ICONST) {
248         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
249
250         tree->opcode       = OP_ICONST;
251         tree->dreg         = mono_regstate_next_int (s->rs);
252         tree->inst_c0      = state->left->tree->inst_c0;
253         mono_bblock_add_inst (s->cbb, tree);
254
255         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
256 }
257
258 stmt: OP_OUTARG_MEMBASE (OP_ICONST) {
259         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
260
261         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, 
262                                          arg->offset, state->left->tree->inst_c0);
263 }
264
265 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
266         MonoCallInst *call = (MonoCallInst*) tree->inst_right;
267
268         tree->opcode       = OP_SETREG;
269         tree->sreg1        = state->left->left->tree->dreg;
270         tree->dreg         = mono_regstate_next_int (s->rs);
271         mono_bblock_add_inst (s->cbb, tree);
272
273         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
274 }
275
276 stmt: OP_OUTARG_MEMBASE (CEE_LDIND_REF (OP_REGVAR)) {
277         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
278
279         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, 
280                                          arg->offset, state->left->tree->inst_c0);
281 }
282
283 stmt: OP_OUTARG_MEMBASE (OP_LDADDR (OP_S390_LOADARG)) {
284         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
285
286         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, 
287                                      arg->offset, state->left->left->tree->dreg);
288 }
289
290 freg: OP_FCONV_TO_R4 (freg) "0" {
291         /* The conversion is done elsewhere */
292         MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->reg1);
293 }
294
295 stmt: OP_OUTARG_R4 (freg) {
296         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
297
298         tree->opcode = OP_S390_SETF4RET;
299         tree->dreg   = mono_regstate_next_float (s->rs);
300         tree->sreg1  = state->left->reg1;
301         mono_bblock_add_inst (s->cbb, tree);
302
303         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
304 }
305
306 stmt: OP_OUTARG_R8 (freg),
307 stmt: OP_OUTARG (freg) {
308         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
309
310         tree->opcode = OP_SETFREG;
311         tree->dreg   = mono_regstate_next_float (s->rs);
312         tree->sreg1  = state->left->reg1;
313         mono_bblock_add_inst (s->cbb, tree);
314
315         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
316 }
317
318 stmt: OP_OUTARG_MEMBASE (freg) {
319         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
320
321         /*----------------------------------------------*/
322         /* The length stored in size tells us whether   */
323         /* we need to store a float or a double         */
324         /*----------------------------------------------*/
325         if (arg->size == 4) {
326                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, 
327                                              STK_BASE, arg->offset,
328                                              state->left->reg1);
329         } else {
330                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, 
331                                              STK_BASE, arg->offset,
332                                              state->left->reg1);
333         }
334 }
335
336 stmt: OP_OUTARG_R4 (CEE_LDOBJ (OP_REGOFFSET)),
337 stmt: OP_OUTARG_R8 (CEE_LDOBJ (OP_REGOFFSET)) {
338         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
339
340         tree->opcode = OP_SETFREG;
341         tree->dreg   = mono_regstate_next_float (s->rs);
342         tree->sreg1  = state->left->reg1;
343         mono_bblock_add_inst (s->cbb, tree);
344
345         mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
346 }
347
348 freg: OP_FCONV_TO_R4 (CEE_LDOBJ (OP_REGOFFSET)) {
349         MonoInst *vt = state->left->left->tree;
350  
351         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, state->reg1, vt->inst_basereg, 
352                                        vt->inst_offset);
353         MONO_EMIT_NEW_UNALU (s, OP_FCONV_TO_R4, state->reg1, state->reg1);
354 }
355
356 freg: OP_FCONV_TO_R8 (CEE_LDOBJ (OP_REGOFFSET)) {
357         tree->opcode = OP_SETFREG;
358         tree->sreg1 = state->left->reg1;
359         tree->dreg = tree->unused;
360         mono_bblock_add_inst (s->cbb, tree);
361 }
362
363
364 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
365         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
366         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
367         MonoInst *vt         = state->left->left->tree;
368         
369         int start_reg = tree->sreg1;
370         int size      = arg->size;
371         int soffset   = vt->inst_offset;
372         int treg;
373         
374         if (size < 0) { 
375                 size = -size;
376                 treg = mono_regstate_next_int (s->rs);
377                 if (start_reg != STK_BASE) {
378                         MONO_EMIT_NEW_MOVE(s, STK_BASE, arg->offPrm,
379                                            vt->inst_basereg, soffset, size);
380                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, 
381                                                  STK_BASE, arg->offPrm);
382                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
383                 } else { 
384                         MONO_EMIT_NEW_MOVE(s, STK_BASE, arg->offPrm,
385                                            vt->inst_basereg, soffset, size);
386                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, arg->offPrm);
387                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
388                                                      STK_BASE, arg->offset, treg);
389                 }
390         } else {
391                 if (start_reg != STK_BASE) {
392                         MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset);
393                 } else {
394                         MONO_OUTPUT_VTS (s, size, STK_BASE, arg->offset,
395                                          vt->inst_basereg, soffset);
396                 }       
397         }
398 }
399
400 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGPTR)) {
401         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
402         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
403         MonoInst *vt         = state->left->left->tree;
404         
405         int start_reg = tree->sreg1;
406         int size      = arg->size;
407         int soffset   = vt->inst_offset;
408
409         if (start_reg != STK_BASE) {
410                 MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset);
411         } else {
412                 
413                 MONO_OUTPUT_VTS (s, size, STK_BASE, arg->offset,
414                                  vt->inst_basereg, soffset);
415         }       
416 }
417
418 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_REGOFFSET)) "0" {
419         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
420         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
421         MonoInst *vt         = state->left->left->tree;
422         
423         int start_reg = tree->sreg1;
424         int size      = arg->size;
425         int soffset   = vt->inst_offset;
426         int treg;
427
428 //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_REGOFFSET))\n");
429         if (size < 0) { 
430                 size = -size;
431                 treg = mono_regstate_next_int (s->rs);
432                 if (start_reg != STK_BASE) {
433 //                      MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
434 //                                               STK_BASE, soffset);
435                         MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm,
436                                             vt->inst_basereg, soffset, size);
437                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
438                                                  STK_BASE, arg->offPrm);
439                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
440                 } else {
441                         MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm,
442                                             vt->inst_basereg, soffset, size);
443                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, arg->offPrm);
444                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
445                                                      STK_BASE, arg->offset, treg);
446                 }
447         } else {
448                 if (start_reg != STK_BASE) {
449                         MONO_OUTPUT_VTR(s, size, start_reg, vt->inst_basereg, soffset);
450                 } else {
451                         MONO_OUTPUT_VTS(s, size, STK_BASE, arg->offset,
452                                           vt->inst_basereg, soffset);
453                 }       
454         }
455 }
456
457 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_LOADARG)) {
458         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
459         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
460         MonoInst *vt         = state->left->left->tree;
461         
462         int start_reg = tree->inst_basereg;
463         int size      = -arg->size;
464         int soffset   = vt->inst_offset;
465         int treg;
466
467 //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_LOADARG))\n");
468         treg = mono_regstate_next_int (s->rs);
469         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg);
470         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, vt->unused);
471         MONO_EMIT_NEW_MOVE (s, STK_BASE, soffset, treg, 0, size);
472         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, soffset);
473         if (start_reg != STK_BASE) {
474                 mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
475         } else {
476                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
477                                              STK_BASE, arg->offset, treg);
478         }
479 }
480
481 stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGREG)) {
482         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
483         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
484         MonoInst *vt         = state->left->left->tree;
485         
486         int base_reg = tree->inst_basereg;
487         int size     = -arg->size;
488         int soffset  = vt->inst_offset;
489         int treg;
490
491 //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_ARGREG))\n");
492         treg = mono_regstate_next_int (s->rs);
493         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, s->frame_reg, soffset);
494         MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm, treg, 0, size);
495         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, arg->offPrm);
496         if (base_reg != STK_BASE) {
497                 mono_call_inst_add_outarg_reg (call, treg, base_reg, FALSE);
498         } else {
499                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
500                                              STK_BASE, arg->offset, treg);
501         }
502 }
503
504 stmt: OP_OUTARG_VT (OP_ICONST) {
505         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
506         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
507
508         int start_reg = tree->sreg1;
509         int size      = arg->size;
510         int nregs     = size / 4;
511
512 //printf("OP_OUTARG_VT(OP_ICONST)\n");
513         if (start_reg != STK_BASE) {
514                 if (nregs) {
515                         tree->opcode  = OP_SETREGIMM;
516                         tree->dreg    = mono_regstate_next_int (s->rs);
517                         tree->inst_c0 = state->left->tree->inst_c0;
518                         mono_bblock_add_inst (s->cbb, tree);
519                         mono_call_inst_add_outarg_reg (call, tree->dreg, start_reg, FALSE);
520                 }
521         } else {
522                 MONO_OUTPUT_VTS (s, size, STK_BASE, tree->inst_c0, 
523                                  s->frame_reg, tree->inst_offset);
524         }
525 }
526
527 stmt: OP_OUTARG_VT (reg) {
528         MonoCallInst *call   = (MonoCallInst*) tree->inst_right;
529         MonoCallArgParm *arg = (MonoCallArgParm *) tree; 
530         MonoInst *vt         = state->left->left->tree;
531         int start_reg        = tree->sreg1;
532         int size             = arg->size;
533         int soffset          = vt->inst_offset;
534         int treg;
535
536         if (size < 0) { 
537                 size = -size;
538                 treg = mono_regstate_next_int (s->rs);
539                 if (start_reg != STK_BASE) {
540                         MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm, state->left->reg1,
541                                             0, size);
542                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg,
543                                                  STK_BASE, arg->offPrm);
544                         mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE);
545                 } else {
546                         MONO_EMIT_NEW_MOVE (s, STK_BASE, soffset+size, state->left->reg1,
547                                             0, size);
548                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE,
549                                                  soffset+size);
550                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, 
551                                                      STK_BASE, arg->offset, treg);
552                 }
553         } else {
554                 if (start_reg != STK_BASE) {
555                         MONO_OUTPUT_VTR (s, size, start_reg, STK_BASE, soffset);
556                 } else {
557                         treg = mono_regstate_next_int (s->rs);
558                         MONO_OUTPUT_VTS (s, size, STK_BASE, soffset, treg,
559                                          state->left->tree->inst_offset);
560                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, 
561                                                  s->stack_offset);
562                 }
563         }
564 }
565
566 stmt: OP_OUTARG_VT (OP_REFANYTYPE (reg)) "0" {
567 //printf("OP_OUTARG_VT (OP_REFANYTYPE (base))\n");
568         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->tree->sreg1, state->left->left->reg1, 
569                                     G_STRUCT_OFFSET (MonoTypedRef, type));
570 }       
571
572 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
573         /* nothing to do: the value is already on the FP stack */
574 }
575
576 stmt: CEE_BNE_UN (fpcflags) {
577         tree->opcode = OP_FBNE_UN;
578         mono_bblock_add_inst (s->cbb, tree);
579 }
580
581 stmt: CEE_BEQ (fpcflags) {
582         tree->opcode = OP_FBEQ;
583         mono_bblock_add_inst (s->cbb, tree);
584 }
585
586 stmt: CEE_BLT (fpcflags) {
587         tree->opcode = OP_FBLT;
588         mono_bblock_add_inst (s->cbb, tree);
589 }
590
591 stmt: CEE_BLT_UN (fpcflags) {
592         tree->opcode = OP_FBLT_UN;
593         mono_bblock_add_inst (s->cbb, tree);
594 }
595
596 stmt: CEE_BGT (fpcflags) {
597         tree->opcode = OP_FBGT;
598         mono_bblock_add_inst (s->cbb, tree);
599 }
600
601 stmt: CEE_BGT_UN (fpcflags) {
602         tree->opcode = OP_FBGT_UN;
603         mono_bblock_add_inst (s->cbb, tree);
604 }
605
606 stmt: CEE_BGE  (fpcflags) {
607         tree->opcode = OP_FBGE;
608         mono_bblock_add_inst (s->cbb, tree);
609 }
610
611 stmt: CEE_BGE_UN (fpcflags) {
612         tree->opcode = OP_FBGE_UN;
613         mono_bblock_add_inst (s->cbb, tree);
614 }
615
616 stmt: CEE_BLE  (fpcflags) {
617         tree->opcode = OP_FBLE;
618         mono_bblock_add_inst (s->cbb, tree);
619 }
620
621 stmt: CEE_BLE_UN (fpcflags) {
622         tree->opcode = OP_FBLE_UN;
623         mono_bblock_add_inst (s->cbb, tree);
624 }
625
626 stmt: CEE_POP (freg) "0" {
627         /* nothing to do */
628 }     
629
630 freg: OP_LCONV_TO_R8 (lreg) {
631         /* nothing to do - emulated */
632 }
633
634 freg: OP_LCONV_TO_R4 (lreg) {
635         /* nothing to do - emulated */
636 }
637
638 freg: OP_LCONV_TO_R_UN (lreg) {
639         /* nothing to do - emulated */
640 }
641
642 freg: OP_FREM (freg, freg) {
643         /* nothing to do - emulated */
644 }
645
646 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
647         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
648                          state->left->right->reg1);
649 }
650
651 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
652         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
653                          state->left->right->reg1);
654 }
655
656 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
657         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
658                          state->left->right->reg1);
659 }
660
661 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
662         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
663                          state->left->right->reg1);
664 }
665
666 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
667         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
668                          state->left->right->reg1);
669 }
670
671 base: OP_S390_STKARG "0" {
672         int treg;
673
674         treg = mono_regstate_next_int (s->rs);
675         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg);
676         tree->inst_offset  = state->tree->inst_offset;
677         tree->inst_basereg = treg;
678 }
679
680 reg: OP_LDADDR (OP_S390_ARGREG),
681 reg: CEE_LDOBJ (OP_S390_ARGREG) "0" {
682         MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, s->frame_reg, state->left->tree->inst_offset);
683 }
684
685 base: OP_LDADDR (OP_S390_LOADARG) "0" {
686         int treg;
687
688         treg = mono_regstate_next_int (s->rs);
689         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg);
690         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, state->left->tree->unused);
691         tree->inst_offset  = 0;
692         tree->inst_basereg = treg;
693 }
694
695 base: OP_LDADDR (OP_S390_ARGPTR) "0" {
696         int treg;
697
698         treg = mono_regstate_next_int (s->rs);
699         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, 
700                                  state->left->tree->inst_offset);
701         tree->inst_offset  = 0;
702         tree->inst_basereg = treg;
703 }
704
705 base: OP_LDADDR (OP_S390_STKARG) "0" {
706         int treg;
707
708 printf("base: OP_LDADDR(OP_S390_STKARG) 0\n");
709         treg = mono_regstate_next_int (s->rs);
710         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg);
711         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, treg, 
712                                  state->left->tree->inst_offset);
713         tree->inst_offset  = 0;
714         tree->inst_basereg = treg;
715 }
716
717 reg: OP_LDADDR (OP_S390_LOADARG) {
718         int treg;
719
720         treg = mono_regstate_next_int (s->rs);
721         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg);
722         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, treg, state->left->tree->inst_offset);
723 }
724
725 reg: OP_LDADDR (OP_S390_ARGPTR) "2" {
726         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
727                                  state->left->tree->inst_offset);
728         tree->inst_offset  = 0;
729         tree->inst_basereg = state->reg1;
730 }
731
732 reg: OP_LDADDR (OP_S390_STKARG) "2" {
733         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, state->reg1, s->frame_reg);
734         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1,
735                                  (state->left->tree->unused +
736                                   state->left->tree->inst_offset));
737         tree->inst_offset  = 0;
738         tree->inst_basereg = state->reg1;
739 }
740
741 reg: CEE_LDOBJ (OP_S390_LOADARG) "1" {
742         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
743                                  state->left->tree->inst_offset);
744 }
745
746 reg: CEE_LDOBJ (OP_S390_ARGPTR) "1" {
747         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, 
748                              state->left->tree->inst_offset);
749 }
750
751 reg: CEE_LDOBJ (OP_S390_STKARG) "1" {
752 printf("reg: CEE_LDOBJ(OP_S390_STKARG)\n");
753         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, state->reg1, s->frame_reg);
754         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1,
755                                  (state->left->tree->inst_offset + 
756                                   state->left->tree->unused));
757         tree->inst_offset  = 0;
758         tree->inst_basereg = state->reg1;
759 }
760
761 base: CEE_LDOBJ (OP_S390_ARGPTR) "0" {
762         int treg;
763
764         treg = mono_regstate_next_int (s->rs);
765         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, 
766                                     state->left->tree->inst_offset);
767         tree->inst_offset  = 0;
768         tree->inst_basereg = treg;
769 }
770
771 base: CEE_LDOBJ (OP_S390_STKARG) "0" {
772         int treg;
773
774         treg = mono_regstate_next_int (s->rs);
775         MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg);
776         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, treg, state->left->tree->unused);
777         MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, state->left->tree->inst_offset);
778         tree->inst_offset  = 0;
779         tree->inst_basereg = treg;
780 }
781
782 reg: OP_ATOMIC_ADD_NEW_I4 (base, reg),
783 reg: OP_ATOMIC_ADD_I4 (base, reg) {
784         tree->opcode = tree->opcode;
785         tree->inst_basereg = state->left->tree->inst_basereg; 
786         tree->inst_offset = state->left->tree->inst_offset; 
787         tree->dreg = state->reg1;
788         tree->sreg2 = state->right->reg1;
789     
790         mono_bblock_add_inst (s->cbb, tree);
791 }
792
793 reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) {
794         tree->opcode = OP_ATOMIC_EXCHANGE_I4;
795         tree->dreg = state->reg1;
796         tree->sreg2 = state->right->reg1;
797         tree->inst_basereg = state->left->tree->inst_basereg; 
798         tree->inst_offset = state->left->tree->inst_offset; 
799     
800         mono_bblock_add_inst (s->cbb, tree);
801 }
802
803 %%