e1b5c304f0f4c65c63a7cf98a20fa3292638d47d
[mono.git] / mono / mini / inssel-long32.brg
1 %%
2
3 #
4 # inssel-long32.brg: burg file for 64bit instructions on 32bit architectures
5 #
6 # Author:
7 #   Dietmar Maurer (dietmar@ximian.com)
8 #
9 # (C) 2002 Ximian, Inc.
10 #
11
12 #
13 # We use a new non-terminal called "lreg" for 64bit registers, and
14 # emulate lreg with 2 32bit registers.
15 #
16
17 stmt: CEE_POP (lreg) {
18         /* do nothing */
19 }
20
21 i8con: CEE_CONV_I8 (OP_ICONST) "0" {
22        int data = state->left->tree->inst_c0;
23         tree->opcode = OP_I8CONST;
24         tree->inst_c0 = data;
25         if (data < 0)
26                 tree->inst_c1 = -1;
27         else
28                 tree->inst_c1 = 0;
29 }
30
31 i8con: CEE_CONV_U8 (OP_ICONST) "0" {
32         int data = state->left->tree->inst_c0;
33         tree->opcode = OP_I8CONST;
34         tree->inst_c0 = data;
35         tree->inst_c1 = 0;
36 }
37
38 i8con: OP_I8CONST "0"
39
40 lreg: OP_ICONST {
41        int data = state->tree->inst_c0;
42
43        MONO_EMIT_NEW_ICONST (s, state->reg1, data);
44
45        if (data >= 0)
46                MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
47        else 
48                MONO_EMIT_NEW_ICONST (s, state->reg2, -1);
49 }
50
51 lreg: OP_I8CONST {
52         MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_c0);
53         MONO_EMIT_NEW_ICONST (s, state->reg2, tree->inst_c1);
54 }
55
56 lreg: CEE_LDIND_I8 (base) {
57         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, 
58                                        state->left->tree->inst_basereg, state->left->tree->inst_offset);
59         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg2, 
60                                        state->left->tree->inst_basereg, state->left->tree->inst_offset + 4);
61 }
62
63 stmt: CEE_STIND_I8 (base, lreg) {
64         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
65                                      state->left->tree->inst_offset + 4, state->right->reg2);
66         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
67                                      state->left->tree->inst_offset, state->right->reg1);
68 }
69
70 stmt: CEE_STIND_I8 (base, i8con) {
71         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
72                                          state->left->tree->inst_offset + 4, state->right->tree->inst_c1);
73         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
74                                          state->left->tree->inst_offset, state->right->tree->inst_c0);
75 }
76
77
78 lreg: OP_LADD (lreg, lreg) {
79         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
80         MONO_EMIT_BIALU (s, tree, OP_ADC, state->reg2, state->left->reg2, state->right->reg2);
81 }
82
83 lreg: OP_LADD_OVF (lreg, lreg) {
84         /* ADC sets the condition code */
85         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
86         MONO_EMIT_NEW_BIALU (s, OP_ADC, state->reg2, state->left->reg2, state->right->reg2);
87         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
88 }
89
90 lreg: OP_LADD_OVF_UN (lreg, lreg) {
91         /* ADC sets the condition code */
92         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
93         MONO_EMIT_NEW_BIALU (s, OP_ADC, state->reg2, state->left->reg2, state->right->reg2);
94         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
95 }
96
97 lreg: OP_LADD (lreg, i8con) {
98         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
99         MONO_EMIT_BIALU_IMM (s, tree, OP_ADC_IMM, state->reg2, state->left->reg2, state->right->tree->inst_c1);
100 }
101
102 lreg: OP_LSUB (lreg, lreg) {
103         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
104         MONO_EMIT_BIALU (s, tree, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
105 }
106
107 lreg: OP_LSUB (lreg, i8con) {
108         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
109         MONO_EMIT_BIALU_IMM (s, tree, OP_SBB_IMM, state->reg2, state->left->reg2, state->right->tree->inst_c1);
110 }
111
112 lreg: OP_LSUB_OVF (lreg, lreg) {
113         /* SBB sets the condition code */
114         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
115         MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
116         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
117 }
118
119 lreg: OP_LSUB_OVF_UN (lreg, lreg) {
120         /* SBB sets the condition code */
121         MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1);
122         MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
123         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
124 }
125
126 lreg: OP_LAND (lreg, lreg) {    
127         MONO_EMIT_NEW_BIALU (s, CEE_AND, state->reg1, state->left->reg1, state->right->reg1);
128         MONO_EMIT_BIALU (s, tree, CEE_AND, state->reg2, state->left->reg2, state->right->reg2);
129 }
130
131 lreg: OP_LAND (lreg, i8con) {   
132         MONO_EMIT_NEW_BIALU_IMM (s, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
133         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg2, state->left->reg2, state->right->tree->inst_c1);
134 }
135
136 lreg: OP_LOR (lreg, lreg) {
137         MONO_EMIT_NEW_BIALU (s, CEE_OR, state->reg1, state->left->reg1, state->right->reg1);
138         MONO_EMIT_BIALU (s, tree, CEE_OR, state->reg2, state->left->reg2, state->right->reg2);
139 }
140
141 lreg: OP_LOR (lreg, i8con) {
142         MONO_EMIT_NEW_BIALU_IMM (s, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
143         MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg2, state->left->reg2, state->right->tree->inst_c1);
144 }
145
146 lreg: OP_LXOR (lreg, lreg) {
147         MONO_EMIT_NEW_BIALU (s, CEE_XOR, state->reg1, state->left->reg1, state->right->reg1);
148         MONO_EMIT_BIALU (s, tree, CEE_XOR, state->reg2, state->left->reg2, state->right->reg2);
149 }
150
151 lreg: OP_LXOR (lreg, i8con) {
152         MONO_EMIT_NEW_BIALU_IMM (s, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
153         MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg2, state->left->reg2, state->right->tree->inst_c1);
154 }
155
156 lreg: OP_LNOT (lreg) {
157         MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg1, state->left->reg1);
158         MONO_EMIT_UNALU (s, tree, CEE_NOT, state->reg2, state->left->reg2);
159 }
160
161 lreg: OP_LNEG (lreg) "4" {
162         MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg1, state->left->reg1);
163         MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg2, state->left->reg2);
164         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1, 1);
165         MONO_EMIT_BIALU_IMM (s, tree, OP_ADC_IMM, state->reg2, state->reg2, 0);
166 }
167
168 reg: OP_CEQ (OP_COMPARE (lreg, lreg)) { 
169         MonoInst *word_differs;
170         
171         MONO_NEW_LABEL (s, word_differs);
172
173         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
174         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
175         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, word_differs);
176         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
177         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, word_differs);
178         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
179         
180         mono_bblock_add_inst (s->cbb, word_differs);
181 }
182
183 reg: OP_CLT (OP_COMPARE (lreg, lreg)) { 
184         MonoInst *set_to_0, *set_to_1;
185         
186         MONO_NEW_LABEL (s, set_to_0);
187         MONO_NEW_LABEL (s, set_to_1);
188
189         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
190         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
191         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT, set_to_0);
192         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
193         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
194         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
195         mono_bblock_add_inst (s->cbb, set_to_1);
196         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
197         mono_bblock_add_inst (s->cbb, set_to_0);
198 }       
199
200 reg: OP_CLT_UN (OP_COMPARE (lreg, lreg)) {      
201         MonoInst *set_to_0, *set_to_1;
202         
203         MONO_NEW_LABEL (s, set_to_0);
204         MONO_NEW_LABEL (s, set_to_1);
205
206         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
207         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
208         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT_UN, set_to_0);
209         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
210         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
211         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
212         mono_bblock_add_inst (s->cbb, set_to_1);
213         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
214         mono_bblock_add_inst (s->cbb, set_to_0);
215 }       
216
217 reg: OP_CGT (OP_COMPARE (lreg, lreg)) { 
218         MonoInst *set_to_0, *set_to_1;
219         
220         MONO_NEW_LABEL (s, set_to_0);
221         MONO_NEW_LABEL (s, set_to_1);
222
223         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
224         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg2, state->left->left->reg2);
225         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT, set_to_0);
226         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
227         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg1, state->left->left->reg1);
228         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
229         mono_bblock_add_inst (s->cbb, set_to_1);
230         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
231         mono_bblock_add_inst (s->cbb, set_to_0);
232 }       
233
234 reg: OP_CGT_UN (OP_COMPARE (lreg, lreg)) {      
235         MonoInst *set_to_0, *set_to_1;
236         
237         MONO_NEW_LABEL (s, set_to_0);
238         MONO_NEW_LABEL (s, set_to_1);
239
240         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
241         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg2, state->left->left->reg2);
242         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT_UN, set_to_0);
243         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
244         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg1, state->left->left->reg1);
245         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
246         mono_bblock_add_inst (s->cbb, set_to_1);
247         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
248         mono_bblock_add_inst (s->cbb, set_to_0);
249 }       
250
251 stmt: CEE_BNE_UN (OP_COMPARE (lreg, lreg)) {
252         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
253         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_true_bb);
254         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
255         mono_bblock_add_inst (s->cbb, tree);
256 }
257
258 stmt: CEE_BNE_UN (OP_COMPARE (lreg, i8con)) {
259         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
260         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_true_bb);
261         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
262         mono_bblock_add_inst (s->cbb, tree);
263 }
264
265 stmt: CEE_BEQ (OP_COMPARE (lreg, lreg)) {
266         
267         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
268         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
269         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
270         mono_bblock_add_inst (s->cbb, tree);
271 }
272
273 stmt: CEE_BEQ (OP_COMPARE (lreg, i8con)) {
274         
275         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
276         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
277         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
278         mono_bblock_add_inst (s->cbb, tree);
279 }
280
281 stmt: CEE_BLE (OP_COMPARE (lreg, lreg)) {
282
283         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
284         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
285         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
286         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
287         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
288 }
289
290 stmt: CEE_BLE (OP_COMPARE (lreg, i8con)) {
291
292         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
293         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
294         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
295         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
296         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
297 }
298
299 stmt: CEE_BLE_UN (OP_COMPARE (lreg, lreg)) {
300
301         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
302         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
303         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
304         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
305         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
306 }
307
308 stmt: CEE_BLE_UN (OP_COMPARE (lreg, i8con)) {
309
310         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
311         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
312         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
313         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
314         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
315 }
316
317 stmt: CEE_BGE (OP_COMPARE (lreg, lreg)) {
318
319         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
320         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
321         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
322         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
323         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
324 }
325
326 stmt: CEE_BGE (OP_COMPARE (lreg, i8con)) {
327
328         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
329         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
330         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
331         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
332         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
333 }
334
335 stmt: CEE_BGE_UN (OP_COMPARE (lreg, lreg)) {
336
337         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
338         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
339         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
340         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
341         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
342 }
343
344 stmt: CEE_BGE_UN (OP_COMPARE (lreg, i8con)) {
345
346         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
347         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
348         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
349         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
350         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
351 }
352
353 stmt: CEE_BLT (OP_COMPARE (lreg, lreg)) {
354
355         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
356         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
357         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
358         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
359         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
360 }
361
362 stmt: CEE_BLT (OP_COMPARE (lreg, i8con)) {
363
364         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
365         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
366         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
367         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
368         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
369 }
370
371 stmt: CEE_BLT_UN (OP_COMPARE (lreg, lreg)) {
372
373         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
374         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
375         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
376         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
377         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
378 }
379
380 stmt: CEE_BLT_UN (OP_COMPARE (lreg, i8con)) {
381
382         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
383         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
384         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
385         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
386         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
387 }
388
389 stmt: CEE_BGT (OP_COMPARE (lreg, lreg)) {
390
391         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
392         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
393         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
394         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
395         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
396 }
397
398 stmt: CEE_BGT (OP_COMPARE (lreg, i8con)) {
399
400         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
401         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
402         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
403         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
404         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
405 }
406
407 stmt: CEE_BGT_UN (OP_COMPARE (lreg, lreg)) {
408
409         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
410         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
411         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
412         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
413         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
414 }
415
416 stmt: CEE_BGT_UN (OP_COMPARE (lreg, i8con)) {
417
418         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_c1);
419         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
420         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
421         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_c0);
422         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
423 }
424
425 lreg: CEE_CONV_I8 (OP_ICONST) {
426         int data = state->left->tree->inst_c0;
427
428        MONO_EMIT_NEW_ICONST (s, state->reg1, data);
429
430        if (data >= 0)
431                MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
432        else 
433                MONO_EMIT_NEW_ICONST (s, state->reg2, -1);
434 }
435
436 lreg: CEE_CONV_I8 (reg) {
437         MonoInst *is_negative, *end_label;
438         int tmpreg = mono_regstate_next_int (s->rs);
439         
440         MONO_NEW_LABEL (s, is_negative);
441         MONO_NEW_LABEL (s, end_label);
442
443         /* branchless code:
444          * low = reg;
445          * tmp = low > -1 ? 1: 0;
446          * high = tmp - 1; if low is zero or pos high becomes 0, else -1
447          * not sure why it doesn't work in practice
448          */
449         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
450         /*MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->reg1, -1);
451         tree->dreg = tmpreg;
452         tree->opcode = OP_CGT;
453         mono_bblock_add_inst (s->cbb, tree);
454         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, tmpreg, -1);*/
455         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->reg1, 0);
456         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative);
457         MONO_EMIT_NEW_ICONST (s, tmpreg, 0);
458         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
459         mono_bblock_add_inst (s->cbb, is_negative);
460         MONO_EMIT_NEW_ICONST (s, tmpreg, -1);
461         mono_bblock_add_inst (s->cbb, end_label);
462         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, tmpreg);
463 }
464
465 lreg: CEE_CONV_U8 (reg) {
466         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
467         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
468 }
469
470 lreg: CEE_CONV_OVF_U8 (reg) {
471         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
472         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
473         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
474         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
475 }
476
477 lreg: CEE_CONV_OVF_I8_UN (reg) {
478         /* an unsigned 32 bit num always fits in a signed 64 bit one */
479         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
480         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
481 }
482
483 lreg: CEE_CONV_OVF_U8_UN (reg) {
484         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
485         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
486 }
487
488 freg: OP_LCONV_TO_R_UN (lreg) {
489         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->left->reg2);
490 }
491
492 lreg: OP_FCONV_TO_I8 (freg) {
493         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
494 }
495
496 lreg: OP_FCONV_TO_U8 (freg) {
497         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
498 }
499
500 reg: OP_LCONV_TO_I4 (i8con) {
501         MONO_EMIT_NEW_ICONST (s, state->reg1, state->left->tree->inst_c0);
502 }
503
504 reg: OP_LCONV_TO_I4 (lreg) {
505         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
506 }
507
508 reg: OP_LCONV_TO_U4 (lreg) {
509         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
510 }
511
512 lreg: OP_LCONV_TO_U8 (lreg) {
513         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
514         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
515 }
516
517 lreg: OP_LCONV_TO_I8 (lreg) {
518         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
519         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
520 }
521
522 reg: OP_LCONV_TO_U (lreg) {
523         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
524 }
525
526 reg: OP_LCONV_TO_I (lreg) {
527         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
528 }
529
530 reg: OP_LCONV_TO_I1 (lreg) {
531         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
532 }
533
534 reg: OP_LCONV_TO_U1 (lreg) {
535         MONO_EMIT_UNALU (s, tree, CEE_CONV_U1, state->reg1, state->left->reg1);
536 }
537
538 reg: OP_LCONV_TO_I2 (lreg) {
539         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
540 }
541
542 reg: OP_LCONV_TO_U2 (lreg) {
543         MONO_EMIT_UNALU (s, tree, CEE_CONV_U2, state->reg1, state->left->reg1);
544 }
545
546 reg: OP_LCONV_TO_OVF_I1 (lreg) {
547         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
548         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
549         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
550         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
551
552         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
553         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
554         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
555         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
556         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
557 }
558
559 reg: OP_LCONV_TO_OVF_U1 (lreg) {
560         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
561         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
562
563         /* probe value to be within 0 to 255 */
564         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
565         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
566         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
567 }
568
569 reg: OP_LCONV_TO_OVF_I2 (lreg) {
570         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
571         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
572         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
573         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
574
575         /* Probe value to be within -32768 and 32767 */
576         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
577         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
578         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
579         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
580         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
581 }
582
583 reg: OP_LCONV_TO_OVF_U2 (lreg) {
584         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
585         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
586
587         /* Probe value to be within 0 and 65535 */
588         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
589         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
590         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
591 }
592
593
594 reg: OP_LCONV_TO_OVF_U4_UN (lreg) {
595         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
596         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
597         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
598 }
599
600 reg: OP_LCONV_TO_OVF_I_UN (lreg) {
601         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
602         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
603         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
604 }
605
606 reg: OP_LCONV_TO_OVF_U4 (lreg) {
607         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
608         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
609         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
610 }
611
612 reg: OP_LCONV_TO_OVF_I (lreg) {
613         tree->dreg = state->reg1;
614         tree->sreg1 = state->left->reg1;
615         tree->sreg2 = state->left->reg2;
616         mono_bblock_add_inst (s->cbb, tree);
617 }
618
619 reg: OP_LCONV_TO_OVF_I4 (lreg) {
620         tree->dreg = state->reg1;
621         tree->sreg1 = state->left->reg1;
622         tree->sreg2 = state->left->reg2;
623         tree->opcode = OP_LCONV_TO_OVF_I;
624         mono_bblock_add_inst (s->cbb, tree);
625 }
626
627 lreg: OP_LCONV_TO_OVF_I8_UN (lreg) {
628         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
629         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
630
631         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
632         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
633 }
634
635 lreg: OP_LCONV_TO_OVF_U8 (lreg) {
636         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
637         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
638
639         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
640         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
641 }
642
643 %%