2003-05-26 Dietmar Maurer <dietmar@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 {
294                 tree->opcode = OP_X86_PUSH_OBJ;
295                 tree->inst_basereg = vt->inst_basereg;
296                 tree->inst_offset = vt->inst_offset;
297                 mono_bblock_add_inst (s->cbb, tree);
298         }
299 }
300
301 stmt: OP_OUTARG_VT (OP_ICONST) {
302         tree->opcode = OP_X86_PUSH_IMM;
303         tree->inst_imm = state->left->tree->inst_c0;
304         mono_bblock_add_inst (s->cbb, tree);
305 }
306
307 reg: CEE_LDELEMA (reg, reg) "15" {
308         int length_reg = mono_regstate_next_int (s->rs);
309         guint32 size = mono_class_array_element_size (tree->klass);
310         
311         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, length_reg, 
312                                        state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
313         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, length_reg, state->right->reg1);
314         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
315
316         if (size == 1 || size == 2 || size == 4 || size == 8) {
317                 static const int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
318                 tree->opcode = OP_X86_LEA;
319                 tree->dreg = state->reg1;
320                 tree->sreg1 = state->left->reg1;
321                 tree->sreg2 = state->right->reg1;
322                 tree->inst_imm = G_STRUCT_OFFSET (MonoArray, vector);
323                 tree->unused = fast_log2 [size];
324                 mono_bblock_add_inst (s->cbb, tree);
325         } else {
326                 int mult_reg = mono_regstate_next_int (s->rs);
327                 int add_reg = mono_regstate_next_int (s->rs);
328                 MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult_reg, state->right->reg1, size);
329                 MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
330                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
331         }
332 }
333
334 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
335         /* nothing to do: the value is already on the FP stack */
336 }
337
338 stmt: CEE_STIND_I4 (base, CEE_ADD (CEE_LDIND_I4 (base), OP_ICONST)) {
339         int con = state->right->right->tree->inst_c0;   
340
341         if (con == 1) {
342                 tree->opcode = OP_X86_INC_MEMBASE;
343         } else {
344                 tree->opcode = OP_X86_ADD_MEMBASE_IMM;
345                 tree->inst_imm = con;
346         }
347
348         tree->inst_basereg = state->left->tree->inst_basereg;
349         tree->inst_offset = state->left->tree->inst_offset;
350         mono_bblock_add_inst (s->cbb, tree);
351 } cost {
352         MBTREE_TYPE *t1 = state->right->left->left->tree;
353         MBTREE_TYPE *t2 = state->left->tree;
354         MBCOND (t1->inst_basereg == t2->inst_basereg &&
355                 t1->inst_offset == t2->inst_offset);
356         return 2;
357 }
358
359 stmt: CEE_STIND_I4 (base, CEE_SUB (CEE_LDIND_I4 (base), OP_ICONST)) {
360         int con = state->right->right->tree->inst_c0;   
361
362         if (con == 1) {
363                 tree->opcode = OP_X86_DEC_MEMBASE;
364         } else {
365                 tree->opcode = OP_X86_SUB_MEMBASE_IMM;
366                 tree->inst_imm = con;
367         }
368
369         tree->inst_basereg = state->left->tree->inst_basereg;
370         tree->inst_offset = state->left->tree->inst_offset;
371         mono_bblock_add_inst (s->cbb, tree);
372 } cost {
373         MBTREE_TYPE *t1 = state->right->left->left->tree;
374         MBTREE_TYPE *t2 = state->left->tree;
375         MBCOND (t1->inst_basereg == t2->inst_basereg &&
376                 t1->inst_offset == t2->inst_offset);
377         return 2;
378 }
379
380 #
381 # this rules is incorrect, it needs to do an indirect inc (inc_membase)
382 #stmt: CEE_STIND_I4 (reg, CEE_ADD (reg, OP_ICONST)) {
383 #       tree->opcode = OP_X86_INC_REG;
384 #       tree->dreg = state->left->reg1;
385 #       mono_bblock_add_inst (s->cbb, tree);
386 #} cost {
387 #       MBState *s1 = state->left;
388 #       MBState *s2 = state->right->left;
389 #       int con = state->right->right->tree->inst_c0;   
390 #       MBCOND (con == 1 && s1->reg1 == s2->reg1);
391 #       return 1;
392 #}
393
394 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)) {
395         int con = state->right->right->tree->inst_c0;   
396         int dreg = state->left->tree->dreg;
397         int sreg = state->right->left->left->tree->dreg;
398
399         if (con == 1) {
400                 if (dreg != sreg)
401                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
402                 tree->opcode = OP_X86_DEC_REG;
403                 tree->dreg = tree->sreg1 = dreg;
404         } else if (con == -1) {
405                 if (dreg != sreg)
406                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
407                 tree->opcode = OP_X86_INC_REG;
408                 tree->dreg = tree->sreg1 = dreg;
409         } else {
410                 tree->opcode = OP_SUB_IMM;
411                 tree->inst_imm = con;
412                 tree->sreg1 = sreg;
413                 tree->dreg = dreg;
414         }
415         mono_bblock_add_inst (s->cbb, tree);
416 }
417
418 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)) {
419         int con = state->right->right->tree->inst_c0;
420         int dreg = state->left->tree->dreg;
421         int sreg = state->right->left->left->tree->dreg;
422
423         if (con == 1) {
424                 if (dreg != sreg)
425                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
426                 tree->opcode = OP_X86_INC_REG;
427                 tree->dreg = tree->sreg1 = dreg;
428         } else if (con == -1) {
429                 if (dreg != sreg)
430                         MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, sreg);
431                 tree->opcode = OP_X86_DEC_REG;
432                 tree->dreg = tree->sreg1 = dreg;
433         } else {
434                 tree->opcode = OP_ADD_IMM;
435                 tree->inst_imm = con;
436                 tree->sreg1 = sreg;
437                 tree->dreg = dreg;
438         }
439         mono_bblock_add_inst (s->cbb, tree);
440 }
441
442 reg: CEE_LDIND_I2 (OP_REGVAR) {
443         MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);
444 }
445
446 # on x86, fp compare overwrites EAX, so we must
447 # either improve the local register allocator or
448 # emit coarse opcodes which saves EAX for us.
449
450 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
451         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
452                          state->left->right->reg1);
453 }
454
455 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
456         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
457                          state->left->right->reg1);
458 }
459
460 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
461         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
462                          state->left->right->reg1);
463 }
464
465 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
466         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
467                          state->left->right->reg1);
468 }
469
470 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
471         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
472                          state->left->right->reg1);
473 }
474
475 # fpcflags overwrites EAX, but this does not matter for statements
476 # because we are the last operation in the tree.
477  
478 stmt: CEE_BNE_UN (fpcflags) {
479         tree->opcode = OP_FBNE_UN;
480         mono_bblock_add_inst (s->cbb, tree);
481 }
482
483 stmt: CEE_BEQ (fpcflags) {
484         tree->opcode = OP_FBEQ;
485         mono_bblock_add_inst (s->cbb, tree);
486 }
487
488 stmt: CEE_BLT (fpcflags) {
489         tree->opcode = OP_FBLT;
490         mono_bblock_add_inst (s->cbb, tree);
491 }
492
493 stmt: CEE_BLT_UN (fpcflags) {
494         tree->opcode = OP_FBLT_UN;
495         mono_bblock_add_inst (s->cbb, tree);
496 }
497
498 stmt: CEE_BGT (fpcflags) {
499         tree->opcode = OP_FBGT;
500         mono_bblock_add_inst (s->cbb, tree);
501 }
502
503 stmt: CEE_BGT_UN (fpcflags) {
504         tree->opcode = OP_FBGT_UN;
505         mono_bblock_add_inst (s->cbb, tree);
506 }
507
508 stmt: CEE_BGE  (fpcflags) {
509         tree->opcode = OP_FBGE;
510         mono_bblock_add_inst (s->cbb, tree);
511 }
512
513 stmt: CEE_BGE_UN (fpcflags) {
514         tree->opcode = OP_FBGE_UN;
515         mono_bblock_add_inst (s->cbb, tree);
516 }
517
518 stmt: CEE_BLE  (fpcflags) {
519         tree->opcode = OP_FBLE;
520         mono_bblock_add_inst (s->cbb, tree);
521 }
522
523 stmt: CEE_BLE_UN (fpcflags) {
524         tree->opcode = OP_FBLE_UN;
525         mono_bblock_add_inst (s->cbb, tree);
526 }
527
528 stmt: CEE_POP (freg) "0" {
529         /* we need to pop the value from the x86 FP stack */
530         MONO_EMIT_UNALU (s, tree, OP_X86_FPOP, -1, state->left->reg1);  
531 }     
532
533 %%