2008-03-20 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / mini / inssel-arm.brg
1 %%
2
3 #
4 # inssel-arm.brg: burg file for special ARM 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         MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
15         /*MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, spvar->inst_basereg, spvar->inst_offset, ppc_sp);
16         */
17         tree->inst_left = spvar;
18         mono_bblock_add_inst (s->cbb, tree);
19 }
20
21 stmt: OP_ENDFINALLY {
22         MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
23         tree->inst_left = spvar;
24         mono_bblock_add_inst (s->cbb, tree);
25 }
26
27 stmt: OP_ENDFILTER (reg) {
28         MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
29         tree->inst_left = spvar;
30         tree->sreg1 = state->left->reg1;
31         mono_bblock_add_inst (s->cbb, tree);
32 }
33
34 lreg: OP_LADD_OVF (lreg, lreg) "0" {
35         /* ADC sets the condition code */
36         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
37         MONO_EMIT_NEW_BIALU (s, OP_ADD_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2);
38 }
39
40 lreg: OP_LADD_OVF_UN (lreg, lreg) "0" {
41         /* ADC sets the condition code */
42         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
43         MONO_EMIT_NEW_BIALU (s, OP_ADD_OVF_UN_CARRY, state->reg2, state->left->reg2, state->right->reg2);
44 }
45
46 lreg: OP_LSUB_OVF (lreg, lreg) "0" {
47         /* SBB sets the condition code */
48         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
49         MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2);
50 }
51
52 lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" {
53         /* SBB sets the condition code */
54         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
55         MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_UN_CARRY, state->reg2, state->left->reg2, state->right->reg2);
56 }
57
58 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
59         /* this should only happen for methods returning a long */
60         MONO_EMIT_NEW_UNALU (s, OP_MOVE, ARMREG_R0, state->right->reg1);
61         MONO_EMIT_NEW_UNALU (s, OP_MOVE, ARMREG_R1, state->right->reg2);
62 }
63
64 lreg: OP_LNEG (lreg) "2" {
65         MONO_EMIT_NEW_BIALU_IMM (s, OP_ARM_RSBS_IMM, state->reg1, state->left->reg1, 0);
66         MONO_EMIT_BIALU_IMM (s, tree, OP_ARM_RSC_IMM, state->reg2, state->left->reg2, 0);
67 }
68
69 freg: OP_LCONV_TO_R8 (lreg) {
70         tree->dreg = state->reg1;
71         tree->sreg1 = state->left->reg1;
72         tree->sreg2 = state->left->reg2;
73         mono_bblock_add_inst (s->cbb, tree);
74 }
75
76 freg: OP_LCONV_TO_R4 (lreg) {
77         tree->dreg = state->reg1;
78         tree->sreg1 = state->left->reg1;
79         tree->sreg2 = state->left->reg2;
80         mono_bblock_add_inst (s->cbb, tree);
81 }
82
83 freg: CEE_CONV_R_UN (reg) {
84         tree->dreg = state->reg1;
85         tree->sreg1 = state->left->reg1;
86         mono_bblock_add_inst (s->cbb, tree);
87 }
88
89 reg: OP_LOCALLOC (OP_ICONST) {
90         /* microcoded in mini-arm.c */
91         tree->sreg1 = mono_regstate_next_int (s->rs);
92         tree->dreg = state->reg1;
93         MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
94         mono_bblock_add_inst (s->cbb, tree);
95 }
96
97 reg: OP_LOCALLOC (reg) {
98         tree->dreg = state->reg1;
99         tree->sreg1 = state->left->reg1;
100         mono_bblock_add_inst (s->cbb, tree);
101 }
102
103 stmt: OP_SETRET (reg) {
104         tree->opcode = OP_MOVE;
105         tree->sreg1 = state->left->reg1;
106         tree->dreg = ARMREG_R0;
107         mono_bblock_add_inst (s->cbb, tree);
108 }
109
110 stmt: OP_SETRET (lreg) {
111         tree->opcode = OP_SETLRET;
112         tree->sreg1 = state->left->reg1;
113         tree->sreg2 = state->left->reg2;
114         tree->dreg = ARMREG_R0;
115         mono_bblock_add_inst (s->cbb, tree);
116 }
117
118 stmt: OP_SETRET (freg) {
119         if (SOFT_FLOAT_IMPL) {
120                 tree->opcode = OP_SETLRET;
121                 tree->sreg1 = state->left->reg1;
122                 tree->sreg2 = state->left->reg2;
123                 tree->dreg = ARMREG_R0;
124                 mono_bblock_add_inst (s->cbb, tree);
125         } else {
126                 tree->opcode = OP_FMOVE;
127                 tree->sreg1 = state->left->reg1;
128                 tree->dreg = 0;
129                 mono_bblock_add_inst (s->cbb, tree);
130         }
131 }
132
133 stmt: OP_SETRET (OP_ICONST) {
134         tree->opcode = OP_ICONST;
135         tree->inst_c0 = state->left->tree->inst_c0;
136         tree->dreg = ARMREG_R0;
137         mono_bblock_add_inst (s->cbb, tree);
138 }
139
140 stmt: CEE_STIND_I (OP_REGVAR, CEE_SUB (CEE_LDIND_I (OP_REGVAR), OP_ICONST)),
141 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)),
142 stmt: CEE_STIND_I (OP_REGVAR, CEE_ADD (CEE_LDIND_I (OP_REGVAR), OP_ICONST)),
143 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST)) {
144         int con = state->right->right->tree->inst_c0;
145         int dreg = state->left->tree->dreg;
146         int sreg = state->right->left->left->tree->dreg;
147
148         if (state->right->op == CEE_ADD)
149                 tree->opcode = OP_ADD_IMM;
150         else if (state->right->op == CEE_SUB)
151                 tree->opcode = OP_SUB_IMM;
152         else
153                 g_assert_not_reached ();
154         tree->inst_imm = con;
155         tree->sreg1 = sreg;
156         tree->dreg = dreg;
157         mono_bblock_add_inst (s->cbb, tree);
158 }
159
160 stmt: OP_OUTARG (reg) {
161         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
162
163         tree->opcode = OP_MOVE;
164         tree->dreg = mono_regstate_next_int (s->rs);
165         tree->sreg1 = state->left->reg1;
166         mono_bblock_add_inst (s->cbb, tree);
167
168         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
169 }
170
171 stmt: OP_OUTARG (OP_REGVAR) {
172         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
173         tree->opcode = OP_MOVE;
174         tree->dreg = mono_regstate_next_int (s->rs);
175         tree->sreg1 = state->left->tree->dreg;
176         mono_bblock_add_inst (s->cbb, tree);
177
178         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
179 }
180
181 stmt: OP_OUTARG (lreg) {
182         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
183         int tdreg;
184         tdreg = mono_regstate_next_int (s->rs);
185         MONO_EMIT_NEW_UNALU (s, OP_MOVE, tdreg, state->left->reg2);
186         
187         /* An #if would be better here, but monoburg
188            strips them out as comments */
189         if (G_BYTE_ORDER == G_BIG_ENDIAN)
190                 mono_call_inst_add_outarg_reg (s, call, tdreg, tree->backend.reg3, FALSE);
191         else
192                 mono_call_inst_add_outarg_reg (s, call, tdreg, tree->backend.reg3 + 1, FALSE);
193
194         tree->opcode = OP_MOVE;
195         tree->dreg = mono_regstate_next_int (s->rs);
196         tree->sreg1 = state->left->reg1;
197         mono_bblock_add_inst (s->cbb, tree);
198         
199         if (G_BYTE_ORDER == G_BIG_ENDIAN)
200                 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3 + 1, FALSE);
201         else
202                 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
203 }
204
205 stmt: OP_OUTARG (OP_ICONST) {
206         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
207         tree->opcode = OP_ICONST;
208         tree->dreg = mono_regstate_next_int (s->rs);
209         tree->inst_c0 = state->left->tree->inst_c0;
210         mono_bblock_add_inst (s->cbb, tree);
211
212         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
213 }
214
215 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
216         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
217         tree->opcode = OP_MOVE;
218         tree->sreg1 = state->left->left->tree->dreg;
219         tree->dreg = mono_regstate_next_int (s->rs);
220         mono_bblock_add_inst (s->cbb, tree);
221
222         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
223 }
224
225 stmt: OP_OUTARG_R8 (freg),
226 stmt: OP_OUTARG (freg) {
227         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
228         int creg;
229         if (SOFT_FLOAT_IMPL) {
230                 /* same as the OUTARG (lreg) case */
231                 int tdreg;
232                 tdreg = mono_regstate_next_int (s->rs);
233                 MONO_EMIT_NEW_UNALU (s, OP_MOVE, tdreg, state->left->reg2);
234         
235                 /* An #if would be better here, but monoburg
236                    strips them out as comments */
237                 if (G_BYTE_ORDER == G_BIG_ENDIAN)
238                         mono_call_inst_add_outarg_reg (s, call, tdreg, tree->backend.reg3, FALSE);
239                 else
240                         mono_call_inst_add_outarg_reg (s, call, tdreg, tree->backend.reg3 + 1, FALSE);
241
242                 tree->opcode = OP_MOVE;
243                 tree->dreg = mono_regstate_next_int (s->rs);
244                 tree->sreg1 = state->left->reg1;
245                 mono_bblock_add_inst (s->cbb, tree);
246         
247                 if (G_BYTE_ORDER == G_BIG_ENDIAN)
248                         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3 + 1, FALSE);
249                 else
250                         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
251         } else {
252                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, ARMREG_SP, (s->param_area - 8), state->left->reg1);
253                 creg = mono_regstate_next_int (s->rs);
254                 mono_call_inst_add_outarg_reg (s, call, creg, tree->backend.reg3, FALSE);
255                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 8));
256                 creg = mono_regstate_next_int (s->rs);
257                 mono_call_inst_add_outarg_reg (s, call, creg, tree->backend.reg3 + 1, FALSE);
258                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 8 + 4));
259         }
260 }
261
262 stmt: OP_OUTARG_R4 (freg) {
263         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
264         int creg;
265         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, ARMREG_SP, (s->param_area - 8), state->left->reg1);
266         creg = mono_regstate_next_int (s->rs);
267         mono_call_inst_add_outarg_reg (s, call, creg, tree->backend.reg3, FALSE);
268         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 8));
269 }
270
271 stmt: OP_OUTARG_MEMBASE (reg) {
272         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, tree->backend.arg_info >> 8, state->left->reg1);
273 }
274
275 stmt: OP_OUTARG_MEMBASE (lreg) {
276         int offset = tree->backend.arg_info >> 8;
277         int partial = (tree->backend.arg_info & 0xff) == 0xff;
278         if (partial) {
279                 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
280                 if (G_BYTE_ORDER == G_BIG_ENDIAN) {
281                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1);
282                 } else {
283                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg2);
284                 }
285                 tree->opcode = OP_MOVE;
286                 tree->dreg = mono_regstate_next_int (s->rs);
287                 tree->sreg1 = G_BYTE_ORDER == G_BIG_ENDIAN? state->left->reg2: state->left->reg1;
288                 mono_bblock_add_inst (s->cbb, tree);
289                 mono_call_inst_add_outarg_reg (s, call, tree->dreg, ARMREG_R3, FALSE);
290                 return;
291         }
292         if (G_BYTE_ORDER == G_BIG_ENDIAN) {
293                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg2);
294                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset + 4, state->left->reg1);
295         } else {
296                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1);
297                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset + 4, state->left->reg2);
298         }
299 }
300
301 stmt: OP_OUTARG_MEMBASE (freg) {
302         int offset = tree->backend.arg_info >> 8;
303         if (SOFT_FLOAT_IMPL) {
304                 int partial = (tree->backend.arg_info & 0xff) == 0xff;
305                 /* same as OP_OUTARG_MEMBASE (lreg) */
306                 if (G_BYTE_ORDER == G_BIG_ENDIAN) {
307                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg2);
308                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset + 4, state->left->reg1);
309                 } else {
310                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1);
311                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset + 4, state->left->reg2);
312                 }
313         } else {
314                 if ((tree->backend.arg_info & 0xff) == 8)
315                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1);
316                 else if ((tree->backend.arg_info & 0xff) == 4)
317                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1);
318                 else if ((tree->backend.arg_info & 0xff) == 0xff) {
319                         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
320                         int creg;
321                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, ARMREG_SP, (s->param_area - 8), state->left->reg1);
322                         creg = mono_regstate_next_int (s->rs);
323                         mono_call_inst_add_outarg_reg (s, call, creg, ARMREG_R3, FALSE);
324                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 8));
325                         creg = mono_regstate_next_int (s->rs);
326                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 4));
327                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, creg);
328                 } else
329                         g_assert_not_reached ();
330         }
331 }
332
333 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
334         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
335         MonoInst *vt = state->left->left->tree;
336         int start_reg = tree->backend.arg_info & 0xf;
337         int nregs = (tree->backend.arg_info >> 4) & 0xf;
338         int ovf_size = (tree->backend.arg_info >> 8) & 0xfff;
339         int doffset = ((tree->backend.arg_info >> 20) & 0xfff) * 4;
340         int i, tmpr, soffset, dreg;
341         int size = 0;
342         soffset = vt->inst_offset;
343
344         for (i = 0; i < nregs; ++i) {
345                 tmpr = mono_regstate_next_int (s->rs);
346                 dreg = mono_regstate_next_int (s->rs);
347                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg, soffset);
348                 MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, tmpr);
349                 mono_call_inst_add_outarg_reg (s, call, dreg, start_reg + i, FALSE);
350                 soffset += sizeof (gpointer);
351         }
352         //g_print ("vt size: %d at R%d + %d\n", doffset, vt->inst_basereg, vt->inst_offset);
353         if (ovf_size != 0) {
354                 mini_emit_memcpy (s, ARMREG_SP, doffset, vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0);
355         }
356 }
357
358 stmt: OP_OUTARG_VT (OP_ICONST) {
359         int nregs = (tree->backend.arg_info >> 4) & 0xf;
360         if (nregs) {
361                 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
362                 tree->opcode = OP_ICONST;
363                 tree->dreg = mono_regstate_next_int (s->rs);
364                 tree->inst_c0 = state->left->tree->inst_c0;
365                 mono_bblock_add_inst (s->cbb, tree);
366
367                 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.arg_info & 0xf, FALSE);
368         } else {
369                 g_assert_not_reached ();
370         }
371 }
372
373 stmt: OP_OUTARG_VT (reg) {
374         int start_reg = tree->backend.arg_info & 0xff;
375         int nregs = (tree->backend.arg_info >> 8) & 0xff;
376         if (nregs) {
377                 tree->opcode = OP_MOVE;
378                 tree->dreg = start_reg;
379                 tree->sreg1 = state->left->reg1;
380                 mono_bblock_add_inst (s->cbb, tree);
381         } else {
382                 g_assert_not_reached ();
383         }
384 }
385
386 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
387         /* nothing to do: the value is already on the FP stack */
388 }
389
390 stmt: CEE_BNE_UN (OP_COMPARE (freg, freg)) {
391         MONO_EMIT_BIALU (s, tree, OP_FBNE_UN, -1, state->left->left->reg1, state->left->right->reg1);
392 }
393
394 stmt: CEE_BEQ (OP_COMPARE (freg, freg)) {
395         MONO_EMIT_BIALU (s, tree, OP_FBEQ, -1, state->left->left->reg1, state->left->right->reg1);
396 }
397
398 stmt: CEE_BLT (OP_COMPARE (freg, freg)) {
399         MONO_EMIT_BIALU (s, tree, OP_FBLT, -1, state->left->left->reg1, state->left->right->reg1);
400 }
401
402 stmt: CEE_BLT_UN (OP_COMPARE (freg, freg)) {
403         MONO_EMIT_BIALU (s, tree, OP_FBLT_UN, -1, state->left->left->reg1, state->left->right->reg1);
404 }
405
406 stmt: CEE_BGT (OP_COMPARE (freg, freg)) {
407         MONO_EMIT_BIALU (s, tree, OP_FBGT, -1, state->left->left->reg1, state->left->right->reg1);
408 }
409
410 stmt: CEE_BGT_UN (OP_COMPARE (freg, freg)) {
411         MONO_EMIT_BIALU (s, tree, OP_FBGT_UN, -1, state->left->left->reg1, state->left->right->reg1);
412 }
413
414 stmt: CEE_BGE  (OP_COMPARE (freg, freg)) {
415         MONO_EMIT_BIALU (s, tree, OP_FBGE, -1, state->left->left->reg1, state->left->right->reg1);
416 }
417
418 stmt: CEE_BGE_UN (OP_COMPARE (freg, freg)) {
419         MONO_EMIT_BIALU (s, tree, OP_FBGE_UN, -1, state->left->left->reg1, state->left->right->reg1);
420 }
421
422 stmt: CEE_BLE  (OP_COMPARE (freg, freg)) {
423         MONO_EMIT_BIALU (s, tree, OP_FBLE, -1, state->left->left->reg1, state->left->right->reg1);
424 }
425
426 stmt: CEE_BLE_UN (OP_COMPARE (freg, freg)) {
427         MONO_EMIT_BIALU (s, tree, OP_FBLE_UN, -1, state->left->left->reg1, state->left->right->reg1);
428 }
429
430 stmt: CEE_POP (freg) "0" {
431         /* nothing to do */
432 }     
433
434 freg: OP_LCONV_TO_R8 (lreg) {
435         /* nothing to do - emulated */
436 }
437
438 freg: OP_LCONV_TO_R4 (lreg) {
439         /* nothing to do - emulated */
440 }
441
442 freg: OP_LCONV_TO_R_UN (lreg) {
443         /* nothing to do - emulated */
444 }
445
446 freg: OP_FREM (freg, freg) {
447         /* nothing to do - emulated */
448 }
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 reg: CEE_ADD_OVF (reg, reg) "0" {
476         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
477 }
478
479 reg: CEE_ADD_OVF_UN (reg, reg) "0" {
480         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
481 }
482
483 reg: CEE_SUB_OVF (reg, reg) "0" {
484         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
485 }
486
487 reg: CEE_SUB_OVF_UN (reg, reg) "0" {
488         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
489 }
490
491 stmt: OP_SWITCH (reg) {
492         MonoInst *label;
493         int n = GPOINTER_TO_INT (tree->klass);
494         
495         MONO_NEW_LABEL (s, label);
496
497         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, n);
498         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_many_bb [n]);
499
500         if (s->compile_aot) {
501                 /* FIXME: Optimize this */
502                 int offset_reg = mono_regstate_next_int (s->rs);
503                 int target_reg = mono_regstate_next_int (s->rs);
504                 int table_reg = mono_regstate_next_int (s->rs);
505                 int sum_reg = mono_regstate_next_int (s->rs);
506                 MonoJumpInfoBBTable *table;
507
508                 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, offset_reg, state->left->reg1, 2);
509
510                 table = mono_mempool_alloc (s->mempool, sizeof (MonoJumpInfoBBTable));
511                 table->table = tree->inst_many_bb;
512                 table->table_size = n;
513
514                 MONO_EMIT_NEW_AOTCONST (s, table_reg, table, MONO_PATCH_INFO_SWITCH);
515
516                 MONO_EMIT_NEW_BIALU (s, CEE_ADD, sum_reg, table_reg, offset_reg);
517                 MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, sum_reg, 0);
518                 MONO_EMIT_UNALU (s, tree, OP_BR_REG, -1, target_reg);
519         } else {
520                 mono_bblock_add_inst (s->cbb, label);
521                 mono_create_jump_table (s, label, tree->inst_many_bb, n);
522                 /* the backend code will deal with aot vs normal case */
523                 tree->sreg1 = state->left->reg1;
524                 mono_bblock_add_inst (s->cbb, tree);
525         }
526 }
527
528 %%