Mon Jun 30 19:16:33 CEST 2003 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / inssel-x86.brg
1 %%
2
3 #
4 # inssel-x86.brg: burg file for special x86 instructions
5 #
6 # Author:
7 #   Dietmar Maurer (dietmar@ximian.com)
8 #   Paolo Molaro (lupus@ximian.com)
9 #
10 # (C) 2002 Ximian, Inc.
11 #
12
13 stmt: OP_START_HANDLER {
14         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->spvar->inst_basereg, s->spvar->inst_offset, X86_ESP);
15 }
16
17 stmt: CEE_ENDFINALLY {
18         MONO_EMIT_NEW_LOAD_MEMBASE (s, X86_ESP, s->spvar->inst_basereg, s->spvar->inst_offset); 
19         tree->opcode = CEE_RET;
20         mono_bblock_add_inst (s->cbb, tree);
21 }
22
23 stmt: OP_ENDFILTER (reg) {
24         MONO_EMIT_NEW_UNALU (s, OP_MOVE, X86_EAX, state->left->reg1);
25         MONO_EMIT_NEW_LOAD_MEMBASE (s, X86_ESP, s->spvar->inst_basereg, s->spvar->inst_offset); 
26         tree->opcode = CEE_RET;
27         mono_bblock_add_inst (s->cbb, tree);
28 }
29
30 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
31         /* this should only happen for methods returning a long */
32         MONO_EMIT_NEW_UNALU (s, OP_MOVE, X86_EAX, state->right->reg1);
33         MONO_EMIT_NEW_UNALU (s, OP_MOVE, X86_EDX, state->right->reg2);
34 }
35
36 lreg: OP_LNEG (lreg) "3" {
37         int tmpr = mono_regstate_next_int (s->rs);
38         MONO_EMIT_NEW_UNALU (s, CEE_NEG, state->reg1, state->left->reg1);
39         MONO_EMIT_BIALU_IMM (s, tree, OP_ADC_IMM, tmpr, state->left->reg2, 0);
40         MONO_EMIT_NEW_UNALU (s, CEE_NEG, state->reg2, tmpr);
41 }
42
43 freg: OP_LCONV_TO_R8 (lreg) {
44         MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg2);
45         MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg1);
46         tree->opcode = OP_X86_FP_LOAD_I8;
47         tree->inst_basereg = X86_ESP;
48         tree->inst_offset = 0;
49         mono_bblock_add_inst (s->cbb, tree);
50         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, X86_ESP, X86_ESP, 8);
51 }
52
53 freg: OP_LCONV_TO_R4 (lreg) {
54         MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg2);
55         MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg1);
56         tree->opcode = OP_X86_FP_LOAD_I8;
57         tree->inst_basereg = X86_ESP;
58         tree->inst_offset = 0;
59         mono_bblock_add_inst (s->cbb, tree);
60         /* change precision */
61         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, X86_ESP, 0, state->reg1);
62         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, state->reg1, X86_ESP, 0);
63         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, X86_ESP, X86_ESP, 8);
64 }
65
66 freg: CEE_CONV_R_UN (reg) {
67         MONO_EMIT_NEW_BIALU_IMM (s, OP_X86_PUSH_IMM, -1, -1, 0);
68         MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg1);
69         tree->opcode = OP_X86_FP_LOAD_I8;
70         tree->inst_basereg = X86_ESP;
71         tree->inst_offset = 0;
72         mono_bblock_add_inst (s->cbb, tree);
73         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, X86_ESP, X86_ESP, 8);
74 }
75
76 cflags: OP_COMPARE (CEE_LDIND_I4 (base), reg) {
77         tree->opcode = OP_X86_COMPARE_MEMBASE_REG;
78         tree->inst_basereg = state->left->left->tree->inst_basereg;
79         tree->inst_offset = state->left->left->tree->inst_offset;
80         tree->sreg2 = state->right->reg1;
81         mono_bblock_add_inst (s->cbb, tree);
82 }
83
84 cflags: OP_COMPARE (CEE_LDIND_I4 (base), OP_ICONST) {
85         tree->opcode = OP_X86_COMPARE_MEMBASE_IMM;
86         tree->inst_basereg = state->left->left->tree->inst_basereg;
87         tree->inst_offset = state->left->left->tree->inst_offset;
88         tree->inst_imm = state->right->tree->inst_c0;
89         mono_bblock_add_inst (s->cbb, tree);
90 }
91
92 cflags: OP_COMPARE (reg, CEE_LDIND_I4 (base)) {
93         tree->opcode = OP_X86_COMPARE_REG_MEMBASE;
94         tree->sreg2 = state->right->left->tree->inst_basereg;
95         tree->inst_offset = state->right->left->tree->inst_offset;
96         tree->sreg1 = state->left->reg1;
97         mono_bblock_add_inst (s->cbb, tree);
98 }
99
100 stmt: CEE_STIND_I1 (base, OP_CEQ (cflags)) {
101         tree->opcode = OP_X86_SETEQ_MEMBASE;
102         tree->inst_offset = state->left->tree->inst_offset;
103         tree->inst_basereg = state->left->tree->inst_basereg;
104         mono_bblock_add_inst (s->cbb, tree);
105 }
106
107 reg: OP_LOCALLOC (OP_ICONST) {
108         if (tree->flags & MONO_INST_INIT) {
109                 /* microcoded in mini-x86.c */
110                 tree->sreg1 = mono_regstate_next_int (s->rs);
111                 MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
112                 mono_bblock_add_inst (s->cbb, tree);
113         } else {
114                 MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, state->left->tree->inst_c0);
115                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, X86_ESP);
116         }
117 }
118
119 reg: OP_LOCALLOC (reg) {
120         mono_bblock_add_inst (s->cbb, tree);
121 }
122
123 stmt: OP_SETRET (reg) {
124         tree->opcode = OP_MOVE;
125         tree->sreg1 = state->left->reg1;
126         tree->dreg = X86_EAX;
127         mono_bblock_add_inst (s->cbb, tree);
128 }
129
130 stmt: OP_SETRET (lreg) {
131         MONO_EMIT_NEW_UNALU (s, OP_MOVE, X86_EDX, state->left->reg2);
132         tree->opcode = OP_MOVE;
133         tree->sreg1 = state->left->reg1;
134         tree->dreg = X86_EAX;
135         mono_bblock_add_inst (s->cbb, tree);
136 }
137
138 stmt: OP_SETRET (CEE_LDIND_REF (OP_REGVAR)) {
139         tree->opcode = OP_MOVE;
140         tree->sreg1 = state->left->left->tree->dreg;
141         tree->dreg = X86_EAX;
142         mono_bblock_add_inst (s->cbb, tree);
143 }
144
145 stmt: OP_SETRET (freg) {
146         /* nothing to do */
147 }
148
149 stmt: OP_SETRET (OP_ICONST) {
150         tree->opcode = OP_ICONST;
151         tree->inst_c0 = state->left->tree->inst_c0;
152         tree->dreg = X86_EAX;
153         mono_bblock_add_inst (s->cbb, tree);
154 }
155
156 stmt: OP_OUTARG (reg) {
157         tree->opcode = OP_X86_PUSH;
158         tree->sreg1 = state->left->reg1;
159         mono_bblock_add_inst (s->cbb, tree);
160 }
161
162 # we need to reduce this code duplication with some burg syntax extension
163 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
164         tree->opcode = OP_X86_PUSH;
165         tree->sreg1 = state->left->left->tree->dreg;
166         mono_bblock_add_inst (s->cbb, tree);
167 }
168
169 stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) {
170         tree->opcode = OP_X86_PUSH;
171         tree->sreg1 = state->left->left->tree->dreg;
172         mono_bblock_add_inst (s->cbb, tree);
173 }
174
175 stmt: OP_OUTARG (CEE_LDIND_U4 (OP_REGVAR)) {
176         tree->opcode = OP_X86_PUSH;
177         tree->sreg1 = state->left->left->tree->dreg;
178         mono_bblock_add_inst (s->cbb, tree);
179 }
180
181 stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) {
182         tree->opcode = OP_X86_PUSH;
183         tree->sreg1 = state->left->left->tree->dreg;
184         mono_bblock_add_inst (s->cbb, tree);
185 }
186
187 stmt: OP_OUTARG (lreg) {
188         MONO_EMIT_NEW_UNALU (s, OP_X86_PUSH, -1, state->left->reg2);
189         tree->opcode = OP_X86_PUSH;
190         tree->sreg1 = state->left->reg1;
191         mono_bblock_add_inst (s->cbb, tree);
192 }
193
194 stmt: OP_OUTARG (CEE_LDIND_I8 (base)) {
195         MonoInst *ins;
196         ins = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
197         ins->opcode = OP_X86_PUSH_MEMBASE;
198         ins->inst_basereg = state->left->left->tree->inst_basereg;
199         ins->inst_offset = state->left->left->tree->inst_offset + 4;
200         mono_bblock_add_inst (s->cbb, ins);
201
202         tree->opcode = OP_X86_PUSH_MEMBASE;
203         tree->inst_basereg = state->left->left->tree->inst_basereg;
204         tree->inst_offset = state->left->left->tree->inst_offset;
205         mono_bblock_add_inst (s->cbb, tree);
206 }
207
208 stmt: OP_OUTARG (OP_ICONST) {
209         tree->opcode = OP_X86_PUSH_IMM;
210         tree->inst_imm = state->left->tree->inst_c0;
211         mono_bblock_add_inst (s->cbb, tree);
212 }
213
214 stmt: OP_OUTARG (CEE_LDIND_I4 (base)) {
215         tree->opcode = OP_X86_PUSH_MEMBASE;
216         tree->inst_basereg = state->left->left->tree->inst_basereg;
217         tree->inst_offset = state->left->left->tree->inst_offset;
218         mono_bblock_add_inst (s->cbb, tree);
219 }
220
221 stmt: OP_OUTARG (CEE_LDIND_U4 (base)) {
222         tree->opcode = OP_X86_PUSH_MEMBASE;
223         tree->inst_basereg = state->left->left->tree->inst_basereg;
224         tree->inst_offset = state->left->left->tree->inst_offset;
225         mono_bblock_add_inst (s->cbb, tree);
226 }
227
228 stmt: OP_OUTARG (CEE_LDIND_I (base)) {
229         tree->opcode = OP_X86_PUSH_MEMBASE;
230         tree->inst_basereg = state->left->left->tree->inst_basereg;
231         tree->inst_offset = state->left->left->tree->inst_offset;
232         mono_bblock_add_inst (s->cbb, tree);
233 }
234
235 stmt: OP_OUTARG (CEE_LDIND_REF (base)) {
236         tree->opcode = OP_X86_PUSH_MEMBASE;
237         tree->inst_basereg = state->left->left->tree->inst_basereg;
238         tree->inst_offset = state->left->left->tree->inst_offset;
239         mono_bblock_add_inst (s->cbb, tree);
240 }
241
242 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
243         tree->opcode = OP_X86_PUSH;
244         tree->sreg1 = state->left->left->tree->dreg;
245         mono_bblock_add_inst (s->cbb, tree);
246 }
247
248 stmt: OP_OUTARG (CEE_LDOBJ (reg)) {
249         tree->opcode = OP_X86_PUSH;
250         tree->sreg1 = state->left->reg1;
251         mono_bblock_add_inst (s->cbb, tree);
252 }
253
254 stmt: OP_OUTARG (freg) {
255         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, 8);
256         tree->opcode = OP_STORER8_MEMBASE_REG;
257         tree->sreg1 = state->left->reg1;
258         tree->inst_destbasereg = X86_ESP;
259         tree->inst_offset = 0;
260         mono_bblock_add_inst (s->cbb, tree);
261 }
262
263 stmt: OP_OUTARG_R4 (freg) {
264         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, 4);
265         tree->opcode = OP_STORER4_MEMBASE_REG;
266         tree->sreg1 = state->left->reg1;
267         tree->inst_destbasereg = X86_ESP;
268         tree->inst_offset = 0;
269         mono_bblock_add_inst (s->cbb, tree);
270 }
271
272 stmt: OP_OUTARG_R8 (freg) {
273         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, 8);
274         tree->opcode = OP_STORER8_MEMBASE_REG;
275         tree->sreg1 = state->left->reg1;
276         tree->inst_destbasereg = X86_ESP;
277         tree->inst_offset = 0;
278         mono_bblock_add_inst (s->cbb, tree);
279 }
280
281 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
282         MonoInst *vt = state->left->left->tree;
283         //g_print ("vt size: %d at R%d + %d\n", tree->inst_imm, vt->inst_basereg, vt->inst_offset);
284
285         if (!tree->inst_imm)
286                 return;
287
288         if (tree->inst_imm <= 4) {
289                 tree->opcode = OP_X86_PUSH_MEMBASE;
290                 tree->inst_basereg = vt->inst_basereg;
291                 tree->inst_offset = vt->inst_offset;
292                 mono_bblock_add_inst (s->cbb, tree);
293         } else if (tree->inst_imm <= 20) {
294                 int sz = tree->inst_imm;
295                 sz += 3;
296                 sz &= ~3;
297                 MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, X86_ESP, X86_ESP, sz);
298                 mini_emit_memcpy (s, X86_ESP, 0, vt->inst_basereg, vt->inst_offset, tree->inst_imm, 0);
299         } else {
300                 tree->opcode = OP_X86_PUSH_OBJ;
301                 tree->inst_basereg = vt->inst_basereg;
302                 tree->inst_offset = vt->inst_offset;
303                 mono_bblock_add_inst (s->cbb, tree);
304         }
305 }
306
307 stmt: OP_OUTARG_VT (OP_ICONST) {
308         tree->opcode = OP_X86_PUSH_IMM;
309         tree->inst_imm = state->left->tree->inst_c0;
310         mono_bblock_add_inst (s->cbb, tree);
311 }
312
313 reg: OP_LDADDR (OP_REGOFFSET) "1" {
314         if (state->left->tree->inst_offset) {
315                 tree->opcode = OP_X86_LEA_MEMBASE;
316                 tree->sreg1 = state->left->tree->inst_basereg;
317                 tree->inst_imm = state->left->tree->inst_offset;
318                 tree->dreg = state->reg1;
319         } else {
320                 tree->opcode = OP_MOVE;
321                 tree->sreg1 = state->left->tree->inst_basereg;
322                 tree->dreg = state->reg1;
323         }
324         mono_bblock_add_inst (s->cbb, tree);
325 }
326
327 reg: CEE_LDOBJ (OP_REGOFFSET) "1" {
328         if (state->left->tree->inst_offset) {
329                 tree->opcode = OP_X86_LEA_MEMBASE;
330                 tree->sreg1 = state->left->tree->inst_basereg;
331                 tree->inst_imm = state->left->tree->inst_offset;
332                 tree->dreg = state->reg1;
333         } else {
334                 tree->opcode = OP_MOVE;
335                 tree->sreg1 = state->left->tree->inst_basereg;
336                 tree->dreg = state->reg1;
337         }
338         mono_bblock_add_inst (s->cbb, tree);
339 }
340
341 reg: CEE_LDELEMA (reg, reg) "15" {
342         int length_reg = mono_regstate_next_int (s->rs);
343         guint32 size = mono_class_array_element_size (tree->klass);
344         
345         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, length_reg, 
346                                        state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
347         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, length_reg, state->right->reg1);
348         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
349
350         if (size == 1 || size == 2 || size == 4 || size == 8) {
351                 static const int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
352                 tree->opcode = OP_X86_LEA;
353                 tree->dreg = state->reg1;
354                 tree->sreg1 = state->left->reg1;
355                 tree->sreg2 = state->right->reg1;
356                 tree->inst_imm = G_STRUCT_OFFSET (MonoArray, vector);
357                 tree->unused = fast_log2 [size];
358                 mono_bblock_add_inst (s->cbb, tree);
359         } else {
360                 int mult_reg = mono_regstate_next_int (s->rs);
361                 int add_reg = mono_regstate_next_int (s->rs);
362                 MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult_reg, state->right->reg1, size);
363                 MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
364                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
365         }
366 }
367
368 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
369         /* nothing to do: the value is already on the FP stack */
370 }
371
372 stmt: CEE_STIND_I4 (base, CEE_ADD (CEE_LDIND_I4 (base), OP_ICONST)) {
373         int con = state->right->right->tree->inst_c0;   
374
375         if (con == 1) {
376                 tree->opcode = OP_X86_INC_MEMBASE;
377         } else {
378                 tree->opcode = OP_X86_ADD_MEMBASE_IMM;
379                 tree->inst_imm = con;
380         }
381
382         tree->inst_basereg = state->left->tree->inst_basereg;
383         tree->inst_offset = state->left->tree->inst_offset;
384         mono_bblock_add_inst (s->cbb, tree);
385 } cost {
386         MBTREE_TYPE *t1 = state->right->left->left->tree;
387         MBTREE_TYPE *t2 = state->left->tree;
388         MBCOND (t1->inst_basereg == t2->inst_basereg &&
389                 t1->inst_offset == t2->inst_offset);
390         return 2;
391 }
392
393 stmt: CEE_STIND_I4 (base, CEE_SUB (CEE_LDIND_I4 (base), OP_ICONST)) {
394         int con = state->right->right->tree->inst_c0;   
395
396         if (con == 1) {
397                 tree->opcode = OP_X86_DEC_MEMBASE;
398         } else {
399                 tree->opcode = OP_X86_SUB_MEMBASE_IMM;
400                 tree->inst_imm = con;
401         }
402
403         tree->inst_basereg = state->left->tree->inst_basereg;
404         tree->inst_offset = state->left->tree->inst_offset;
405         mono_bblock_add_inst (s->cbb, tree);
406 } cost {
407         MBTREE_TYPE *t1 = state->right->left->left->tree;
408         MBTREE_TYPE *t2 = state->left->tree;
409         MBCOND (t1->inst_basereg == t2->inst_basereg &&
410                 t1->inst_offset == t2->inst_offset);
411         return 2;
412 }
413
414 #
415 # this rules is incorrect, it needs to do an indirect inc (inc_membase)
416 #stmt: CEE_STIND_I4 (reg, CEE_ADD (reg, OP_ICONST)) {
417 #       tree->opcode = OP_X86_INC_REG;
418 #       tree->dreg = state->left->reg1;
419 #       mono_bblock_add_inst (s->cbb, tree);
420 #} cost {
421 #       MBState *s1 = state->left;
422 #       MBState *s2 = state->right->left;
423 #       int con = state->right->right->tree->inst_c0;   
424 #       MBCOND (con == 1 && s1->reg1 == s2->reg1);
425 #       return 1;
426 #}
427
428 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)) {
429         int con = state->right->right->tree->inst_c0;   
430         int dreg = state->left->tree->dreg;
431         int sreg = state->right->left->left->tree->dreg;
432
433         if (con == 1) {
434                 if (dreg != sreg)
435                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
436                 tree->opcode = OP_X86_DEC_REG;
437                 tree->dreg = tree->sreg1 = dreg;
438         } else if (con == -1) {
439                 if (dreg != sreg)
440                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
441                 tree->opcode = OP_X86_INC_REG;
442                 tree->dreg = tree->sreg1 = dreg;
443         } else {
444                 tree->opcode = OP_SUB_IMM;
445                 tree->inst_imm = con;
446                 tree->sreg1 = sreg;
447                 tree->dreg = dreg;
448         }
449         mono_bblock_add_inst (s->cbb, tree);
450 }
451
452 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)) {
453         int con = state->right->right->tree->inst_c0;
454         int dreg = state->left->tree->dreg;
455         int sreg = state->right->left->left->tree->dreg;
456
457         if (con == 1) {
458                 if (dreg != sreg)
459                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
460                 tree->opcode = OP_X86_INC_REG;
461                 tree->dreg = tree->sreg1 = dreg;
462         } else if (con == -1) {
463                 if (dreg != sreg)
464                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
465                 tree->opcode = OP_X86_DEC_REG;
466                 tree->dreg = tree->sreg1 = dreg;
467         } else {
468                 tree->opcode = OP_ADD_IMM;
469                 tree->inst_imm = con;
470                 tree->sreg1 = sreg;
471                 tree->dreg = dreg;
472         }
473         mono_bblock_add_inst (s->cbb, tree);
474 }
475
476 reg: CEE_LDIND_I2 (OP_REGVAR) {
477         MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);
478 }
479
480 # on x86, fp compare overwrites EAX, so we must
481 # either improve the local register allocator or
482 # emit coarse opcodes which saves EAX for us.
483
484 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
485         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
486                          state->left->right->reg1);
487 }
488
489 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
490         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
491                          state->left->right->reg1);
492 }
493
494 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
495         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
496                          state->left->right->reg1);
497 }
498
499 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
500         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
501                          state->left->right->reg1);
502 }
503
504 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
505         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
506                          state->left->right->reg1);
507 }
508
509 # fpcflags overwrites EAX, but this does not matter for statements
510 # because we are the last operation in the tree.
511  
512 stmt: CEE_BNE_UN (fpcflags) {
513         tree->opcode = OP_FBNE_UN;
514         mono_bblock_add_inst (s->cbb, tree);
515 }
516
517 stmt: CEE_BEQ (fpcflags) {
518         tree->opcode = OP_FBEQ;
519         mono_bblock_add_inst (s->cbb, tree);
520 }
521
522 stmt: CEE_BLT (fpcflags) {
523         tree->opcode = OP_FBLT;
524         mono_bblock_add_inst (s->cbb, tree);
525 }
526
527 stmt: CEE_BLT_UN (fpcflags) {
528         tree->opcode = OP_FBLT_UN;
529         mono_bblock_add_inst (s->cbb, tree);
530 }
531
532 stmt: CEE_BGT (fpcflags) {
533         tree->opcode = OP_FBGT;
534         mono_bblock_add_inst (s->cbb, tree);
535 }
536
537 stmt: CEE_BGT_UN (fpcflags) {
538         tree->opcode = OP_FBGT_UN;
539         mono_bblock_add_inst (s->cbb, tree);
540 }
541
542 stmt: CEE_BGE  (fpcflags) {
543         tree->opcode = OP_FBGE;
544         mono_bblock_add_inst (s->cbb, tree);
545 }
546
547 stmt: CEE_BGE_UN (fpcflags) {
548         tree->opcode = OP_FBGE_UN;
549         mono_bblock_add_inst (s->cbb, tree);
550 }
551
552 stmt: CEE_BLE  (fpcflags) {
553         tree->opcode = OP_FBLE;
554         mono_bblock_add_inst (s->cbb, tree);
555 }
556
557 stmt: CEE_BLE_UN (fpcflags) {
558         tree->opcode = OP_FBLE_UN;
559         mono_bblock_add_inst (s->cbb, tree);
560 }
561
562 stmt: CEE_POP (freg) "0" {
563         /* we need to pop the value from the x86 FP stack */
564         MONO_EMIT_UNALU (s, tree, OP_X86_FPOP, -1, state->left->reg1);  
565 }     
566
567 %%