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