2003-05-25 Francisco Figueiredo Jr. <fxjrlists@yahoo.com.br>
[mono.git] / mono / mini / inssel.brg
1 /*
2  * inssel.brg: instruction selection
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  *
10  */
11
12 #include <string.h>
13
14 #include "mini.h"
15 #include "mini-arch.h"
16 #include <mono/metadata/marshal.h>
17
18 #define MBTREE_TYPE  MonoInst
19 #define MBCGEN_TYPE  MonoCompile
20 #define MBCOST_DATA  MonoCompile
21 #define MBALLOC_STATE mono_mempool_alloc (data->state_pool, sizeof (MBState))
22 #define MBMAX_OPCODES OP_LAST
23 #define MBGET_OP_NAME(op) mono_inst_name (op)
24
25 #define MBTREE_OP(t) ((t)->opcode)
26 #define MBTREE_LEFT(t) ((t)->inst_left)
27 #define MBTREE_RIGHT(t) ((t)->inst_right)
28
29 #define MONO_EMIT_UNALU(cfg,inst,op,dr,sr1) do { \
30                 (inst)->opcode = op; \
31                 (inst)->dreg = dr; \
32                 (inst)->sreg1 = sr1; \
33                 mono_bblock_add_inst (cfg->cbb, inst); \
34         } while (0)
35
36 #define MONO_EMIT_NEW_UNALU(cfg,op,dr,sr1) do { \
37                 MonoInst *inst; \
38                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
39                 inst->opcode = op; \
40                 inst->dreg = dr; \
41                 inst->sreg1 = sr1; \
42                 mono_bblock_add_inst (cfg->cbb, inst); \
43         } while (0)
44
45 #define MONO_EMIT_BIALU(cfg,inst,op,dr,sr1,sr2) do { \
46                 (inst)->opcode = op; \
47                 (inst)->dreg = dr; \
48                 (inst)->sreg1 = sr1; \
49                 (inst)->sreg2 = sr2; \
50                 mono_bblock_add_inst (cfg->cbb, inst); \
51         } while (0)
52
53 #define MONO_EMIT_NEW_BIALU(cfg,op,dr,sr1,sr2) do { \
54                 MonoInst *inst; \
55                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
56                 inst->opcode = op; \
57                 inst->dreg = dr; \
58                 inst->sreg1 = sr1; \
59                 inst->sreg2 = sr2; \
60                 mono_bblock_add_inst (cfg->cbb, inst); \
61         } while (0)
62
63 #define MONO_EMIT_BIALU_IMM(cfg,inst,op,dr,sr,imm) do { \
64                 (inst)->opcode = op; \
65                 (inst)->dreg = dr; \
66                 (inst)->sreg1 = sr; \
67                 (inst)->inst_p1 = (gpointer)imm; \
68                 mono_bblock_add_inst (cfg->cbb, inst); \
69         } while (0)
70
71 #define MONO_EMIT_NEW_BIALU_IMM(cfg,op,dr,sr,imm) do { \
72                 MonoInst *inst; \
73                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
74                 inst->opcode = op; \
75                 inst->dreg = dr; \
76                 inst->sreg1 = sr; \
77                 inst->inst_p1 = (gpointer)imm; \
78                 mono_bblock_add_inst (cfg->cbb, inst); \
79         } while (0)
80
81 #define MONO_EMIT_LOAD_MEMBASE(cfg,inst,dr,base,offset) do { \
82                 (inst)->opcode = OP_LOAD_MEMBASE; \
83                 (inst)->dreg = dr; \
84                 (inst)->inst_basereg = base; \
85                 (inst)->inst_offset = offset; \
86                 mono_bblock_add_inst (cfg->cbb, inst); \
87         } while (0)
88
89 #define MONO_EMIT_LOAD_MEMBASE_OP(cfg,inst,op,dr,base,offset) do { \
90                 (inst)->opcode = op; \
91                 (inst)->dreg = dr; \
92                 (inst)->inst_basereg = base; \
93                 (inst)->inst_offset = offset; \
94                 mono_bblock_add_inst (cfg->cbb, inst); \
95         } while (0)
96
97 #define MONO_EMIT_NEW_LOAD_MEM(cfg,dr,addr) do { \
98                 MonoInst *inst; \
99                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
100                 inst->opcode = OP_LOADU4_MEM; \
101                 inst->dreg = dr; \
102                 inst->inst_p0 = addr; \
103                 mono_bblock_add_inst (cfg->cbb, inst); \
104         } while (0)
105
106 #define MONO_EMIT_NEW_LOAD_MEMBASE(cfg,dr,base,offset) do { \
107                 MonoInst *inst; \
108                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
109                 inst->opcode = OP_LOAD_MEMBASE; \
110                 inst->dreg = dr; \
111                 inst->inst_basereg = base; \
112                 inst->inst_offset = offset; \
113                 mono_bblock_add_inst (cfg->cbb, inst); \
114         } while (0)
115
116 #define MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg,op,dr,base,offset) do { \
117                 MonoInst *inst; \
118                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
119                 inst->opcode = op; \
120                 inst->dreg = dr; \
121                 inst->inst_basereg = base; \
122                 inst->inst_offset = offset; \
123                 mono_bblock_add_inst (cfg->cbb, inst); \
124         } while (0)
125
126 #define MONO_EMIT_STORE_MEMBASE(cfg,inst,op,base,offset,sr) do { \
127                 (inst)->opcode = op; \
128                 (inst)->sreg1 = sr; \
129                 (inst)->inst_destbasereg = base; \
130                 (inst)->inst_offset = offset; \
131                 mono_bblock_add_inst (cfg->cbb, inst); \
132         } while (0)
133
134 #define MONO_EMIT_NEW_STORE_MEMBASE(cfg,op,base,offset,sr) do { \
135                 MonoInst *inst; \
136                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
137                 inst->opcode = op; \
138                 inst->sreg1 = sr; \
139                 inst->inst_destbasereg = base; \
140                 inst->inst_offset = offset; \
141                 mono_bblock_add_inst (cfg->cbb, inst); \
142         } while (0)
143
144 #define MONO_EMIT_STORE_MEMBASE_IMM(cfg,inst,op,base,offset,imm) do { \
145                 (inst)->opcode = op; \
146                 (inst)->inst_destbasereg = base; \
147                 (inst)->inst_offset = offset; \
148                 (inst)->inst_p1 = (gpointer)imm; \
149                 mono_bblock_add_inst (cfg->cbb, inst); \
150         } while (0)
151
152 #define MONO_EMIT_NEW_STORE_MEMBASE_IMM(cfg,op,base,offset,imm) do { \
153                 MonoInst *inst; \
154                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
155                 inst->opcode = op; \
156                 inst->inst_destbasereg = base; \
157                 inst->inst_offset = offset; \
158                 inst->inst_p1 = (gpointer)imm; \
159                 mono_bblock_add_inst (cfg->cbb, inst); \
160         } while (0)
161
162 #define MONO_EMIT_NEW_COMPARE_IMM(cfg,sr1,imm) do { \
163                 MonoInst *inst; \
164                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
165                 inst->opcode = OP_COMPARE_IMM;  \
166                 inst->sreg1 = sr1; \
167                 inst->inst_p1 = (gpointer)imm; \
168                 mono_bblock_add_inst ((cfg)->cbb, inst); \
169         } while (0)
170
171 #define MONO_EMIT_NEW_COND_EXC(cfg,cond,name) do { \
172                 MonoInst *inst; \
173                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
174                 inst->opcode = OP_COND_EXC_##cond;  \
175                 inst->inst_p1 = (char*)name; \
176                 mono_bblock_add_inst ((cfg)->cbb, inst); \
177         } while (0)
178
179 #define MONO_EMIT_NEW_ICONST(cfg,dr,imm) do { \
180                 MonoInst *inst; \
181                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
182                 inst->opcode = OP_ICONST;       \
183                 inst->dreg = dr; \
184                 inst->inst_c0 = imm; \
185                 mono_bblock_add_inst ((cfg)->cbb, inst); \
186         } while (0)
187
188 #define MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,type) do { \
189                 MonoInst *inst; \
190                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
191                 inst->opcode = OP_AOTCONST;     \
192                 inst->dreg = dr; \
193                 inst->inst_p0 = imm; \
194                 inst->inst_c1 = type; \
195                 mono_bblock_add_inst ((cfg)->cbb, inst); \
196         } while (0)
197
198 #define MONO_EMIT_NEW_CLASSCONST(cfg,dr,imm) MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,MONO_PATCH_INFO_CLASS)
199
200 #define MONO_EMIT_NEW_BRANCH_BLOCK(cfg,op,targetbb) do { \
201                 MonoInst *inst; \
202                 MonoInst *target_label; \
203                 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
204                 target_label->opcode = OP_LABEL;        \
205                 target_label->next = (targetbb)->code; \
206                 target_label->inst_c0 = (targetbb)->native_offset; \
207                 (targetbb)->code = target_label; \
208                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
209                 inst->opcode = op;      \
210                 inst->inst_i0 = target_label;   \
211                 inst->flags = MONO_INST_BRLABEL;        \
212                 mono_bblock_add_inst ((cfg)->cbb, inst); \
213         } while (0)
214
215 #define MONO_EMIT_NEW_BRANCH_LABEL(cfg,op,label) do { \
216                 MonoInst *inst; \
217                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
218                 inst->opcode = op;      \
219                 inst->inst_i0 = label;  \
220                 inst->flags = MONO_INST_BRLABEL;        \
221                 mono_bblock_add_inst ((cfg)->cbb, inst); \
222         } while (0)
223
224 #define MONO_NEW_LABEL(cfg,inst) do { \
225                 (inst) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
226                 (inst)->opcode = OP_LABEL;      \
227         } while (0)
228
229 /* we need to kludge state because monoburg puts this stuff before the definition of MBState */
230 void mini_emit_virtual_call (MonoCompile *s, void *state, MonoInst *tree, int novirt_op, int virtop);
231 void mini_emit_isninst_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
232 void mini_emit_isninst_iface_cast (MonoCompile *s, int vtable_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
233 void mini_emit_isninst_iface_class_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
234 void mini_emit_castclass (MonoCompile *s, int klass_reg, MonoClass *klass);
235 void mini_emit_castclass_iface (MonoCompile *s, int vtable_reg, MonoClass *klass);
236 void mini_emit_castclass_iface_class (MonoCompile *s, int klass_reg, MonoClass *klass);
237
238
239 %%
240
241 %termprefix OP_ CEE_
242
243 %start stmt
244
245 #
246 # base addressing mode 
247 #
248
249 base: reg "0" {
250         /* we create a new MonoInst in chain rules and set state->tree to it
251          * since a MBState (and hence state->tree) is reused in chain rules and
252          * normal rules.
253          */
254         MonoInst *inst;
255         inst = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
256         inst->opcode = OP_ICONST; /* doesn't matter */
257         inst->inst_basereg = state->reg1;
258         inst->inst_offset = 0;
259         state->tree = inst;
260         //g_print ("mybase: (assigned R%d from R%d - R%d)\n", state->reg1, tree->dreg, state->reg2);
261         //tree->inst_offset = 0;
262         //tree->inst_basereg = state->reg1;
263 }
264
265 base: OP_REGOFFSET "0" {
266         /* nothing to do */
267 }
268
269 base: OP_LDADDR (OP_REGOFFSET) "0" {
270         tree->inst_offset = state->left->tree->inst_offset;
271         tree->inst_basereg = state->left->tree->inst_basereg;
272 }
273
274 base: CEE_LDOBJ (OP_REGOFFSET) "0" {
275         tree->inst_offset = state->left->tree->inst_offset;
276         tree->inst_basereg = state->left->tree->inst_basereg;
277 }
278
279 base: CEE_ADD (base, OP_ICONST) "0" {
280         tree->inst_offset = state->left->tree->inst_offset + state->right->tree->inst_c0;
281         tree->inst_basereg = state->left->tree->inst_basereg;
282 }
283
284 #
285 # helpers
286 #
287
288 reg: OP_ICONST {
289         MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_c0);
290 }
291
292 reg: OP_AOTCONST {
293         MONO_EMIT_NEW_AOTCONST (s, state->reg1, tree->inst_p0, tree->inst_c1);
294 }
295
296 #
297 # load/store operations
298 #
299
300 reg: CEE_LDIND_I (base) {
301         MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, state->left->tree->inst_basereg, 
302                                 state->left->tree->inst_offset);
303 }
304
305 reg: CEE_LDIND_REF (base) {
306         MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, state->left->tree->inst_basereg, 
307                                 state->left->tree->inst_offset);
308 }
309
310 reg: CEE_LDIND_I1 (base) {
311         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI1_MEMBASE, state->reg1, 
312                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
313 }
314
315 reg: CEE_LDIND_U1 (base) {
316         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU1_MEMBASE, state->reg1, 
317                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
318 }
319
320 reg: CEE_LDIND_I2 (base) {
321         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI2_MEMBASE, state->reg1, 
322                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
323 }
324
325 reg: CEE_LDIND_U2 (base) {
326         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, 
327                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
328 }
329
330 reg: OP_LDADDR (OP_REGOFFSET) {
331         /* use LEA */
332         tree->opcode = OP_MOVE;
333         tree->sreg1 = state->left->tree->inst_basereg;
334         tree->dreg = state->reg1;
335         mono_bblock_add_inst (s->cbb, tree);
336         if (state->left->tree->inst_offset) {
337                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tree->dreg, tree->dreg, state->left->tree->inst_offset);
338         }
339 }
340
341 reg: CEE_LDOBJ (OP_REGOFFSET) {
342         /* use LEA */
343         /* FIXME: this is just an hack */
344         tree->opcode = OP_MOVE;
345         tree->sreg1 = state->left->tree->inst_basereg;
346         tree->dreg = state->reg1;
347         mono_bblock_add_inst (s->cbb, tree);
348         if (state->left->tree->inst_offset) {
349                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tree->dreg, tree->dreg, state->left->tree->inst_offset);
350         }
351 }
352
353 reg: CEE_LDOBJ (reg) {
354         tree->opcode = OP_MOVE;
355         tree->sreg1 = state->left->reg1;
356         tree->dreg = state->reg1;
357         mono_bblock_add_inst (s->cbb, tree);
358 }
359
360 reg: OP_OBJADDR (reg) {
361         tree->opcode = OP_MOVE;
362         tree->sreg1 = state->left->reg1;
363         tree->dreg = state->reg1;
364         mono_bblock_add_inst (s->cbb, tree);
365 }
366
367 reg: OP_VTADDR (reg) {
368         tree->opcode = OP_MOVE;
369         tree->sreg1 = state->left->reg1;
370         tree->dreg = state->reg1;
371         mono_bblock_add_inst (s->cbb, tree);
372 }
373
374 reg: CEE_LDIND_REF (OP_REGVAR) {
375         tree->opcode = OP_MOVE;
376         tree->sreg1 = state->left->tree->dreg;
377         tree->dreg = state->reg1;
378         mono_bblock_add_inst (s->cbb, tree);
379 }
380
381 reg: CEE_LDIND_I4 (OP_REGVAR) {
382         tree->opcode = OP_MOVE;
383         tree->sreg1 = state->left->tree->dreg;
384         tree->dreg = state->reg1;
385         mono_bblock_add_inst (s->cbb, tree);
386 }
387
388 reg: CEE_LDIND_U4 (OP_REGVAR) {
389         tree->opcode = OP_MOVE;
390         tree->sreg1 = state->left->tree->dreg;
391         tree->dreg = state->reg1;
392         mono_bblock_add_inst (s->cbb, tree);
393 }
394
395 reg: CEE_LDIND_U1 (OP_REGVAR) {
396         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->tree->dreg, 0xff);
397 }
398
399 reg: CEE_LDIND_U2 (OP_REGVAR) {
400         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->tree->dreg, 0xffff);
401 }
402
403 stmt: CEE_STIND_REF (base, reg) {
404         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
405                                  state->left->tree->inst_offset, state->right->reg1);
406 }
407
408 stmt: CEE_STIND_REF (base, CEE_LDIND_REF (OP_REGVAR)) {
409         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
410                                  state->left->tree->inst_offset, state->right->left->tree->dreg);
411 }
412
413 stmt: CEE_STIND_REF (base, OP_ICONST) {
414         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STORE_MEMBASE_IMM, state->left->tree->inst_basereg,
415                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
416 }
417
418 stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF (OP_REGVAR)) {
419         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->left->tree->dreg);
420 }
421
422
423 stmt: CEE_STIND_I (base, reg) {
424         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
425                                  state->left->tree->inst_offset, state->right->reg1);
426 }
427
428 stmt: CEE_STIND_I (base, OP_ICONST) {
429         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STORE_MEMBASE_IMM, state->left->tree->inst_basereg,
430                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
431 }
432
433 reg: CEE_LDIND_I4 (base) {
434         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
435                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
436 }
437
438 reg: CEE_LDIND_U4 (base) {
439         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU4_MEMBASE, state->reg1, 
440                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
441 }
442
443 reg: CEE_LDIND_I4 (OP_REGVAR) {
444         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
445 }
446
447 reg: CEE_LDIND_U4 (OP_REGVAR) {
448         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
449 }
450
451 reg: CEE_LDIND_I (OP_REGVAR) {
452         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
453 }
454
455 stmt: CEE_STIND_I4 (base, reg) {
456         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
457                                  state->left->tree->inst_offset, state->right->reg1);
458 }
459
460 stmt: CEE_STIND_I4 (base, CEE_LDIND_I4 (OP_REGVAR)) {
461         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
462                                  state->left->tree->inst_offset, state->right->left->tree->dreg);
463 }
464
465 stmt: CEE_STIND_I4 (base, OP_ICONST) {
466         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
467                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
468 }
469
470 stmt: CEE_STIND_I1 (base, reg) {
471         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI1_MEMBASE_REG, state->left->tree->inst_basereg,
472                                  state->left->tree->inst_offset, state->right->reg1);
473 }
474
475 stmt: CEE_STIND_I1 (base, OP_ICONST) {
476         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI1_MEMBASE_IMM, state->left->tree->inst_basereg,
477                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
478 }
479
480 stmt: CEE_STIND_I2 (base, reg) {
481         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI2_MEMBASE_REG, state->left->tree->inst_basereg,
482                                  state->left->tree->inst_offset, state->right->reg1);
483 }
484
485 stmt: CEE_STIND_I2 (base, OP_ICONST) {
486         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI2_MEMBASE_IMM, state->left->tree->inst_basereg,
487                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
488 }
489
490 stmt: CEE_STIND_I4 (OP_REGVAR, reg) {
491         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
492 }
493
494 stmt: CEE_STIND_I2 (OP_REGVAR, reg) {
495         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->reg1, 0xffff);
496 }
497
498 stmt: CEE_STIND_I1 (OP_REGVAR, reg) {
499         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->reg1, 0xff);
500 }
501
502 stmt: CEE_STIND_I1 (OP_REGVAR, CEE_LDIND_U1 (OP_REGVAR)) {
503         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xff);
504 }
505
506 stmt: CEE_STIND_I1 (OP_REGVAR, CEE_LDIND_I1 (OP_REGVAR)) {
507         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xff);
508 }
509
510 stmt: CEE_STIND_I2 (OP_REGVAR, CEE_LDIND_U2 (OP_REGVAR)) {
511         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xffff);
512 }
513
514 stmt: CEE_STIND_I2 (OP_REGVAR, CEE_LDIND_I2 (OP_REGVAR)) {
515         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xffff);
516 }
517
518 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (OP_REGVAR)) {
519         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->left->tree->dreg);
520 }
521
522 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (base)) {
523         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->left->tree->dreg, 
524                                    state->right->left->tree->inst_basereg, 
525                                    state->right->left->tree->inst_offset);
526 }
527
528 stmt: CEE_STIND_I4 (OP_REGVAR, OP_ICONST) {
529         tree->opcode = OP_ICONST;
530         tree->dreg = state->left->tree->dreg;
531         tree->inst_c0 = state->right->tree->inst_c0;
532         mono_bblock_add_inst (s->cbb, tree);
533 }
534
535 stmt: CEE_STIND_REF (OP_REGVAR, reg) {
536         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
537 }
538
539 stmt: CEE_STIND_REF (OP_REGVAR, OP_ICONST) {
540         tree->opcode = OP_ICONST;
541         tree->dreg = state->left->tree->dreg;
542         tree->inst_c0 = state->right->tree->inst_c0;
543         mono_bblock_add_inst (s->cbb, tree);
544 }
545
546 stmt: CEE_STIND_I (OP_REGVAR, reg) {
547         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
548 }
549
550 stmt: CEE_STELEM_REF (OP_GROUP (reg, reg), reg) {
551
552         g_assert_not_reached ();
553 }
554
555 reg: OP_GROUP (reg, reg) {
556         g_assert_not_reached ();
557 }
558
559 stmt: OP_MEMCPY (reg, reg) {
560         int size = tree->unused;
561         int cur_reg;
562         int cur_offset = 0;
563         /* FIXME: consider alignment for archs that need it. */
564         while (size > 0) {
565                 cur_reg = mono_regstate_next_int (s->rs);
566                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, cur_reg,
567                         state->right->reg1, cur_offset);
568                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->reg1, cur_offset, cur_reg);
569                 cur_offset += 4;
570                 size -= 4;
571         }
572         while (size > 0) {
573                 cur_reg = mono_regstate_next_int (s->rs);
574                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI2_MEMBASE, cur_reg,
575                         state->right->reg1, cur_offset);
576                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, state->left->reg1, cur_offset, cur_reg);
577                 cur_offset += 2;
578                 size -= 2;
579         }
580         while (size > 0) {
581                 cur_reg = mono_regstate_next_int (s->rs);
582                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI1_MEMBASE, cur_reg,
583                         state->right->reg1, cur_offset);
584                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, state->left->reg1, cur_offset, cur_reg);
585                 cur_offset += 1;
586                 size -= 1;
587         }
588 }
589
590 reg: OP_LDELEMA2D (reg, OP_GROUP (reg, reg)) "20" {
591         int bounds_reg = mono_regstate_next_int (s->rs);
592         int add_reg = mono_regstate_next_int (s->rs);
593         int mult_reg = mono_regstate_next_int (s->rs);
594         int mult2_reg = mono_regstate_next_int (s->rs);
595         int low1_reg = mono_regstate_next_int (s->rs);
596         int low2_reg = mono_regstate_next_int (s->rs);
597         int high1_reg = mono_regstate_next_int (s->rs);
598         int high2_reg = mono_regstate_next_int (s->rs);
599         int realidx1_reg = mono_regstate_next_int (s->rs);
600         int realidx2_reg = mono_regstate_next_int (s->rs);
601         int sum_reg = mono_regstate_next_int (s->rs);
602         int index1, index2;
603         guint32 size = mono_array_element_size (tree->klass);
604         
605         index1 = state->right->left->reg1;
606         index2 = state->right->right->reg1;
607
608         /* range checking */
609         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, bounds_reg, 
610                                        state->left->reg1, G_STRUCT_OFFSET (MonoArray, bounds));
611
612         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, low1_reg, 
613                                        bounds_reg, G_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
614         MONO_EMIT_NEW_BIALU (s, CEE_SUB, realidx1_reg, index1, low1_reg);
615         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, high1_reg, 
616                                        bounds_reg, G_STRUCT_OFFSET (MonoArrayBounds, length));
617         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, high1_reg, realidx1_reg);
618         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
619
620         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, low2_reg, 
621                                        bounds_reg, sizeof (MonoArrayBounds) + G_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
622         MONO_EMIT_NEW_BIALU (s, CEE_SUB, realidx2_reg, index2, low2_reg);
623         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, high2_reg, 
624                                        bounds_reg, sizeof (MonoArrayBounds) + G_STRUCT_OFFSET (MonoArrayBounds, length));
625         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, high2_reg, realidx2_reg);
626         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
627
628         MONO_EMIT_NEW_BIALU (s, CEE_MUL, mult_reg, high2_reg, realidx1_reg);
629         MONO_EMIT_NEW_BIALU (s, CEE_ADD, sum_reg, mult_reg, realidx2_reg);
630         MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult2_reg, sum_reg, size);
631         MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult2_reg, state->left->reg1);
632         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
633 }
634
635 #
636 # conversions: conv_u can be implemented with AND, also all _ovf conversions?
637 #
638
639 reg: CEE_CONV_I1 (reg) {
640         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
641 }
642
643 reg: CEE_CONV_I2 (reg) {
644         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
645 }
646
647 reg: CEE_CONV_I4 (reg) {
648         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
649 }
650
651 reg: CEE_CONV_U1 (reg) {
652         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
653 }
654
655 reg: CEE_CONV_U2 (reg) {
656         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
657 }
658
659 reg: CEE_CONV_U4 (reg) {
660         if (sizeof (void *) == 8) {
661                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
662         } else {
663                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
664         }
665 }
666
667 reg: CEE_CONV_U (reg) {
668         if (sizeof (void *) == 8) {
669                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
670         } else {
671                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
672         }
673 }
674
675 reg: CEE_CONV_I (reg) {
676         if (sizeof (void *) == 8) {
677                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
678         } else {
679                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
680         }
681 }
682
683 reg: CEE_CONV_OVF_I4 (reg) {
684         if (sizeof (void *) == 8) {
685                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
686         } else {
687                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
688         }
689 }
690
691 reg: CEE_CONV_OVF_U4 (reg) {
692         if (sizeof (void *) == 8) {
693                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
694         } else {
695                 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */              
696                 MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
697                 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
698                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
699         }
700 }
701
702 reg: CEE_CONV_OVF_I4_UN (reg) {
703         if (sizeof (void *) == 8) {
704                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
705         } else {
706                 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
707                 MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
708                 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
709                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
710         }
711 }
712
713 reg: CEE_CONV_OVF_I1 (reg) {     
714         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
715         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
716         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
717         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
718         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
719 }
720
721 reg: CEE_CONV_OVF_I1_UN (reg) {
722         /* probe values between 0 to 127 */
723         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
724         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
725         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
726 }
727
728 reg: CEE_CONV_OVF_U1 (reg) {
729         /* probe value to be within 0 to 255 */
730         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
731         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
732         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
733 }
734
735 reg: CEE_CONV_OVF_U1_UN (reg) {
736         /* probe value to be within 0 to 255 */
737         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
738         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
739         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
740 }
741
742 reg: CEE_CONV_OVF_I2 (reg) {    
743         /* Probe value to be within -32768 and 32767 */
744         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
745         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
746         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
747         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
748         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
749 }
750
751 reg: CEE_CONV_OVF_I2_UN (reg) {
752         /* Convert uint value into short, value within 0 and 32767 */
753         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
754         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
755         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
756 }
757
758 reg: CEE_CONV_OVF_U2 (reg) {
759         /* Probe value to be within 0 and 65535 */
760         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
761         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
762         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
763 }
764
765 reg: CEE_CONV_OVF_U2_UN (reg) {
766         /* Probe value to be within 0 and 65535 */
767         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
768         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
769         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
770 }
771
772 #
773 # basic alu operations
774 #
775
776 reg: CEE_AND (reg, reg) {
777         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
778 }
779
780 reg: CEE_AND (reg, OP_ICONST) {
781         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
782 }
783
784 reg: CEE_OR (reg, reg) {
785         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
786 }
787
788 reg: CEE_OR (reg, OP_ICONST) {
789         MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
790 }
791
792 reg: CEE_XOR (reg, reg) {
793         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
794 }
795
796 reg: CEE_XOR (reg, OP_ICONST) {
797         MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
798 }
799
800 reg: CEE_NEG (reg) {
801         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
802 }
803
804 reg: CEE_NOT (reg) {
805         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
806 }
807
808 reg: CEE_ADD (reg, reg) {
809         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
810 }
811
812 reg: CEE_ADD (reg, OP_ICONST) {
813         MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
814 }
815
816 reg: CEE_ADD_OVF (reg, reg) {
817         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
818         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
819 }
820
821 reg: CEE_ADD_OVF_UN (reg, reg) {
822         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
823         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
824 }
825
826 reg: CEE_SUB (reg, reg) {
827         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
828 }
829
830 reg: CEE_SUB (reg, OP_ICONST) {
831         MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
832 }
833
834 reg: CEE_SUB_OVF (reg, reg) {
835         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
836         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
837 }
838
839 reg: CEE_SUB_OVF_UN (reg, reg) {
840         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
841         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
842 }
843
844 #
845 # mult/div operations
846 #
847
848 reg: CEE_MUL (reg, reg) {
849         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
850 }
851
852 reg: CEE_MUL (reg, OP_ICONST) {
853         MONO_EMIT_BIALU_IMM (s, tree, OP_MUL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
854 }
855
856 reg: CEE_MUL_OVF (reg, reg) {
857         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
858 }
859
860 reg: CEE_MUL_OVF_UN (reg, reg) {
861         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
862 }
863
864 reg: CEE_DIV (reg, reg) {
865         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
866 }
867
868 #reg: CEE_DIV (reg, OP_ICONST) {
869 #       MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
870 #}
871
872 reg: CEE_DIV_UN (reg, reg) {
873         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
874 }
875
876 #reg: CEE_DIV_UN (reg, OP_ICONST) {
877 #       MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
878 #}
879
880 reg: CEE_REM (reg, reg) {
881         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
882 }
883
884 #reg: CEE_REM (reg, OP_ICONST) {
885 #       MONO_EMIT_BIALU_IMM (s, tree, OP_REM_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
886 #}
887
888 reg: CEE_REM_UN (reg, reg) {
889         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
890 }
891
892 #reg: CEE_REM_UN (reg, OP_ICONST) {
893 #       MONO_EMIT_BIALU_IMM (s, tree, OP_REM_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
894 #}
895
896 #
897 # shift operations
898 #
899
900 reg: CEE_SHL (reg, reg) {
901         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
902 }
903
904 reg: CEE_SHL (reg, OP_ICONST) {
905         MONO_EMIT_BIALU_IMM (s, tree, OP_SHL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
906 }
907
908 reg: CEE_SHR (reg, reg) {
909         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
910 }
911
912 reg: CEE_SHR (reg, OP_ICONST) {
913         MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
914 }
915
916 reg: CEE_SHR_UN (reg, reg) {
917         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
918 }
919
920 reg: CEE_SHR_UN (reg, OP_ICONST) {
921         MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
922 }
923
924
925 #
926 # other alu operations
927 #
928
929 reg: OP_CEQ (cflags) {  
930         tree->dreg = state->reg1;
931         mono_bblock_add_inst (s->cbb, tree);
932 }
933
934 reg: OP_CLT (cflags) {  
935         tree->dreg = state->reg1;
936         mono_bblock_add_inst (s->cbb, tree);
937 }
938
939 reg: OP_CLT_UN (cflags) {       
940         tree->dreg = state->reg1;
941         mono_bblock_add_inst (s->cbb, tree);
942 }
943
944 reg: OP_CGT (cflags) {  
945         tree->dreg = state->reg1;
946         mono_bblock_add_inst (s->cbb, tree);
947 }
948
949 reg: OP_CGT_UN (cflags) {       
950         tree->dreg = state->reg1;
951         mono_bblock_add_inst (s->cbb, tree);
952 }
953
954 #
955 # control flow commands 
956 #
957
958 stmt: OP_LABEL {
959         mono_bblock_add_inst (s->cbb, tree);
960 }
961
962 stmt: CEE_NOP "0" {
963 }
964
965 stmt: CEE_BREAK "0" {
966         mono_bblock_add_inst (s->cbb, tree);
967 }
968
969 stmt: CEE_SWITCH (reg) {
970         MonoInst *label;
971         int offset_reg = mono_regstate_next_int (s->rs);
972         int target_reg = mono_regstate_next_int (s->rs);
973         int n = GPOINTER_TO_INT (tree->klass);
974         
975         MONO_NEW_LABEL (s, label);
976         mono_create_jump_table (s, label, tree->inst_many_bb, n);
977
978         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, n);
979         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_many_bb [n]);
980         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, offset_reg, state->left->reg1, 2);
981         mono_bblock_add_inst (s->cbb, label);
982          /* the backend must patch the address. we use 0xf0f0f0f0 to avoid the usage 
983           * of special (short) opcodes on x86 */
984         MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, 0xf0f0f0f0);
985         MONO_EMIT_UNALU (s, tree, OP_BR_REG, -1, target_reg);
986 }
987
988 stmt: CEE_BR "0" {
989         mono_bblock_add_inst (s->cbb, tree);
990 }
991
992 reg: CEE_CALL {
993         tree->dreg = state->reg1;
994         mono_bblock_add_inst (s->cbb, tree);
995 }
996
997 reg: CEE_CALLVIRT (reg) {
998         mini_emit_virtual_call (s, state, tree, CEE_CALL, OP_CALL_MEMBASE);
999 }
1000
1001 stmt: OP_VOIDCALLVIRT (reg) {
1002         mini_emit_virtual_call (s, state, tree, OP_VOIDCALL, OP_VOIDCALL_MEMBASE);
1003 }
1004
1005 lreg: OP_LCALLVIRT (reg) {
1006         mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE);
1007 }
1008
1009 freg: OP_FCALLVIRT (reg) {
1010         mini_emit_virtual_call (s, state, tree, OP_FCALL, OP_FCALL_MEMBASE);
1011 }
1012
1013 stmt: OP_VCALLVIRT (reg, reg) {
1014         mini_emit_virtual_call (s, state, tree, OP_VCALL, OP_VCALL_MEMBASE);
1015 }
1016
1017 reg: OP_CALL_REG (reg) {
1018         tree->sreg1 = state->left->reg1;
1019         tree->dreg = state->reg1;
1020         mono_bblock_add_inst (s->cbb, tree);
1021 }
1022
1023 stmt: OP_VOIDCALL {
1024         mono_bblock_add_inst (s->cbb, tree);
1025 }
1026
1027 stmt: OP_VOIDCALL_REG (reg) {
1028         tree->sreg1 = state->left->reg1;
1029         mono_bblock_add_inst (s->cbb, tree);
1030 }
1031
1032 freg: OP_FCALL {
1033         tree->dreg = state->reg1;
1034         mono_bblock_add_inst (s->cbb, tree);
1035 }
1036
1037 freg: OP_FCALL_REG (reg) {
1038         tree->sreg1 = state->left->reg1;
1039         tree->dreg = state->reg1;
1040         mono_bblock_add_inst (s->cbb, tree);
1041 }
1042
1043 lreg: OP_LCALL {
1044         tree->dreg = state->reg1;
1045         mono_bblock_add_inst (s->cbb, tree);
1046 }
1047
1048 lreg: OP_LCALL_REG (reg) {
1049         tree->sreg1 = state->left->reg1;
1050         tree->dreg = state->reg1;
1051         mono_bblock_add_inst (s->cbb, tree);
1052 }
1053
1054 stmt: OP_VCALL (reg) {
1055         MonoInst *vtarg;
1056         /* FIXME: this is actually arch-specific... */
1057         MONO_INST_NEW (s, vtarg, OP_OUTARG);
1058         vtarg->inst_left = state->left->tree;
1059         vtarg->type = STACK_MP;
1060         vtarg->sreg1 = state->left->reg1;
1061         mono_bblock_add_inst (s->cbb, vtarg);
1062
1063         mono_bblock_add_inst (s->cbb, tree);
1064 }
1065
1066 stmt: OP_VCALL_REG (reg, reg) {
1067         MonoInst *vtarg;
1068         /* FIXME: this is actually arch-specific... */
1069         MONO_INST_NEW (s, vtarg, OP_OUTARG);
1070         vtarg->inst_left = state->right->tree;
1071         vtarg->type = STACK_MP;
1072         vtarg->sreg1 = state->right->reg1;
1073         mono_bblock_add_inst (s->cbb, vtarg);
1074         
1075         tree->sreg1 = state->left->reg1;
1076         mono_bblock_add_inst (s->cbb, tree);
1077 }
1078
1079 stmt: CEE_RET "0" {
1080         mono_bblock_add_inst (s->cbb, tree);
1081 }
1082
1083 cflags: OP_COMPARE (reg, reg) {
1084         tree->sreg1 = state->left->reg1;
1085         tree->sreg2 = state->right->reg1;
1086         mono_bblock_add_inst (s->cbb, tree);
1087 }
1088
1089 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), reg) {
1090         tree->sreg1 = state->left->left->tree->dreg;
1091         tree->sreg2 = state->right->reg1;
1092         mono_bblock_add_inst (s->cbb, tree);
1093 }
1094
1095 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST) {
1096         tree->opcode = OP_COMPARE_IMM;
1097         tree->sreg1 = state->left->left->tree->dreg;
1098         tree->inst_imm = state->right->tree->inst_c0;
1099         mono_bblock_add_inst (s->cbb, tree);
1100 }
1101
1102 cflags: OP_COMPARE (reg, OP_ICONST) {
1103         tree->opcode = OP_COMPARE_IMM;
1104         tree->sreg1 = state->left->reg1;
1105         tree->inst_imm = state->right->tree->inst_c0;
1106         mono_bblock_add_inst (s->cbb, tree);
1107 }
1108
1109 stmt: CEE_BNE_UN (cflags) {
1110         mono_bblock_add_inst (s->cbb, tree);
1111 }
1112
1113 stmt: CEE_BEQ (cflags) {
1114         mono_bblock_add_inst (s->cbb, tree);
1115 }
1116
1117 stmt: CEE_BLT (cflags) {
1118         mono_bblock_add_inst (s->cbb, tree);
1119 }
1120
1121 stmt: CEE_BLT_UN (cflags) {
1122         mono_bblock_add_inst (s->cbb, tree);
1123 }
1124
1125 stmt: CEE_BGT (cflags) {
1126         mono_bblock_add_inst (s->cbb, tree);
1127 }
1128
1129 stmt: CEE_BGT_UN (cflags) {
1130         mono_bblock_add_inst (s->cbb, tree);
1131 }
1132
1133 stmt: CEE_BGE  (cflags) {
1134         mono_bblock_add_inst (s->cbb, tree);
1135 }
1136
1137 stmt: CEE_BGE_UN (cflags) {
1138         mono_bblock_add_inst (s->cbb, tree);
1139 }
1140
1141 stmt: CEE_BLE  (cflags) {
1142         mono_bblock_add_inst (s->cbb, tree);
1143 }
1144
1145 stmt: CEE_BLE_UN (cflags) {
1146         mono_bblock_add_inst (s->cbb, tree);
1147 }
1148
1149 stmt: CEE_POP (reg)
1150
1151 # remove some common pops without side effects
1152 stmt: CEE_POP (OP_ICONST)
1153 stmt: CEE_POP (CEE_LDIND_REF (base))
1154 stmt: CEE_POP (CEE_LDIND_I4 (base))
1155 stmt: CEE_POP (CEE_LDIND_U1 (base))
1156
1157 stmt: CEE_JMP "0" {
1158         mono_bblock_add_inst (s->cbb, tree);
1159 }
1160
1161 # exception handling
1162
1163 stmt: CEE_THROW (reg) {
1164         MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->reg1);
1165 }
1166
1167 stmt: CEE_THROW (CEE_LDIND_REF (OP_REGVAR)) {
1168         MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->left->tree->dreg);
1169 }
1170
1171 stmt: OP_CALL_HANDLER {
1172         mono_bblock_add_inst (s->cbb, tree);
1173 }
1174
1175 stmt: OP_START_HANDLER "2" {
1176         mono_bblock_add_inst (s->cbb, tree);
1177 }
1178
1179 stmt: CEE_ENDFINALLY "2" {
1180         mono_bblock_add_inst (s->cbb, tree);
1181 }
1182
1183 stmt: OP_ENDFILTER (reg) "2" {
1184         MONO_EMIT_UNALU (s, tree, OP_ENDFILTER, -1, state->left->reg1);
1185 }
1186
1187 stmt: OP_CHECK_THIS (reg) {
1188         mono_bblock_add_inst (s->cbb, tree);
1189 }
1190
1191 # object related opcodes 
1192
1193 reg: CEE_ISINST (reg) {
1194         MonoClass *klass = tree->inst_newa_class;
1195         MonoInst *object_is_null, *end_label, *false_label;
1196         int obj_reg = state->left->reg1;
1197         int vtable_reg = mono_regstate_next_int (s->rs);
1198
1199         MONO_NEW_LABEL (s, object_is_null);
1200         MONO_NEW_LABEL (s, end_label);
1201         MONO_NEW_LABEL (s, false_label);
1202
1203         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1204         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1205
1206         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1207                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1208                 /* the object_is_null target simply copies the input register to the output */
1209                 mini_emit_isninst_iface_cast (s, vtable_reg, klass, false_label, object_is_null);
1210         } else {
1211                 int klass_reg = mono_regstate_next_int (s->rs);
1212
1213                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1214                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1215
1216                 if (klass->rank) {
1217                         int rank_reg = mono_regstate_next_int (s->rs);
1218                         int eclass_reg = mono_regstate_next_int (s->rs);
1219
1220                         MONO_EMIT_NEW_LOAD_MEMBASE (s, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1221                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
1222                         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
1223                         MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, cast_class));
1224                         if (klass->cast_class == mono_defaults.object_class) {
1225                                 int parent_reg = mono_regstate_next_int (s->rs);
1226                                 int const_reg;
1227                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, parent_reg, eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
1228                                 if (mono_compile_aot) {
1229                                         const_reg = mono_regstate_next_int (s->rs);
1230                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1231                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, parent_reg, const_reg);
1232                                 } else {
1233                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
1234                                 }
1235                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, object_is_null);
1236                                 if (mono_compile_aot) {
1237                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1238                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1239                                 } else {
1240                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1241                                 }
1242                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1243                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
1244                         } else if (klass->cast_class == mono_defaults.enum_class->parent) {
1245                                 int const_reg;
1246                                 
1247                                 if (mono_compile_aot) {
1248                                         const_reg = mono_regstate_next_int (s->rs);
1249                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1250                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1251                                 } else {
1252                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
1253                                 }
1254                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1255                                 if (mono_compile_aot) {
1256                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1257                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1258                                 } else {
1259                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1260                                 }
1261                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1262                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
1263                         } else if (klass->cast_class == mono_defaults.enum_class) {
1264                                 if (mono_compile_aot) {
1265                                         int const_reg = mono_regstate_next_int (s->rs);
1266                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1267                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1268                                 } else {
1269                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1270                                 }
1271                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1272                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
1273                         } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1274                                 mini_emit_isninst_iface_class_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
1275                         } else {
1276                                 /* the object_is_null target simply copies the input register to the output */
1277                                 mini_emit_isninst_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
1278                         }
1279                 } else {
1280
1281                         if (klass->marshalbyref) {
1282                                 MonoInst *no_proxy;
1283
1284                                 MONO_NEW_LABEL (s, no_proxy);
1285
1286                                 if (mono_compile_aot) {
1287                                         int tproxy_reg = mono_regstate_next_int (s->rs);
1288                                         MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1289                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1290                                 } else {
1291                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1292                                 }
1293                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, no_proxy);
1294                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, klass));
1295                                 mono_bblock_add_inst (s->cbb, no_proxy);
1296                         }
1297                      
1298                         /* the object_is_null target simply copies the input register to the output */
1299                         mini_emit_isninst_cast (s, klass_reg, klass, false_label, object_is_null);
1300                 }
1301         }
1302
1303         mono_bblock_add_inst (s->cbb, false_label);
1304         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
1305         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1306         mono_bblock_add_inst (s->cbb, object_is_null);
1307         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1308         mono_bblock_add_inst (s->cbb, end_label);
1309 }
1310
1311 reg: OP_UNBOXCAST (reg) {
1312         MonoClass *klass = tree->inst_newa_class;
1313         int obj_reg = state->left->reg1;
1314         int vtable_reg = mono_regstate_next_int (s->rs);
1315         int klass_reg = mono_regstate_next_int (s->rs);
1316         int eclass_reg = mono_regstate_next_int (s->rs);
1317
1318         MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1319         MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1320         MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, element_class));
1321         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, klass->element_class);
1322         
1323         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1324         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1325 }
1326
1327 reg: CEE_CASTCLASS (reg) {
1328         MonoClass *klass = tree->inst_newa_class;
1329         MonoInst *object_is_null;
1330         int obj_reg = state->left->reg1;
1331         int vtable_reg = mono_regstate_next_int (s->rs);
1332
1333         MONO_NEW_LABEL (s, object_is_null);
1334
1335         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1336         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1337
1338         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1339                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1340                 mini_emit_castclass_iface (s, vtable_reg, klass);
1341         } else {
1342                 int klass_reg = mono_regstate_next_int (s->rs);
1343
1344                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1345                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1346
1347                 if (klass->rank) {
1348                         int rank_reg = mono_regstate_next_int (s->rs);
1349                         int eclass_reg = mono_regstate_next_int (s->rs);
1350
1351                         MONO_EMIT_NEW_LOAD_MEMBASE (s, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1352                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
1353                         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1354                         MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, cast_class));
1355                         if (klass->cast_class == mono_defaults.object_class) {
1356                                 int parent_reg = mono_regstate_next_int (s->rs);
1357                                 int const_reg;
1358                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, parent_reg, eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
1359                                 if (mono_compile_aot) {
1360                                         const_reg = mono_regstate_next_int (s->rs);
1361                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1362                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, parent_reg, const_reg);
1363                                 } else {
1364                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
1365                                 }
1366                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, object_is_null);
1367                                 if (mono_compile_aot) {
1368                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1369                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1370                                 } else {
1371                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1372                                 }
1373                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1374                         } else if (klass->cast_class == mono_defaults.enum_class->parent) {
1375                                 int const_reg = mono_regstate_next_int (s->rs);
1376                                 if (mono_compile_aot) {
1377                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1378                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1379                                 } else {
1380                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
1381                                 }
1382                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1383                                 if (mono_compile_aot) {
1384                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1385                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1386                                 } else {
1387                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1388                                 }
1389                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1390                         } else if (klass->cast_class == mono_defaults.enum_class) {
1391                                 if (mono_compile_aot) {
1392                                         int const_reg = mono_regstate_next_int (s->rs);
1393                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1394                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1395                                 } else {
1396                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1397                                 }
1398                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1399                         } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1400                                 mini_emit_castclass_iface_class (s, eclass_reg, klass->cast_class);
1401                         } else {
1402                                 mini_emit_castclass (s, eclass_reg, klass->cast_class);
1403                         }
1404                 } else {
1405
1406                         if (klass->marshalbyref) {
1407                                 MonoInst *no_proxy;
1408
1409                                 MONO_NEW_LABEL (s, no_proxy);
1410
1411                                 if (mono_compile_aot) {
1412                                         int tproxy_reg = mono_regstate_next_int (s->rs);
1413                                         MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1414                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1415                                 } else {
1416                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1417                                 }
1418                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, no_proxy);
1419                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, klass));
1420                                 mono_bblock_add_inst (s->cbb, no_proxy);
1421                         }
1422                      
1423                         mini_emit_castclass (s, klass_reg, klass);
1424                 }
1425         }
1426
1427         mono_bblock_add_inst (s->cbb, object_is_null);
1428         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1429 }
1430
1431 reg: CEE_NEWARR (reg) {
1432         g_assert_not_reached ();
1433 }
1434
1435 lreg: OP_LMUL (lreg, lreg) {
1436         g_assert_not_reached ();
1437 }
1438
1439 lreg: OP_LMUL_OVF (lreg, lreg) {
1440         g_assert_not_reached ();
1441 }
1442
1443 lreg: OP_LMUL_OVF_UN (lreg, lreg) {
1444         g_assert_not_reached ();
1445 }
1446
1447 lreg: OP_LDIV (lreg, lreg) {
1448         g_assert_not_reached ();
1449 }
1450
1451 lreg: OP_LDIV_UN (lreg, lreg) {
1452         g_assert_not_reached ();
1453 }
1454
1455 lreg: OP_LREM (lreg, lreg) {
1456         g_assert_not_reached ();
1457 }
1458
1459 lreg: OP_LREM_UN (lreg, lreg) {
1460         g_assert_not_reached ();
1461 }
1462
1463 lreg: OP_LSHL (lreg, reg) {
1464         g_assert_not_reached ();
1465 }
1466
1467 lreg: OP_LSHR (lreg, reg) {
1468         g_assert_not_reached ();
1469 }
1470
1471 lreg: OP_LSHR_UN (lreg, reg) {
1472         g_assert_not_reached ();
1473 }
1474
1475 reg: CEE_UNBOX (reg) {
1476         int vtable_reg = mono_regstate_next_int (s->rs);
1477         int class_reg = mono_regstate_next_int (s->rs);
1478         int element_class_reg = mono_regstate_next_int (s->rs);
1479
1480         MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1481         MONO_EMIT_NEW_LOAD_MEMBASE (s, class_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1482         MONO_EMIT_NEW_LOAD_MEMBASE (s, element_class_reg, class_reg, G_STRUCT_OFFSET (MonoClass, element_class));
1483
1484         if (mono_compile_aot) {
1485                 /* fixme: make it work with the AOT compiler */
1486                 g_assert_not_reached ();
1487         } else {
1488                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, element_class_reg, tree->inst_newa_class);
1489         }
1490
1491         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1492         MONO_EMIT_BIALU_IMM (s, tree, CEE_ADD, state->reg1, state->left->reg1, sizeof (MonoObject));
1493         g_warning ("untested code!!");
1494 }
1495
1496 #
1497 # string support
1498 #
1499 reg: OP_GETCHR (reg, reg) {
1500         int length_reg = mono_regstate_next_int (s->rs);
1501         int mult_reg = mono_regstate_next_int (s->rs);
1502         int add_reg = mono_regstate_next_int (s->rs);
1503         
1504         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, length_reg, 
1505                                        state->left->reg1, G_STRUCT_OFFSET (MonoString, length));
1506         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, length_reg, state->right->reg1);
1507         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
1508
1509         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, mult_reg, state->right->reg1, 1);
1510         MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
1511         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI2_MEMBASE, state->reg1, 
1512                                    add_reg, G_STRUCT_OFFSET (MonoString, chars));
1513 }
1514
1515 reg: OP_GETCHR (reg, OP_ICONST) {
1516         int length_reg = mono_regstate_next_int (s->rs);
1517         int ind;
1518
1519         MONO_EMIT_NEW_LOAD_MEMBASE (s, length_reg, state->left->reg1, G_STRUCT_OFFSET (MonoString, length));
1520         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, length_reg, state->right->tree->inst_c0);
1521         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
1522        
1523         ind = 2 * state->right->tree->inst_c0 + G_STRUCT_OFFSET (MonoString, chars);
1524         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI2_MEMBASE, state->reg1, state->left->reg1, ind);
1525 }
1526
1527 #
1528 # array support
1529 #
1530 reg: CEE_LDLEN (reg) {  
1531         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
1532                                    state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1533 }
1534
1535 reg: CEE_LDELEMA (reg, OP_ICONST) "15" {
1536         int length_reg = mono_regstate_next_int (s->rs);
1537         guint32 size = mono_class_array_element_size (tree->klass);
1538         int ind;
1539
1540         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, length_reg, 
1541                                        state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1542         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, length_reg, state->right->tree->inst_c0);
1543         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
1544        
1545         ind = size * state->right->tree->inst_c0 + G_STRUCT_OFFSET (MonoArray, vector);
1546         
1547         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, ind);
1548 }
1549
1550 reg: CEE_LDELEMA (reg, reg) "20" {
1551         int length_reg = mono_regstate_next_int (s->rs);
1552         int mult_reg = mono_regstate_next_int (s->rs);
1553         int add_reg = mono_regstate_next_int (s->rs);
1554         guint32 size = mono_class_array_element_size (tree->klass);
1555         
1556         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, length_reg, 
1557                                        state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1558         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, length_reg, state->right->reg1);
1559         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
1560
1561         MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult_reg, state->right->reg1, size);
1562         MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
1563         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
1564 }
1565
1566 %%
1567
1568 void 
1569 mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop)
1570 {
1571         MonoInst *this, *vtarg;
1572         MonoMethod *method = ((MonoCallInst*)tree)->method;
1573         int vtable_reg, slot_reg;
1574         MBState *state = st;
1575
1576         /* add the this argument */
1577         MONO_INST_NEW (cfg, this, OP_OUTARG);
1578         this->inst_left = state->left->tree;
1579         this->type = this->inst_left->type;
1580         this->sreg1 = state->left->reg1;
1581         mono_bblock_add_inst (cfg->cbb, this);
1582
1583         if (novirtop == OP_VCALL) {
1584                 /* FIXME: this is actually arch-specific... */
1585                 MONO_INST_NEW (cfg, vtarg, OP_OUTARG);
1586                 vtarg->inst_left = state->right->tree;
1587                 vtarg->type = STACK_MP;
1588                 vtarg->sreg1 = state->right->reg1;
1589                 mono_bblock_add_inst (cfg->cbb, vtarg);
1590         }
1591
1592         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) || 
1593             ((method->flags & METHOD_ATTRIBUTE_FINAL) && 
1594              method->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)) {
1595                 /* 
1596                  * the method is not virtual, we just need to ensure this is not null
1597                  * and then we can call the method directly.
1598                  */
1599                 if (method->klass->marshalbyref || method->klass == mono_defaults.object_class) {
1600                         method = ((MonoCallInst*)tree)->method = mono_marshal_get_remoting_invoke_with_check (method);
1601                 }
1602
1603                 if (!method->string_ctor)
1604                         MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_THIS, -1, this->sreg1);
1605
1606                 tree->dreg = state->reg1;
1607                 tree->opcode = novirtop;
1608                 mono_bblock_add_inst (cfg->cbb, tree);
1609                 return;
1610         }
1611
1612         vtable_reg = mono_regstate_next_int (cfg->rs);
1613         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this->sreg1, G_STRUCT_OFFSET (MonoObject, vtable));
1614         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1615                 int ifoffset_reg = mono_regstate_next_int (cfg->rs);
1616                 slot_reg = mono_regstate_next_int (cfg->rs);
1617                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ifoffset_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_offsets));
1618                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, slot_reg, ifoffset_reg, method->klass->interface_id << 2);
1619                 tree->inst_offset = method->slot << 2;
1620                 cfg->disable_aot = TRUE;
1621         } else {
1622                 slot_reg = vtable_reg;
1623                 tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (method->slot << 2);
1624         }
1625         
1626         tree->dreg = state->reg1;
1627         tree->opcode = virtop;
1628         tree->sreg1 = slot_reg;
1629         mono_bblock_add_inst (cfg->cbb, tree);
1630 }
1631
1632 void 
1633 mini_emit_isninst_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1634 {
1635         int idepth_reg = mono_regstate_next_int (s->rs);
1636         int stypes_reg = mono_regstate_next_int (s->rs);
1637         int stype = mono_regstate_next_int (s->rs);
1638
1639         if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1640                 MONO_EMIT_NEW_LOAD_MEMBASE (s, idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
1641                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1642                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1643         }
1644         MONO_EMIT_NEW_LOAD_MEMBASE (s, stypes_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, supertypes));
1645         MONO_EMIT_NEW_LOAD_MEMBASE (s, stype, stypes_reg, ((klass->idepth - 1) << 2));
1646         if (mono_compile_aot) {
1647                 int const_reg = mono_regstate_next_int (s->rs);
1648                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1649                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, stype, const_reg);
1650         } else {
1651                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, stype, klass);
1652         }
1653         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, true_target);
1654 }
1655
1656 void 
1657 mini_emit_isninst_iface_cast (MonoCompile *s, int vtable_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1658 {
1659         int max_iid_reg = mono_regstate_next_int (s->rs);
1660         int ioffset_reg = mono_regstate_next_int (s->rs);
1661         int intf_reg = mono_regstate_next_int (s->rs);
1662                 
1663         s->disable_aot = TRUE;
1664
1665         MONO_EMIT_NEW_LOAD_MEMBASE (s, max_iid_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
1666         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1667         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1668         MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_offsets));
1669         MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id << 2);
1670         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1671         /* the object_is_null target simply copies the input register to the output */
1672         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, true_target);
1673 }
1674
1675 /*
1676  * Variant of the aboce that takes a register to the class, not the vtable.
1677  * Note that inside interfaces_offsets the empty value is -1, not NULL, in this case.
1678  */
1679 void 
1680 mini_emit_isninst_iface_class_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1681 {
1682         int max_iid_reg = mono_regstate_next_int (s->rs);
1683         int ioffset_reg = mono_regstate_next_int (s->rs);
1684         int intf_reg = mono_regstate_next_int (s->rs);
1685                 
1686         s->disable_aot = TRUE;
1687
1688         MONO_EMIT_NEW_LOAD_MEMBASE (s, max_iid_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, max_interface_id));
1689         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1690         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1691         MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, interface_offsets));
1692         MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id << 2);
1693         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1694         /* the object_is_null target simply copies the input register to the output */
1695         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE, true_target);
1696 }
1697
1698 void 
1699 mini_emit_castclass (MonoCompile *s, int klass_reg, MonoClass *klass)
1700 {
1701         int idepth_reg = mono_regstate_next_int (s->rs);
1702         int stypes_reg = mono_regstate_next_int (s->rs);
1703         int stype = mono_regstate_next_int (s->rs);
1704
1705         if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1706                 MONO_EMIT_NEW_LOAD_MEMBASE (s, idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
1707                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1708                 MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1709         }
1710         MONO_EMIT_NEW_LOAD_MEMBASE (s, stypes_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, supertypes));
1711         MONO_EMIT_NEW_LOAD_MEMBASE (s, stype, stypes_reg, ((klass->idepth - 1) << 2));
1712         if (mono_compile_aot) {
1713                 int const_reg = mono_regstate_next_int (s->rs);
1714                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1715                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, stype, const_reg);
1716         } else {
1717                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, stype, klass);
1718         }
1719         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1720 }
1721
1722 void 
1723 mini_emit_castclass_iface (MonoCompile *s, int vtable_reg, MonoClass *klass)
1724 {
1725         int max_iid_reg = mono_regstate_next_int (s->rs);
1726         int ioffset_reg = mono_regstate_next_int (s->rs);
1727         int intf_reg = mono_regstate_next_int (s->rs);
1728                 
1729         s->disable_aot = TRUE;
1730
1731         MONO_EMIT_NEW_LOAD_MEMBASE (s, max_iid_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
1732         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1733         MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1734         MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_offsets));
1735         MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id << 2);
1736         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1737         MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
1738 }
1739
1740 /*
1741  * Variant of the aboce that takes a register to the class, not the vtable.
1742  * Note that inside interfaces_offsets the empty value is -1, not NULL, in this case.
1743  */
1744 void 
1745 mini_emit_castclass_iface_class (MonoCompile *s, int klass_reg, MonoClass *klass)
1746 {
1747         int max_iid_reg = mono_regstate_next_int (s->rs);
1748         int ioffset_reg = mono_regstate_next_int (s->rs);
1749         int intf_reg = mono_regstate_next_int (s->rs);
1750                 
1751         s->disable_aot = TRUE;
1752
1753         MONO_EMIT_NEW_LOAD_MEMBASE (s, max_iid_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, max_interface_id));
1754         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1755         MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1756         MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, interface_offsets));
1757         MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id << 2);
1758         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1759         MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
1760 }
1761