2004-10-08 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / mini / inssel-long32.brg
1 %%
2
3 #
4 # inssel-long32.brg: burg file for integer instructions on 32bit architectures
5 #
6 # Author:
7 #   Dietmar Maurer (dietmar@ximian.com)
8 #
9 # (C) 2002 Ximian, Inc.
10 #
11
12 #
13 # 32 bit rules
14 #
15
16 #
17 # basic alu operations
18 #
19
20 reg: CEE_AND (reg, reg),
21 reg: CEE_OR (reg, reg),
22 reg: CEE_XOR (reg, reg),
23 reg: CEE_ADD (reg, reg),
24 reg: CEE_SUB (reg, reg),
25 reg: CEE_MUL (reg, reg),
26 reg: CEE_MUL_OVF (reg, reg),
27 reg: CEE_MUL_OVF_UN (reg, reg),
28 reg: CEE_DIV (reg, reg),
29 reg: CEE_DIV_UN (reg, reg),
30 reg: CEE_REM (reg, reg),
31 reg: CEE_REM_UN (reg, reg),
32 reg: CEE_SHL (reg, reg),
33 reg: CEE_SHR (reg, reg),
34 reg: CEE_SHR_UN (reg, reg) {
35         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
36 }
37
38 reg: CEE_NEG (reg),
39 reg: CEE_NOT (reg) {
40         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
41 }
42
43
44 reg: CEE_AND (reg, OP_ICONST) {
45         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
46 }
47
48 reg: CEE_OR (reg, OP_ICONST) {
49         MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
50 }
51
52 reg: CEE_XOR (reg, OP_ICONST) {
53         MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
54 }
55
56 reg: CEE_ADD (reg, OP_ICONST) {
57         MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
58 }
59
60 reg: CEE_SUB (reg, OP_ICONST) {
61         MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
62 }
63
64 reg: CEE_MUL (reg, OP_ICONST) {
65         MONO_EMIT_BIALU_IMM (s, tree, OP_MUL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
66 }
67
68 reg: CEE_SHL (reg, OP_ICONST) {
69         MONO_EMIT_BIALU_IMM (s, tree, OP_SHL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
70 }
71
72 reg: CEE_SHR (reg, OP_ICONST) {
73         MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
74 }
75
76 reg: CEE_SHR_UN (reg, OP_ICONST) {
77         MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
78 }
79
80 reg: CEE_ADD_OVF (reg, reg) {
81         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
82         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
83 }
84
85 reg: CEE_ADD_OVF_UN (reg, reg) {
86         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
87         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
88 }
89
90 reg: CEE_SUB (reg, CEE_LDIND_I4 (OP_REGVAR)) {
91         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->left->tree->dreg);
92 }
93
94 reg: CEE_SUB_OVF (reg, reg) {
95         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
96         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
97 }
98
99 reg: CEE_SUB_OVF_UN (reg, reg) {
100         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
101         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
102 }
103
104 cflags: OP_COMPARE (reg, reg) {
105         tree->sreg1 = state->left->reg1;
106         tree->sreg2 = state->right->reg1;
107         mono_bblock_add_inst (s->cbb, tree);
108 }
109
110 cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), reg),
111 cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), reg),
112 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), reg),
113 cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), reg) {
114         tree->sreg1 = state->left->left->tree->dreg;
115         tree->sreg2 = state->right->reg1;
116         mono_bblock_add_inst (s->cbb, tree);
117 }
118
119 cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), CEE_LDIND_REF (OP_REGVAR)),
120 cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), CEE_LDIND_I (OP_REGVAR)),
121 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), CEE_LDIND_I4 (OP_REGVAR)),
122 cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), CEE_LDIND_U4 (OP_REGVAR)) {
123         tree->sreg1 = state->left->left->tree->dreg;
124         tree->sreg2 = state->right->left->tree->dreg;
125         mono_bblock_add_inst (s->cbb, tree);
126 }
127
128 cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), OP_ICONST),
129 cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), OP_ICONST),
130 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST),
131 cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), OP_ICONST) {
132         tree->opcode = OP_COMPARE_IMM;
133         tree->sreg1 = state->left->left->tree->dreg;
134         tree->inst_imm = state->right->tree->inst_c0;
135         mono_bblock_add_inst (s->cbb, tree);
136 }
137
138 cflags: OP_COMPARE (reg, OP_ICONST) {
139         tree->opcode = OP_COMPARE_IMM;
140         tree->sreg1 = state->left->reg1;
141         tree->inst_imm = state->right->tree->inst_c0;
142         mono_bblock_add_inst (s->cbb, tree);
143 }
144
145 stmt: CEE_BNE_UN (cflags),
146 stmt: CEE_BEQ (cflags),
147 stmt: CEE_BLT (cflags),
148 stmt: CEE_BLT_UN (cflags),
149 stmt: CEE_BGT (cflags),
150 stmt: CEE_BGT_UN (cflags),
151 stmt: CEE_BGE  (cflags),
152 stmt: CEE_BGE_UN (cflags),
153 stmt: CEE_BLE  (cflags),
154 stmt: CEE_BLE_UN (cflags) {
155         mono_bblock_add_inst (s->cbb, tree);
156 }
157
158 reg: OP_CEQ (cflags),
159 reg: OP_CLT (cflags),
160 reg: OP_CLT_UN (cflags),
161 reg: OP_CGT (cflags),
162 reg: OP_CGT_UN (cflags) {       
163         tree->dreg = state->reg1;
164         mono_bblock_add_inst (s->cbb, tree);
165 }
166
167 #
168 # 64 bit rules
169 #
170
171 #
172 # We use a new non-terminal called "lreg" for 64bit registers, and
173 # emulate lreg with 2 32bit registers.
174 #
175
176 stmt: CEE_POP (lreg) {
177         /* do nothing */
178 }
179
180 i8con: CEE_CONV_I8 (OP_ICONST) "0" {
181        int data = state->left->tree->inst_c0;
182         tree->opcode = OP_I8CONST;
183         tree->inst_ls_word = data;
184         if (data < 0)
185                 tree->inst_ms_word = -1;
186         else
187                 tree->inst_ms_word = 0;
188 }
189
190 i8con: CEE_CONV_U8 (OP_ICONST) "0" {
191         int data = state->left->tree->inst_c0;
192         tree->opcode = OP_I8CONST;
193         tree->inst_ls_word = data;
194         tree->inst_ms_word = 0;
195 }
196
197 i8con: OP_I8CONST "0"
198
199 lreg: OP_ICONST {
200        int data = state->tree->inst_c0;
201
202        MONO_EMIT_NEW_ICONST (s, state->reg1, data);
203
204        if (data >= 0)
205                MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
206        else 
207                MONO_EMIT_NEW_ICONST (s, state->reg2, -1);
208 }
209
210 lreg: OP_I8CONST {
211         MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_ls_word);
212         MONO_EMIT_NEW_ICONST (s, state->reg2, tree->inst_ms_word);
213 }
214
215 lreg: CEE_LDIND_I8 (base) {
216         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, 
217                                        state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_LS_WORD_OFFSET);
218         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg2, 
219                                        state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_MS_WORD_OFFSET);
220 }
221
222 stmt: CEE_STIND_I8 (base, lreg) {
223         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
224                                      state->left->tree->inst_offset + MINI_MS_WORD_OFFSET, state->right->reg2);
225         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
226                                      state->left->tree->inst_offset + MINI_LS_WORD_OFFSET, state->right->reg1);
227 }
228
229 stmt: CEE_STIND_I8 (base, i8con) {
230         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
231                                          state->left->tree->inst_offset + MINI_MS_WORD_OFFSET, state->right->tree->inst_ms_word);
232         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
233                                          state->left->tree->inst_offset + MINI_LS_WORD_OFFSET, state->right->tree->inst_ls_word);
234 }
235
236 lreg: OP_BIGMUL (reg, reg),
237 lreg: OP_BIGMUL_UN (reg, reg) {
238         MONO_EMIT_NEW_BIALU (s, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); 
239 }
240
241 lreg: OP_LONG_SHRUN_32 (lreg) {
242         /* just move the upper half to the lower and zero the high word */
243         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg2);
244         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
245 }
246
247 reg: OP_LCONV_TO_I4 (OP_LONG_SHRUN_32 (lreg)),
248 reg: OP_LCONV_TO_U4 (OP_LONG_SHRUN_32 (lreg)) {
249         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->left->reg2);
250 }
251
252
253 lreg: OP_LONG_SHRUN_32 (CEE_LDIND_I8 (base)) {
254         /* just move the upper half to the lower and zero the high word */
255         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, 
256                                        state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset + MINI_MS_WORD_OFFSET);
257         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
258 }
259
260 reg: OP_LCONV_TO_I4 (OP_LONG_SHRUN_32 (CEE_LDIND_I8 (base))),
261 reg: OP_LCONV_TO_U4 (OP_LONG_SHRUN_32 (CEE_LDIND_I8 (base))) {
262         /* just move the upper half to the lower and zero the high word */
263         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, 
264                                        state->left->left->left->tree->inst_basereg,
265                                        state->left->left->left->tree->inst_offset + MINI_MS_WORD_OFFSET);
266 }
267
268 lreg: OP_LADD (lreg, lreg) {
269         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
270         MONO_EMIT_BIALU (s, tree, OP_ADC, state->reg2, state->left->reg2, state->right->reg2);
271 }
272
273 lreg: OP_LADD_OVF (lreg, lreg) {
274         /* ADC sets the condition code */
275         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
276         MONO_EMIT_NEW_BIALU (s, OP_ADC, state->reg2, state->left->reg2, state->right->reg2);
277         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
278 }
279
280 lreg: OP_LADD_OVF_UN (lreg, lreg) {
281         /* ADC sets the condition code */
282         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
283         MONO_EMIT_NEW_BIALU (s, OP_ADC, state->reg2, state->left->reg2, state->right->reg2);
284         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
285 }
286
287 lreg: OP_LADD (lreg, i8con) {
288         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADDCC_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
289         MONO_EMIT_BIALU_IMM (s, tree, OP_ADC_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
290 }
291
292 lreg: OP_LSUB (lreg, lreg) {
293         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
294         MONO_EMIT_BIALU (s, tree, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
295 }
296
297 lreg: OP_LSUB (lreg, i8con) {
298         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUBCC_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
299         MONO_EMIT_BIALU_IMM (s, tree, OP_SBB_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
300 }
301
302 lreg: OP_LSUB_OVF (lreg, lreg) {
303         /* SBB sets the condition code */
304         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
305         MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
306         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
307 }
308
309 lreg: OP_LSUB_OVF_UN (lreg, lreg) {
310         /* SBB sets the condition code */
311         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
312         MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
313         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
314 }
315
316 lreg: OP_LAND (lreg, lreg) {    
317         MONO_EMIT_NEW_BIALU (s, CEE_AND, state->reg1, state->left->reg1, state->right->reg1);
318         MONO_EMIT_BIALU (s, tree, CEE_AND, state->reg2, state->left->reg2, state->right->reg2);
319 }
320
321 lreg: OP_LAND (lreg, i8con) {   
322         MONO_EMIT_NEW_BIALU_IMM (s, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
323         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
324 }
325
326 lreg: OP_LOR (lreg, lreg) {
327         MONO_EMIT_NEW_BIALU (s, CEE_OR, state->reg1, state->left->reg1, state->right->reg1);
328         MONO_EMIT_BIALU (s, tree, CEE_OR, state->reg2, state->left->reg2, state->right->reg2);
329 }
330
331 lreg: OP_LOR (lreg, i8con) {
332         MONO_EMIT_NEW_BIALU_IMM (s, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
333         MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
334 }
335
336 lreg: OP_LXOR (lreg, lreg) {
337         MONO_EMIT_NEW_BIALU (s, CEE_XOR, state->reg1, state->left->reg1, state->right->reg1);
338         MONO_EMIT_BIALU (s, tree, CEE_XOR, state->reg2, state->left->reg2, state->right->reg2);
339 }
340
341 lreg: OP_LXOR (lreg, i8con) {
342         MONO_EMIT_NEW_BIALU_IMM (s, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word);
343         MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word);
344 }
345
346 lreg: OP_LNOT (lreg) {
347         MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg1, state->left->reg1);
348         MONO_EMIT_UNALU (s, tree, CEE_NOT, state->reg2, state->left->reg2);
349 }
350
351 lreg: OP_LNEG (lreg) "4" {
352         MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg1, state->left->reg1);
353         MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg2, state->left->reg2);
354         /* ADC sets the condition codes */
355         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADC_IMM, state->reg1, state->reg1, 1);
356         MONO_EMIT_BIALU_IMM (s, tree, OP_ADC_IMM, state->reg2, state->reg2, 0);
357 }
358
359 reg: OP_CEQ (OP_LCOMPARE (lreg, lreg)) {        
360         MonoInst *word_differs;
361         
362         MONO_NEW_LABEL (s, word_differs);
363
364         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
365         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
366         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, word_differs);
367         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
368         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, word_differs);
369         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
370         
371         mono_bblock_add_inst (s->cbb, word_differs);
372 }
373
374 reg: OP_CLT (OP_LCOMPARE (lreg, lreg)) {        
375         MonoInst *set_to_0, *set_to_1;
376         
377         MONO_NEW_LABEL (s, set_to_0);
378         MONO_NEW_LABEL (s, set_to_1);
379
380         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
381         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
382         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT, set_to_0);
383         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
384         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
385         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
386         mono_bblock_add_inst (s->cbb, set_to_1);
387         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
388         mono_bblock_add_inst (s->cbb, set_to_0);
389 }       
390
391 reg: OP_CLT_UN (OP_LCOMPARE (lreg, lreg)) {     
392         MonoInst *set_to_0, *set_to_1;
393         
394         MONO_NEW_LABEL (s, set_to_0);
395         MONO_NEW_LABEL (s, set_to_1);
396
397         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
398         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
399         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT_UN, set_to_0);
400         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
401         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
402         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
403         mono_bblock_add_inst (s->cbb, set_to_1);
404         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
405         mono_bblock_add_inst (s->cbb, set_to_0);
406 }       
407
408 reg: OP_CGT (OP_LCOMPARE (lreg, lreg)) {        
409         MonoInst *set_to_0, *set_to_1;
410         
411         MONO_NEW_LABEL (s, set_to_0);
412         MONO_NEW_LABEL (s, set_to_1);
413
414         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
415         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg2, state->left->left->reg2);
416         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT, set_to_0);
417         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
418         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg1, state->left->left->reg1);
419         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
420         mono_bblock_add_inst (s->cbb, set_to_1);
421         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
422         mono_bblock_add_inst (s->cbb, set_to_0);
423 }       
424
425 reg: OP_CGT_UN (OP_LCOMPARE (lreg, lreg)) {     
426         MonoInst *set_to_0, *set_to_1;
427         
428         MONO_NEW_LABEL (s, set_to_0);
429         MONO_NEW_LABEL (s, set_to_1);
430
431         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
432         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg2, state->left->left->reg2);
433         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGT_UN, set_to_0);
434         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, set_to_1);
435         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->right->reg1, state->left->left->reg1);
436         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE_UN, set_to_0);
437         mono_bblock_add_inst (s->cbb, set_to_1);
438         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
439         mono_bblock_add_inst (s->cbb, set_to_0);
440 }       
441
442 stmt: CEE_BNE_UN (OP_LCOMPARE (lreg, lreg)) {
443         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
444         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_true_bb);
445         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
446         mono_bblock_add_inst (s->cbb, tree);
447 }
448
449 stmt: CEE_BNE_UN (OP_LCOMPARE (lreg, i8con)) {
450         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
451         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_true_bb);
452         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
453         mono_bblock_add_inst (s->cbb, tree);
454 }
455
456 stmt: CEE_BEQ (OP_LCOMPARE (lreg, lreg)) {
457         
458         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
459         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
460         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
461         mono_bblock_add_inst (s->cbb, tree);
462 }
463
464 stmt: CEE_BEQ (OP_LCOMPARE (lreg, i8con)) {
465         
466         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
467         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
468         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
469         mono_bblock_add_inst (s->cbb, tree);
470 }
471
472 stmt: CEE_BLE (OP_LCOMPARE (lreg, lreg)) {
473
474         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
475         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
476         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
477         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
478         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
479 }
480
481 stmt: CEE_BLE (OP_LCOMPARE (lreg, i8con)) {
482
483         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
484         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
485         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
486         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
487         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
488 }
489
490 stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, lreg)) {
491
492         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
493         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
494         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
495         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
496         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
497 }
498
499 stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, i8con)) {
500
501         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
502         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
503         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
504         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
505         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLE_UN, tree->inst_true_bb);
506 }
507
508 stmt: CEE_BGE (OP_LCOMPARE (lreg, lreg)) {
509
510         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
511         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
512         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
513         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
514         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
515 }
516
517 stmt: CEE_BGE (OP_LCOMPARE (lreg, i8con)) {
518
519         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
520         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
521         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
522         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
523         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
524 }
525
526 stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, lreg)) {
527
528         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
529         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
530         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
531         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
532         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
533 }
534
535 stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, i8con)) {
536
537         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
538         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
539         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
540         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
541         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_true_bb);
542 }
543
544 stmt: CEE_BLT (OP_LCOMPARE (lreg, lreg)) {
545
546         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
547         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
548         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
549         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
550         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
551 }
552
553 stmt: CEE_BLT (OP_LCOMPARE (lreg, i8con)) {
554
555         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
556         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT, tree->inst_true_bb);
557         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
558         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
559         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
560 }
561
562 stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, lreg)) {
563
564         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
565         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
566         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
567         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
568         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
569 }
570
571 stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, i8con)) {
572
573         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
574         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
575         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
576         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
577         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BLT_UN, tree->inst_true_bb);
578 }
579
580 stmt: CEE_BGT (OP_LCOMPARE (lreg, lreg)) {
581
582         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
583         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
584         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
585         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
586         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
587 }
588
589 stmt: CEE_BGT (OP_LCOMPARE (lreg, i8con)) {
590
591         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
592         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT, tree->inst_true_bb);
593         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
594         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
595         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
596 }
597
598 stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, lreg)) {
599
600         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg2, state->left->right->reg2);
601         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
602         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
603         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, state->left->left->reg1, state->left->right->reg1);
604         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
605 }
606
607 stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, i8con)) {
608
609         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg2, state->left->right->tree->inst_ms_word);
610         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
611         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BNE_UN, tree->inst_false_bb);
612         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->left->reg1, state->left->right->tree->inst_ls_word);
613         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGT_UN, tree->inst_true_bb);
614 }
615
616 lreg: CEE_CONV_I8 (OP_ICONST) {
617         int data = state->left->tree->inst_c0;
618
619        MONO_EMIT_NEW_ICONST (s, state->reg1, data);
620
621        if (data >= 0)
622                MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
623        else 
624                MONO_EMIT_NEW_ICONST (s, state->reg2, -1);
625 }
626
627 lreg: CEE_CONV_I8 (reg) {
628         MonoInst *is_negative, *end_label;
629         int tmpreg = mono_regstate_next_int (s->rs);
630         
631         MONO_NEW_LABEL (s, is_negative);
632         MONO_NEW_LABEL (s, end_label);
633
634         /* branchless code:
635          * low = reg;
636          * tmp = low > -1 ? 1: 0;
637          * high = tmp - 1; if low is zero or pos high becomes 0, else -1
638          * not sure why it doesn't work in practice
639          */
640         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
641         /*MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->reg1, -1);
642         tree->dreg = tmpreg;
643         tree->opcode = OP_CGT;
644         mono_bblock_add_inst (s->cbb, tree);
645         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, tmpreg, -1);*/
646         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->reg1, 0);
647         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative);
648         MONO_EMIT_NEW_ICONST (s, tmpreg, 0);
649         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
650         mono_bblock_add_inst (s->cbb, is_negative);
651         MONO_EMIT_NEW_ICONST (s, tmpreg, -1);
652         mono_bblock_add_inst (s->cbb, end_label);
653         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, tmpreg);
654 }
655
656 lreg: CEE_CONV_U8 (reg) {
657         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
658         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
659 }
660
661 lreg: CEE_CONV_OVF_U8 (reg) {
662         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
663         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
664         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
665         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
666 }
667
668 lreg: CEE_CONV_OVF_I8 (reg) {
669         /* a signed 32 bit num always fits in a signed 64 bit one */
670         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg2, state->left->reg1, 31);
671         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
672 }
673
674 lreg: CEE_CONV_OVF_I8_UN (reg) {
675         /* an unsigned 32 bit num always fits in a signed 64 bit one */
676         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
677         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
678 }
679
680 lreg: CEE_CONV_OVF_U8_UN (reg) {
681         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
682         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
683 }
684
685 freg: OP_LCONV_TO_R_UN (lreg) {
686         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->left->reg2);
687 }
688
689 lreg: OP_FCONV_TO_I8 (freg) {
690         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
691 }
692
693 lreg: OP_FCONV_TO_U8 (freg) {
694         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
695 }
696
697 reg: OP_LCONV_TO_I4 (i8con) {
698         MONO_EMIT_NEW_ICONST (s, state->reg1, state->left->tree->inst_ls_word);
699 }
700
701 reg: OP_LCONV_TO_I4 (lreg),
702 reg: OP_LCONV_TO_U4 (lreg) {
703         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
704 }
705
706 reg: OP_LCONV_TO_I4 (CEE_LDIND_I8 (base)),
707 reg: OP_LCONV_TO_U4 (CEE_LDIND_I8 (base)) {
708         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
709                                    state->left->left->tree->inst_basereg, 
710                                    state->left->left->tree->inst_offset + MINI_LS_WORD_OFFSET);
711 }
712
713 lreg: OP_LCONV_TO_U8 (lreg),
714 lreg: OP_LCONV_TO_I8 (lreg) {
715         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
716         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
717 }
718
719 reg: OP_LCONV_TO_U (lreg),
720 reg: OP_LCONV_TO_I (lreg) {
721         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
722 }
723
724 reg: OP_LCONV_TO_I1 (lreg) {
725         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
726 }
727
728 reg: OP_LCONV_TO_U1 (lreg) {
729         MONO_EMIT_UNALU (s, tree, CEE_CONV_U1, state->reg1, state->left->reg1);
730 }
731
732 reg: OP_LCONV_TO_I2 (lreg) {
733         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
734 }
735
736 reg: OP_LCONV_TO_U2 (lreg) {
737         MONO_EMIT_UNALU (s, tree, CEE_CONV_U2, state->reg1, state->left->reg1);
738 }
739
740 reg: OP_LCONV_TO_OVF_I1_UN (lreg) {
741         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
742         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
743
744         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
745         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
746         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
747         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
748         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
749 }
750
751 reg: OP_LCONV_TO_OVF_I1 (lreg) {
752         MonoInst *is_negative, *end_label;
753
754         MONO_NEW_LABEL (s, is_negative);
755         MONO_NEW_LABEL (s, end_label);
756
757         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
758         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
759         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
760         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
761
762         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
763         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative);
764
765         /* Positive */
766         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
767         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
768         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
769
770         /* Negative */
771         mono_bblock_add_inst (s->cbb, is_negative);
772         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
773         MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException");
774         mono_bblock_add_inst (s->cbb, end_label);
775
776         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
777 }
778
779 reg: OP_LCONV_TO_OVF_U1_UN (lreg),
780 reg: OP_LCONV_TO_OVF_U1 (lreg) {
781         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
782         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
783
784         /* probe value to be within 0 to 255 */
785         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
786         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
787         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
788 }
789
790 reg: OP_LCONV_TO_OVF_I2 (lreg) {
791         MonoInst *is_negative, *end_label;
792
793         MONO_NEW_LABEL (s, is_negative);
794         MONO_NEW_LABEL (s, end_label);
795
796         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
797         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
798         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
799         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
800
801         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
802         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative);
803
804         /* Positive */
805         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
806         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
807         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
808
809         /* Negative */
810         mono_bblock_add_inst (s->cbb, is_negative);
811         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
812         MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException");
813         mono_bblock_add_inst (s->cbb, end_label);
814
815         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
816 }
817
818 reg: OP_LCONV_TO_OVF_I2_UN (lreg) {
819         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
820         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
821
822         /* Probe value to be within -32768 and 32767 */
823         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
824         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
825         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
826         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
827         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
828 }
829
830 reg: OP_LCONV_TO_OVF_U2_UN (lreg),
831 reg: OP_LCONV_TO_OVF_U2 (lreg) {
832         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
833         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
834
835         /* Probe value to be within 0 and 65535 */
836         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
837         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
838         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
839 }
840
841
842 reg: OP_LCONV_TO_OVF_U4_UN (lreg) {
843         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
844         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
845         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
846 }
847
848 reg: OP_LCONV_TO_OVF_I_UN (lreg) {
849         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
850         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
851         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
852 }
853
854 reg: OP_LCONV_TO_OVF_U4 (lreg) {
855         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
856         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
857         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
858 }
859
860 reg: OP_LCONV_TO_OVF_I (lreg) {
861         tree->dreg = state->reg1;
862         tree->sreg1 = state->left->reg1;
863         tree->sreg2 = state->left->reg2;
864         mono_bblock_add_inst (s->cbb, tree);
865 }
866
867 reg: OP_LCONV_TO_OVF_I4_UN (lreg),
868 reg: OP_LCONV_TO_OVF_I4 (lreg) {
869         tree->dreg = state->reg1;
870         tree->sreg1 = state->left->reg1;
871         tree->sreg2 = state->left->reg2;
872         tree->opcode = OP_LCONV_TO_OVF_I;
873         mono_bblock_add_inst (s->cbb, tree);
874 }
875
876 lreg: OP_LCONV_TO_OVF_I8_UN (lreg) {
877         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
878         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
879
880         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
881         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
882 }
883
884 lreg: OP_LCONV_TO_OVF_U8 (lreg) {
885         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
886         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
887
888         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
889         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
890 }
891
892 lreg: OP_LCONV_TO_OVF_I8 (lreg) {
893         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
894         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
895 }
896
897 lreg: OP_LCONV_TO_OVF_U8_UN (lreg) {
898         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
899         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
900 }
901
902 lreg: OP_LCALLVIRT (reg) {
903         mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE);
904 }
905
906 lreg: OP_LCALL {
907         tree->dreg = state->reg1;
908         mono_bblock_add_inst (s->cbb, tree);
909 }
910
911 lreg: OP_LCALL_REG (reg) {
912         tree->sreg1 = state->left->reg1;
913         tree->dreg = state->reg1;
914         mono_bblock_add_inst (s->cbb, tree);
915 }
916
917 lreg: OP_LCALL_REG (OP_ICONST) {
918         tree->opcode = OP_LCALL;
919         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
920         tree->dreg = state->reg1;
921         mono_bblock_add_inst (s->cbb, tree);
922 }
923
924 %%