2008-07-22 Zoltan Varga <vargaz@gmail.com>
[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) "2" {
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) "2" {
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)) "2" {
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) "2" {
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) "2" {
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) "2" {
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) "2" {   
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_LSHR_UN_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_LSHR_UN_32 (lreg)),
270 reg: OP_LCONV_TO_U4 (OP_LSHR_UN_32 (lreg)) {
271         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->left->reg2);
272 }
273
274
275 lreg: OP_LSHR_UN_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_LSHR_UN_32 (CEE_LDIND_I8 (base))),
283 reg: OP_LCONV_TO_U4 (OP_LSHR_UN_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_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, word_differs);
388         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, state->left->left->reg1, state->left->right->reg1, word_differs);
389         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
390         
391         mono_bblock_add_inst (s->cbb, word_differs);
392 }
393
394 reg: OP_CLT (OP_LCOMPARE (lreg, lreg)) {        
395         MonoInst *set_to_0, *set_to_1;
396         
397         MONO_NEW_LABEL (s, set_to_0);
398         MONO_NEW_LABEL (s, set_to_1);
399
400         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
401         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT, state->left->left->reg2, state->left->right->reg2, set_to_0);
402         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, set_to_1);
403         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, state->left->left->reg1, state->left->right->reg1, set_to_0);
404         mono_bblock_add_inst (s->cbb, set_to_1);
405         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
406         mono_bblock_add_inst (s->cbb, set_to_0);
407 }       
408
409 reg: OP_CLT_UN (OP_LCOMPARE (lreg, lreg)) {     
410         MonoInst *set_to_0, *set_to_1;
411         
412         MONO_NEW_LABEL (s, set_to_0);
413         MONO_NEW_LABEL (s, set_to_1);
414
415         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
416         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT_UN, state->left->left->reg2, state->left->right->reg2, set_to_0);
417         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, set_to_1);
418         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, state->left->left->reg1, state->left->right->reg1, set_to_0);
419         mono_bblock_add_inst (s->cbb, set_to_1);
420         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
421         mono_bblock_add_inst (s->cbb, set_to_0);
422 }       
423
424 reg: OP_CGT (OP_LCOMPARE (lreg, lreg)) {        
425         MonoInst *set_to_0, *set_to_1;
426         
427         MONO_NEW_LABEL (s, set_to_0);
428         MONO_NEW_LABEL (s, set_to_1);
429
430         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
431         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT, state->left->right->reg2, state->left->left->reg2, set_to_0);
432         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL_CHAINED (s, CEE_BNE_UN, state->left->right->reg2, state->left->left->reg2, set_to_1);
433         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, state->left->right->reg1, state->left->left->reg1, set_to_0);
434         mono_bblock_add_inst (s->cbb, set_to_1);
435         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
436         mono_bblock_add_inst (s->cbb, set_to_0);
437 }       
438
439 reg: OP_CGT_UN (OP_LCOMPARE (lreg, lreg)) {     
440         MonoInst *set_to_0, *set_to_1;
441         
442         MONO_NEW_LABEL (s, set_to_0);
443         MONO_NEW_LABEL (s, set_to_1);
444
445         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
446         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT_UN, state->left->right->reg2, state->left->left->reg2, set_to_0);
447         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL_CHAINED (s, CEE_BNE_UN, state->left->right->reg2, state->left->left->reg2, set_to_1);
448         MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, state->left->right->reg1, state->left->left->reg1, set_to_0);
449         mono_bblock_add_inst (s->cbb, set_to_1);
450         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
451         mono_bblock_add_inst (s->cbb, set_to_0);
452 }       
453
454 stmt: CEE_BNE_UN (OP_LCOMPARE (lreg, lreg)) {
455         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BNE_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
456         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
457 }
458
459 stmt: CEE_BNE_UN (OP_LCOMPARE (lreg, i8con)) {
460         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BNE_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
461         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
462 }
463
464 stmt: CEE_BEQ (OP_LCOMPARE (lreg, lreg)) {
465         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BNE_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_false_bb);
466         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BEQ, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
467 }
468
469 stmt: CEE_BEQ (OP_LCOMPARE (lreg, i8con)) {
470         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BNE_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_false_bb);
471         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BEQ, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
472 }
473
474 stmt: CEE_BLE (OP_LCOMPARE (lreg, lreg)) {
475         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLT, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
476         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
477         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLE_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
478 }
479
480 stmt: CEE_BLE (OP_LCOMPARE (lreg, i8con)) {
481         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLT, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
482         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
483         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLE_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
484 }
485
486 stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, lreg)) {
487         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
488         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
489         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLE_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
490 }
491
492 stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, i8con)) {
493
494         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
495         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
496         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLE_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
497 }
498
499 stmt: CEE_BGE (OP_LCOMPARE (lreg, lreg)) {
500         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGT, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
501         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
502         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGE_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
503 }
504
505 stmt: CEE_BGE (OP_LCOMPARE (lreg, i8con)) {
506         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGT, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
507         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
508         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGE_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
509 }
510
511 stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, lreg)) {
512         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
513         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
514         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGE_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
515 }
516
517 stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, i8con)) {
518         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
519         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
520         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGE_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
521 }
522
523 stmt: CEE_BLT (OP_LCOMPARE (lreg, lreg)) {
524         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLT, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
525         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
526         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
527 }
528
529 stmt: CEE_BLT (OP_LCOMPARE (lreg, i8con)) {
530         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLT, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
531         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
532         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
533 }
534
535 stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, lreg)) {
536         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
537         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
538         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
539 }
540
541 stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, i8con)) {
542         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
543         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
544         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BLT_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
545 }
546
547 stmt: CEE_BGT (OP_LCOMPARE (lreg, lreg)) {
548         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGT, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
549         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
550         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
551 }
552
553 stmt: CEE_BGT (OP_LCOMPARE (lreg, i8con)) {
554         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGT, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
555         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
556         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
557 }
558
559 stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, lreg)) {
560         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_true_bb);
561         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->reg2, tree->inst_false_bb);
562         MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg1, state->left->right->reg1, tree->inst_true_bb);
563 }
564
565 stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, i8con)) {
566         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_true_bb);
567         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK_CHAINED (s, CEE_BNE_UN, state->left->left->reg2, state->left->right->tree->inst_ms_word, tree->inst_false_bb);
568         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_BLOCK (s, CEE_BGT_UN, state->left->left->reg1, state->left->right->tree->inst_ls_word, tree->inst_true_bb);
569 }
570
571 lreg: CEE_CONV_I8 (OP_ICONST) {
572         int data = state->left->tree->inst_c0;
573
574        MONO_EMIT_NEW_ICONST (s, state->reg1, data);
575
576        if (data >= 0)
577                MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
578        else 
579                MONO_EMIT_NEW_ICONST (s, state->reg2, -1);
580 }
581
582 lreg: CEE_CONV_I8 (reg) {
583         int tmpreg = mono_regstate_next_int (s->rs);
584         
585         /* branchless code:
586          * low = reg;
587          * tmp = low > -1 ? 1: 0;
588          * high = tmp - 1; if low is zero or pos high becomes 0, else -1
589          */
590         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
591         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->reg1, -1);
592         tree->dreg = tmpreg;
593         tree->opcode = OP_CGT;
594         mono_bblock_add_inst (s->cbb, tree);
595         MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, tmpreg, 1);
596 }
597
598 lreg: CEE_CONV_U8 (reg) {
599         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
600         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
601 }
602
603 lreg: CEE_CONV_OVF_U8 (reg) {
604         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException");
605         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
606         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
607 }
608
609 lreg: CEE_CONV_OVF_I8 (reg) {
610         /* a signed 32 bit num always fits in a signed 64 bit one */
611         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg2, state->left->reg1, 31);
612         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
613 }
614
615 lreg: CEE_CONV_OVF_I8_UN (reg) {
616         /* an unsigned 32 bit num always fits in a signed 64 bit one */
617         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
618         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
619 }
620
621 lreg: CEE_CONV_OVF_U8_UN (reg) {
622         MONO_EMIT_NEW_ICONST (s, state->reg2, 0);
623         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
624 }
625
626 reg: CEE_CONV_OVF_I_UN (reg),
627 reg: CEE_CONV_OVF_U (reg) {
628         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException");
629         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
630 }
631
632 reg: CEE_CONV_OVF_U_UN (reg),
633 reg: CEE_CONV_OVF_I (reg) {
634         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
635 }
636
637 freg: OP_LCONV_TO_R_UN (lreg) {
638         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->left->reg2);
639 }
640
641 lreg: OP_FCONV_TO_I8 (freg) {
642         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
643 }
644
645 lreg: OP_FCONV_TO_U8 (freg) {
646         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
647 }
648
649 reg: OP_LCONV_TO_I4 (i8con) {
650         MONO_EMIT_NEW_ICONST (s, state->reg1, state->left->tree->inst_ls_word);
651 }
652
653 reg: OP_LCONV_TO_I4 (lreg),
654 reg: OP_LCONV_TO_U4 (lreg) {
655         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
656 }
657
658 reg: OP_LCONV_TO_I4 (CEE_LDIND_I8 (base)),
659 reg: OP_LCONV_TO_U4 (CEE_LDIND_I8 (base)) {
660         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
661                                    state->left->left->tree->inst_basereg, 
662                                    state->left->left->tree->inst_offset + MINI_LS_WORD_OFFSET);
663 }
664
665 lreg: OP_LCONV_TO_U8 (lreg),
666 lreg: OP_LCONV_TO_I8 (lreg) {
667         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
668         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
669 }
670
671 reg: OP_LCONV_TO_U (lreg),
672 reg: OP_LCONV_TO_I (lreg) {
673         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
674 }
675
676 reg: OP_LCONV_TO_I1 (lreg) {
677         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
678 }
679
680 reg: OP_LCONV_TO_U1 (lreg) {
681         MONO_EMIT_UNALU (s, tree, CEE_CONV_U1, state->reg1, state->left->reg1);
682 }
683
684 reg: OP_LCONV_TO_I2 (lreg) {
685         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
686 }
687
688 reg: OP_LCONV_TO_U2 (lreg) {
689         MONO_EMIT_UNALU (s, tree, CEE_CONV_U2, state->reg1, state->left->reg1);
690 }
691
692 reg: OP_LCONV_TO_OVF_I1_UN (lreg) {
693         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
694         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 127, "OverflowException");
695         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -128, "OverflowException");
696         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
697 }
698
699 reg: OP_LCONV_TO_OVF_I1 (lreg) {
700         MonoInst *is_negative, *end_label;
701
702         MONO_NEW_LABEL (s, is_negative);
703         MONO_NEW_LABEL (s, end_label);
704
705         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg2, 0, "OverflowException");
706         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, -1, "OverflowException");
707         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL (s, CEE_BLT, state->left->reg2, 0, is_negative);
708
709         /* Positive */
710         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 127, "OverflowException");
711         MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label);
712
713         /* Negative */
714         mono_bblock_add_inst (s->cbb, is_negative);
715         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT_UN, state->left->reg1, -128, "OverflowException");
716         mono_bblock_add_inst (s->cbb, end_label);
717
718         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
719 }
720
721 reg: OP_LCONV_TO_OVF_U1_UN (lreg),
722 reg: OP_LCONV_TO_OVF_U1 (lreg) {
723         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
724
725         /* probe value to be within 0 to 255 */
726         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 255, "OverflowException");
727         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
728 }
729
730 reg: OP_LCONV_TO_OVF_I2 (lreg) {
731         MonoInst *is_negative, *end_label;
732
733         MONO_NEW_LABEL (s, is_negative);
734         MONO_NEW_LABEL (s, end_label);
735
736         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg2, 0, "OverflowException");
737         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, -1, "OverflowException");
738
739         MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL (s, CEE_BLT, state->left->reg2, 0, is_negative);
740
741         /* Positive */
742         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 32767, "OverflowException");
743         MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label);
744
745         /* Negative */
746         mono_bblock_add_inst (s->cbb, is_negative);
747         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT_UN, state->left->reg1, -32768, "OverflowException");
748         mono_bblock_add_inst (s->cbb, end_label);
749
750         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
751 }
752
753 reg: OP_LCONV_TO_OVF_I2_UN (lreg) {
754         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
755
756         /* Probe value to be within -32768 and 32767 */
757         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 32767, "OverflowException");
758         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -32768, "OverflowException");
759         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
760 }
761
762 reg: OP_LCONV_TO_OVF_U2_UN (lreg),
763 reg: OP_LCONV_TO_OVF_U2 (lreg) {
764         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
765
766         /* Probe value to be within 0 and 65535 */
767         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 0xffff, "OverflowException");
768         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
769 }
770
771
772 reg: OP_LCONV_TO_OVF_U4_UN (lreg),
773 reg: OP_LCONV_TO_OVF_U_UN (lreg) {
774         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
775         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
776 }
777
778 reg: OP_LCONV_TO_OVF_I_UN (lreg) {
779         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
780         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
781 }
782
783 reg: OP_LCONV_TO_OVF_U4 (lreg),
784 reg: OP_LCONV_TO_OVF_U (lreg) {
785         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
786         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
787 }
788
789 reg: OP_LCONV_TO_OVF_I (lreg) {
790         tree->dreg = state->reg1;
791         tree->sreg1 = state->left->reg1;
792         tree->sreg2 = state->left->reg2;
793         mono_bblock_add_inst (s->cbb, tree);
794 }
795
796 reg: OP_LCONV_TO_OVF_I4_UN (lreg) {
797         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException");
798         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException");
799         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
800 }
801
802 reg: OP_LCONV_TO_OVF_I4 (lreg) {
803         tree->dreg = state->reg1;
804         tree->sreg1 = state->left->reg1;
805         tree->sreg2 = state->left->reg2;
806         tree->opcode = OP_LCONV_TO_OVF_I;
807         mono_bblock_add_inst (s->cbb, tree);
808 }
809
810 lreg: OP_LCONV_TO_OVF_I8_UN (lreg) {
811         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, 0, "OverflowException");
812
813         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
814         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
815 }
816
817 lreg: OP_LCONV_TO_OVF_U8 (lreg) {
818         MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, 0, "OverflowException");
819
820         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
821         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
822 }
823
824 lreg: OP_LCONV_TO_OVF_I8 (lreg) {
825         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
826         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
827 }
828
829 lreg: OP_LCONV_TO_OVF_U8_UN (lreg) {
830         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1);
831         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2);
832 }
833
834 lreg: OP_LCALLVIRT (reg) {
835         mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE);
836 }
837
838 lreg: OP_LCALLVIRT_IMT (reg, reg) {
839         tree->opcode = OP_LCALLVIRT;
840         mini_emit_virtual_imt_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE, state->right->reg1);
841 }
842
843 lreg: OP_LCALL {
844         tree->dreg = state->reg1;
845         mono_bblock_add_inst (s->cbb, tree);
846 }
847
848 lreg: OP_LCALL_RGCTX (reg) {
849         emit_rgctx_argument (s, tree, state->left->reg1, OP_LCALL);
850
851         tree->dreg = state->reg1;
852         mono_bblock_add_inst (s->cbb, tree);
853 }
854
855 lreg: OP_LCALL_REG (reg) {
856         tree->sreg1 = state->left->reg1;
857         tree->dreg = state->reg1;
858         mono_bblock_add_inst (s->cbb, tree);
859 }
860
861 lreg: OP_LCALL_REG_RGCTX (reg, reg) {
862         emit_rgctx_argument (s, tree, state->right->reg1, OP_LCALL_REG);
863
864         tree->sreg1 = state->left->reg1;
865         tree->dreg = state->reg1;
866         mono_bblock_add_inst (s->cbb, tree);
867 }
868
869 lreg: OP_LCALL_REG (OP_ICONST) {
870         tree->opcode = OP_LCALL;
871         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
872         tree->dreg = state->reg1;
873         mono_bblock_add_inst (s->cbb, tree);
874 }
875
876 %%