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