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