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