This should fix #76928. This fix incorporates ideas from a patch
[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         int tmpreg = mono_regstate_next_int (s->rs);
629         
630         /* branchless code:
631          * low = reg;
632          * tmp = low > -1 ? 1: 0;
633          * high = tmp - 1; if low is zero or pos high becomes 0, else -1
634          */
635         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
636         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->reg1, -1);
637         tree->dreg = tmpreg;
638         tree->opcode = OP_CGT;
639         mono_bblock_add_inst (s->cbb, tree);
640         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, tmpreg, 1);
641 }
642
643 lreg: CEE_CONV_U8 (reg) {
644         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
645         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
646 }
647
648 lreg: CEE_CONV_OVF_U8 (reg) {
649         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
650         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
651         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
652         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
653 }
654
655 lreg: CEE_CONV_OVF_I8 (reg) {
656         /* a signed 32 bit num always fits in a signed 64 bit one */
657         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg2, state->left->reg1, 31);
658         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
659 }
660
661 lreg: CEE_CONV_OVF_I8_UN (reg) {
662         /* an unsigned 32 bit num always fits in a signed 64 bit one */
663         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
664         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
665 }
666
667 lreg: CEE_CONV_OVF_U8_UN (reg) {
668         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
669         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
670 }
671
672 freg: OP_LCONV_TO_R_UN (lreg) {
673         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->left->reg2);
674 }
675
676 lreg: OP_FCONV_TO_I8 (freg) {
677         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
678 }
679
680 lreg: OP_FCONV_TO_U8 (freg) {
681         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
682 }
683
684 reg: OP_LCONV_TO_I4 (i8con) {
685         MONO_EMIT_NEW_ICONST (s, state->reg1, state->left->tree->inst_ls_word);
686 }
687
688 reg: OP_LCONV_TO_I4 (lreg),
689 reg: OP_LCONV_TO_U4 (lreg) {
690         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
691 }
692
693 reg: OP_LCONV_TO_I4 (CEE_LDIND_I8 (base)),
694 reg: OP_LCONV_TO_U4 (CEE_LDIND_I8 (base)) {
695         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
696                                    state->left->left->tree->inst_basereg, 
697                                    state->left->left->tree->inst_offset + MINI_LS_WORD_OFFSET);
698 }
699
700 lreg: OP_LCONV_TO_U8 (lreg),
701 lreg: OP_LCONV_TO_I8 (lreg) {
702         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
703         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
704 }
705
706 reg: OP_LCONV_TO_U (lreg),
707 reg: OP_LCONV_TO_I (lreg) {
708         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
709 }
710
711 reg: OP_LCONV_TO_I1 (lreg) {
712         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
713 }
714
715 reg: OP_LCONV_TO_U1 (lreg) {
716         MONO_EMIT_UNALU (s, tree, CEE_CONV_U1, state->reg1, state->left->reg1);
717 }
718
719 reg: OP_LCONV_TO_I2 (lreg) {
720         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
721 }
722
723 reg: OP_LCONV_TO_U2 (lreg) {
724         MONO_EMIT_UNALU (s, tree, CEE_CONV_U2, state->reg1, state->left->reg1);
725 }
726
727 reg: OP_LCONV_TO_OVF_I1_UN (lreg) {
728         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
729         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
730
731         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
732         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
733         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
734         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
735         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
736 }
737
738 reg: OP_LCONV_TO_OVF_I1 (lreg) {
739         MonoInst *is_negative, *end_label;
740
741         MONO_NEW_LABEL (s, is_negative);
742         MONO_NEW_LABEL (s, end_label);
743
744         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
745         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
746         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
747         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
748
749         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
750         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative);
751
752         /* Positive */
753         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
754         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
755         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
756
757         /* Negative */
758         mono_bblock_add_inst (s->cbb, is_negative);
759         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
760         MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException");
761         mono_bblock_add_inst (s->cbb, end_label);
762
763         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
764 }
765
766 reg: OP_LCONV_TO_OVF_U1_UN (lreg),
767 reg: OP_LCONV_TO_OVF_U1 (lreg) {
768         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
769         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
770
771         /* probe value to be within 0 to 255 */
772         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
773         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
774         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
775 }
776
777 reg: OP_LCONV_TO_OVF_I2 (lreg) {
778         MonoInst *is_negative, *end_label;
779
780         MONO_NEW_LABEL (s, is_negative);
781         MONO_NEW_LABEL (s, end_label);
782
783         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
784         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
785         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, -1);
786         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
787
788         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
789         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT, is_negative);
790
791         /* Positive */
792         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
793         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
794         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
795
796         /* Negative */
797         mono_bblock_add_inst (s->cbb, is_negative);
798         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
799         MONO_EMIT_NEW_COND_EXC (s, LT_UN, "OverflowException");
800         mono_bblock_add_inst (s->cbb, end_label);
801
802         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
803 }
804
805 reg: OP_LCONV_TO_OVF_I2_UN (lreg) {
806         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
807         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
808
809         /* Probe value to be within -32768 and 32767 */
810         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
811         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
812         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
813         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
814         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
815 }
816
817 reg: OP_LCONV_TO_OVF_U2_UN (lreg),
818 reg: OP_LCONV_TO_OVF_U2 (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 0 and 65535 */
823         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
824         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
825         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
826 }
827
828
829 reg: OP_LCONV_TO_OVF_U4_UN (lreg) {
830         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
831         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
832         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
833 }
834
835 reg: OP_LCONV_TO_OVF_I_UN (lreg) {
836         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
837         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
838         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
839 }
840
841 reg: OP_LCONV_TO_OVF_U4 (lreg) {
842         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
843         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "OverflowException");
844         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
845 }
846
847 reg: OP_LCONV_TO_OVF_I (lreg) {
848         tree->dreg = state->reg1;
849         tree->sreg1 = state->left->reg1;
850         tree->sreg2 = state->left->reg2;
851         mono_bblock_add_inst (s->cbb, tree);
852 }
853
854 reg: OP_LCONV_TO_OVF_I4_UN (lreg),
855 reg: OP_LCONV_TO_OVF_I4 (lreg) {
856         tree->dreg = state->reg1;
857         tree->sreg1 = state->left->reg1;
858         tree->sreg2 = state->left->reg2;
859         tree->opcode = OP_LCONV_TO_OVF_I;
860         mono_bblock_add_inst (s->cbb, tree);
861 }
862
863 lreg: OP_LCONV_TO_OVF_I8_UN (lreg) {
864         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
865         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
866
867         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
868         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
869 }
870
871 lreg: OP_LCONV_TO_OVF_U8 (lreg) {
872         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg2, 0);
873         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
874
875         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
876         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
877 }
878
879 lreg: OP_LCONV_TO_OVF_I8 (lreg) {
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_UN (lreg) {
885         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
886         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
887 }
888
889 lreg: OP_LCALLVIRT (reg) {
890         mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE);
891 }
892
893 lreg: OP_LCALL {
894         tree->dreg = state->reg1;
895         mono_bblock_add_inst (s->cbb, tree);
896 }
897
898 lreg: OP_LCALL_REG (reg) {
899         tree->sreg1 = state->left->reg1;
900         tree->dreg = state->reg1;
901         mono_bblock_add_inst (s->cbb, tree);
902 }
903
904 lreg: OP_LCALL_REG (OP_ICONST) {
905         tree->opcode = OP_LCALL;
906         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
907         tree->dreg = state->reg1;
908         mono_bblock_add_inst (s->cbb, tree);
909 }
910
911 %%