This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[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 #include <config.h>
12 #include <string.h>
13
14 #include "mini.h"
15 #include <mono/metadata/marshal.h>
16 #include <mono/metadata/debug-helpers.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_I8CONST(cfg,dr,imm) do { \
189                 MonoInst *inst; \
190                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
191                 inst->opcode = OP_I8CONST;      \
192                 inst->dreg = dr; \
193                 inst->inst_l = imm; \
194                 mono_bblock_add_inst ((cfg)->cbb, inst); \
195         } while (0)
196
197 #define MONO_EMIT_NEW_PCONST(cfg,dr,imm) do { \
198                 MonoInst *inst; \
199                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
200                 inst->opcode = OP_ICONST;       \
201                 inst->dreg = dr; \
202                 inst->inst_p0 = (gpointer) imm; \
203                 mono_bblock_add_inst ((cfg)->cbb, inst); \
204         } while (0)
205
206 #define MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,type) do { \
207                 MonoInst *inst; \
208                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
209                 inst->opcode = OP_AOTCONST;     \
210                 inst->dreg = dr; \
211                 inst->inst_p0 = imm; \
212                 inst->inst_c1 = type; \
213                 mono_bblock_add_inst ((cfg)->cbb, inst); \
214         } while (0)
215
216 #define MONO_EMIT_NEW_CLASSCONST(cfg,dr,imm) MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,MONO_PATCH_INFO_CLASS)
217
218 #define MONO_EMIT_NEW_BRANCH_BLOCK(cfg,op,targetbb) do { \
219                 MonoInst *inst; \
220                 MonoInst *target_label; \
221                 target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
222                 target_label->opcode = OP_LABEL;        \
223                 target_label->next = (targetbb)->code; \
224                 target_label->inst_c0 = (targetbb)->native_offset; \
225                 (targetbb)->code = target_label; \
226                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
227                 inst->opcode = op;      \
228                 inst->inst_i0 = target_label;   \
229                 inst->flags = MONO_INST_BRLABEL;        \
230                 mono_bblock_add_inst ((cfg)->cbb, inst); \
231         } while (0)
232
233 #define MONO_EMIT_NEW_BRANCH_LABEL(cfg,op,label) do { \
234                 MonoInst *inst; \
235                 inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
236                 inst->opcode = op;      \
237                 inst->inst_i0 = label;  \
238                 inst->flags = MONO_INST_BRLABEL;        \
239                 mono_bblock_add_inst ((cfg)->cbb, inst); \
240         } while (0)
241
242 #define MONO_NEW_LABEL(cfg,inst) do { \
243                 (inst) = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));       \
244                 (inst)->opcode = OP_LABEL;      \
245         } while (0)
246
247 #define MONO_EMIT_BOUNDS_CHECK(cfg, array_reg, array_type, array_length_field, index_reg) do { \
248                 if (! (state->tree->flags & MONO_INST_NORANGECHECK)) { \
249                         int _length_reg = mono_regstate_next_int (cfg->rs); \
250                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, G_STRUCT_OFFSET (array_type, array_length_field)); \
251                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, _length_reg, index_reg); \
252                         MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
253                 } \
254         } while (0)
255
256 #define MONO_EMIT_BOUNDS_CHECK_IMM(cfg, array_reg, array_type, array_length_field, index_imm) do { \
257                 if (! (state->tree->flags & MONO_INST_NORANGECHECK)) { \
258                         int _length_reg = mono_regstate_next_int (cfg->rs); \
259                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, _length_reg, array_reg, G_STRUCT_OFFSET (array_type, array_length_field)); \
260                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, _length_reg, index_imm); \
261                         MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException"); \
262                 } \
263         } while (0)
264
265 /* we need to kludge state because monoburg puts this stuff before the definition of MBState */
266 void mini_emit_virtual_call (MonoCompile *s, void *state, MonoInst *tree, int novirt_op, int virtop);
267 void mini_emit_isninst_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
268 void mini_emit_isninst_iface_cast (MonoCompile *s, int vtable_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
269 void mini_emit_isninst_iface_class_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target);
270 void mini_emit_castclass (MonoCompile *s, int klass_reg, MonoClass *klass);
271 void mini_emit_castclass_iface (MonoCompile *s, int vtable_reg, MonoClass *klass);
272 void mini_emit_castclass_iface_class (MonoCompile *s, int klass_reg, MonoClass *klass);
273
274 void mini_emit_memcpy (MonoCompile *s, int destreg, int doffset, int srcreg, int soffset, int size, int align);
275 void mini_emit_memset (MonoCompile *s, int destreg, int offset, int size, int val, int align);
276
277 %%
278
279 %termprefix OP_ CEE_
280
281 %start stmt
282
283 #
284 # base addressing mode 
285 #
286
287 base: reg "0" {
288         /* we create a new MonoInst in chain rules and set state->tree to it
289          * since a MBState (and hence state->tree) is reused in chain rules and
290          * normal rules.
291          */
292         MonoInst *inst;
293         inst = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
294         inst->opcode = OP_ICONST; /* doesn't matter */
295         inst->inst_basereg = state->reg1;
296         inst->inst_offset = 0;
297         state->tree = inst;
298         //g_print ("mybase: (assigned R%d from R%d - R%d)\n", state->reg1, tree->dreg, state->reg2);
299         //tree->inst_offset = 0;
300         //tree->inst_basereg = state->reg1;
301 }
302
303 base: CEE_LDIND_I (OP_REGVAR) "0" {
304         tree->inst_offset = 0;
305         tree->inst_basereg = state->left->tree->dreg;
306 }
307
308 base: OP_REGOFFSET "0" {
309         /* nothing to do */
310 }
311
312 base: OP_LDADDR (OP_REGOFFSET) "0" {
313         tree->inst_offset = state->left->tree->inst_offset;
314         tree->inst_basereg = state->left->tree->inst_basereg;
315 }
316
317 base: CEE_LDOBJ (OP_REGOFFSET) "0" {
318         tree->inst_offset = state->left->tree->inst_offset;
319         tree->inst_basereg = state->left->tree->inst_basereg;
320 }
321
322 base: CEE_ADD (base, OP_ICONST) "0" {
323         tree->inst_offset = state->left->tree->inst_offset + state->right->tree->inst_c0;
324         tree->inst_basereg = state->left->tree->inst_basereg;
325 }
326
327 base: CEE_ADD (CEE_LDIND_REF (OP_REGVAR), OP_ICONST) "0" {
328         tree->inst_offset = state->right->tree->inst_c0;
329         tree->inst_basereg = state->left->left->tree->dreg;
330 }
331
332 base: CEE_ADD (CEE_LDIND_I (OP_REGVAR), OP_ICONST) "0" {
333         tree->inst_offset = state->right->tree->inst_c0;
334         tree->inst_basereg = state->left->left->tree->dreg;
335 }
336
337 #
338 # helpers
339 #
340
341 reg: OP_ICONST {
342         MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_c0);
343 }
344
345 reg: OP_AOTCONST {
346         MONO_EMIT_NEW_AOTCONST (s, state->reg1, tree->inst_p0, tree->inst_c1);
347 }
348
349 #
350 # load/store operations
351 #
352
353 reg: CEE_LDIND_I (base) {
354         MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, state->left->tree->inst_basereg, 
355                                 state->left->tree->inst_offset);
356 }
357
358 reg: CEE_LDIND_REF (base) {
359         MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, state->left->tree->inst_basereg, 
360                                 state->left->tree->inst_offset);
361 }
362
363 reg: CEE_LDIND_I1 (base) {
364         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI1_MEMBASE, state->reg1, 
365                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
366 }
367
368 reg: CEE_LDIND_U1 (base) {
369         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU1_MEMBASE, state->reg1, 
370                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
371 }
372
373 reg: CEE_LDIND_I2 (base) {
374         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI2_MEMBASE, state->reg1, 
375                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
376 }
377
378 reg: CEE_LDIND_U2 (base) {
379         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, 
380                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
381 }
382
383 reg: OP_LDADDR (OP_REGOFFSET) "2" {
384         /* use LEA */
385         tree->opcode = OP_MOVE;
386         tree->sreg1 = state->left->tree->inst_basereg;
387         tree->dreg = state->reg1;
388         mono_bblock_add_inst (s->cbb, tree);
389         if (state->left->tree->inst_offset) {
390                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tree->dreg, tree->dreg, state->left->tree->inst_offset);
391         }
392 }
393
394 reg: CEE_LDOBJ (OP_REGOFFSET) "2" {
395         /* use LEA */
396         /* FIXME: this is just an hack */
397         tree->opcode = OP_MOVE;
398         tree->sreg1 = state->left->tree->inst_basereg;
399         tree->dreg = state->reg1;
400         mono_bblock_add_inst (s->cbb, tree);
401         if (state->left->tree->inst_offset) {
402                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tree->dreg, tree->dreg, state->left->tree->inst_offset);
403         }
404 }
405
406 reg: CEE_LDOBJ (reg) {
407         tree->opcode = OP_MOVE;
408         tree->sreg1 = state->left->reg1;
409         tree->dreg = state->reg1;
410         mono_bblock_add_inst (s->cbb, tree);
411 }
412
413 reg: OP_OBJADDR (reg) {
414         tree->opcode = OP_MOVE;
415         tree->sreg1 = state->left->reg1;
416         tree->dreg = state->reg1;
417         mono_bblock_add_inst (s->cbb, tree);
418 }
419
420 reg: OP_VTADDR (reg) {
421         tree->opcode = OP_MOVE;
422         tree->sreg1 = state->left->reg1;
423         tree->dreg = state->reg1;
424         mono_bblock_add_inst (s->cbb, tree);
425 }
426
427 reg: CEE_LDIND_REF (OP_REGVAR),
428 reg: CEE_LDIND_I4 (OP_REGVAR),
429 reg: CEE_LDIND_U4 (OP_REGVAR) {
430         tree->opcode = OP_MOVE;
431         tree->sreg1 = state->left->tree->dreg;
432         tree->dreg = state->reg1;
433         mono_bblock_add_inst (s->cbb, tree);
434 }
435
436 reg: CEE_LDIND_U1 (OP_REGVAR) {
437         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->tree->dreg, 0xff);
438 }
439
440 reg: CEE_LDIND_U2 (OP_REGVAR) {
441         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->tree->dreg, 0xffff);
442 }
443
444 stmt: CEE_STIND_REF (base, reg) {
445         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
446                                  state->left->tree->inst_offset, state->right->reg1);
447 }
448
449 stmt: CEE_STIND_REF (base, CEE_LDIND_REF (OP_REGVAR)) {
450         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
451                                  state->left->tree->inst_offset, state->right->left->tree->dreg);
452 }
453
454 stmt: CEE_STIND_REF (base, OP_ICONST) {
455         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STORE_MEMBASE_IMM, state->left->tree->inst_basereg,
456                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
457 }
458
459 stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF (OP_REGVAR)) {
460         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->left->tree->dreg);
461 }
462
463
464 stmt: CEE_STIND_I (base, reg) {
465         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORE_MEMBASE_REG, state->left->tree->inst_basereg,
466                                  state->left->tree->inst_offset, state->right->reg1);
467 }
468
469 stmt: CEE_STIND_I (base, OP_ICONST) {
470         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STORE_MEMBASE_IMM, state->left->tree->inst_basereg,
471                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
472 }
473
474 reg: CEE_LDIND_I4 (base) {
475         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
476                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
477 }
478
479 reg: CEE_LDIND_U4 (base) {
480         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU4_MEMBASE, state->reg1, 
481                                    state->left->tree->inst_basereg, state->left->tree->inst_offset);
482 }
483
484 reg: CEE_LDIND_I4 (OP_REGVAR) {
485         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
486 }
487
488 reg: CEE_LDIND_U4 (OP_REGVAR) {
489         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
490 }
491
492 reg: CEE_LDIND_I (OP_REGVAR) {
493         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->tree->dreg);
494 }
495
496 stmt: CEE_STIND_I4 (base, reg) {
497         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
498                                  state->left->tree->inst_offset, state->right->reg1);
499 }
500
501 stmt: CEE_STIND_I4 (base, CEE_LDIND_I4 (OP_REGVAR)) {
502         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg,
503                                  state->left->tree->inst_offset, state->right->left->tree->dreg);
504 }
505
506 stmt: CEE_STIND_I4 (base, OP_ICONST) {
507         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg,
508                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
509 }
510
511 stmt: CEE_STIND_I1 (base, reg) {
512         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI1_MEMBASE_REG, state->left->tree->inst_basereg,
513                                  state->left->tree->inst_offset, state->right->reg1);
514 }
515
516 stmt: CEE_STIND_I1 (base, OP_ICONST) {
517         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI1_MEMBASE_IMM, state->left->tree->inst_basereg,
518                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
519 }
520
521 stmt: CEE_STIND_I2 (base, reg) {
522         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI2_MEMBASE_REG, state->left->tree->inst_basereg,
523                                  state->left->tree->inst_offset, state->right->reg1);
524 }
525
526 stmt: CEE_STIND_I2 (base, OP_ICONST) {
527         MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI2_MEMBASE_IMM, state->left->tree->inst_basereg,
528                                      state->left->tree->inst_offset, state->right->tree->inst_c0);
529 }
530
531 stmt: CEE_STIND_I4 (OP_REGVAR, reg) {
532         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
533 }
534
535 stmt: CEE_STIND_I2 (OP_REGVAR, reg) {
536         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->reg1, 0xffff);
537 }
538
539 stmt: CEE_STIND_I1 (OP_REGVAR, reg) {
540         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->reg1, 0xff);
541 }
542
543 stmt: CEE_STIND_I1 (OP_REGVAR, CEE_LDIND_U1 (OP_REGVAR)) {
544         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xff);
545 }
546
547 stmt: CEE_STIND_I1 (OP_REGVAR, CEE_LDIND_I1 (OP_REGVAR)) {
548         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xff);
549 }
550
551 stmt: CEE_STIND_I2 (OP_REGVAR, CEE_LDIND_U2 (OP_REGVAR)) {
552         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xffff);
553 }
554
555 stmt: CEE_STIND_I2 (OP_REGVAR, CEE_LDIND_I2 (OP_REGVAR)) {
556         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->left->tree->dreg, state->right->left->tree->dreg, 0xffff);
557 }
558
559 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (OP_REGVAR)) {
560         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->left->tree->dreg);
561 }
562
563 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (base)) {
564         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->left->tree->dreg, 
565                                    state->right->left->tree->inst_basereg, 
566                                    state->right->left->tree->inst_offset);
567 }
568
569 stmt: CEE_STIND_I4 (OP_REGVAR, OP_ICONST),
570 stmt: CEE_STIND_I2 (OP_REGVAR, OP_ICONST),
571 stmt: CEE_STIND_I1 (OP_REGVAR, OP_ICONST),
572 stmt: CEE_STIND_REF (OP_REGVAR, OP_ICONST),
573 stmt: CEE_STIND_I (OP_REGVAR, OP_ICONST) {
574         tree->inst_c0 = state->right->tree->inst_c0;
575         if (tree->opcode == CEE_STIND_I2)
576                 tree->inst_c0 &= 0xffff;
577         if (tree->opcode == CEE_STIND_I1)
578                 tree->inst_c0 &= 0xff;
579         
580         tree->opcode = OP_ICONST;
581         tree->dreg = state->left->tree->dreg;
582         mono_bblock_add_inst (s->cbb, tree);
583 }
584
585 stmt: CEE_STIND_REF (OP_REGVAR, reg) {
586         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
587 }
588
589 stmt: CEE_STIND_I (OP_REGVAR, reg) {
590         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
591 }
592
593 stmt: CEE_STELEM_REF (OP_GROUP (reg, reg), reg) {
594
595         g_assert_not_reached ();
596 }
597
598 reg: OP_GROUP (reg, reg) {
599         g_assert_not_reached ();
600 }
601
602 stmt: OP_MEMCPY (reg, reg) {
603         int size = tree->unused;
604         mini_emit_memcpy (s, state->left->reg1, 0, state->right->reg1, 0, size, 0);
605 }
606
607 stmt: OP_MEMSET (reg) {
608         int size = tree->unused;
609         mini_emit_memset (s, state->left->reg1, 0, size, tree->inst_imm, 0);
610 }
611
612 reg: OP_LDELEMA2D (reg, OP_GROUP (reg, reg)) "20" {
613         int bounds_reg = mono_regstate_next_int (s->rs);
614         int add_reg = mono_regstate_next_int (s->rs);
615         int mult_reg = mono_regstate_next_int (s->rs);
616         int mult2_reg = mono_regstate_next_int (s->rs);
617         int low1_reg = mono_regstate_next_int (s->rs);
618         int low2_reg = mono_regstate_next_int (s->rs);
619         int high1_reg = mono_regstate_next_int (s->rs);
620         int high2_reg = mono_regstate_next_int (s->rs);
621         int realidx1_reg = mono_regstate_next_int (s->rs);
622         int realidx2_reg = mono_regstate_next_int (s->rs);
623         int sum_reg = mono_regstate_next_int (s->rs);
624         int index1, index2;
625         guint32 size = mono_array_element_size (tree->klass);
626         
627         index1 = state->right->left->reg1;
628         index2 = state->right->right->reg1;
629
630         /* range checking */
631         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, bounds_reg, 
632                                        state->left->reg1, G_STRUCT_OFFSET (MonoArray, bounds));
633
634         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, low1_reg, 
635                                        bounds_reg, G_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
636         MONO_EMIT_NEW_BIALU (s, CEE_SUB, realidx1_reg, index1, low1_reg);
637         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, high1_reg, 
638                                        bounds_reg, G_STRUCT_OFFSET (MonoArrayBounds, length));
639         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, high1_reg, realidx1_reg);
640         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
641
642         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, low2_reg, 
643                                        bounds_reg, sizeof (MonoArrayBounds) + G_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
644         MONO_EMIT_NEW_BIALU (s, CEE_SUB, realidx2_reg, index2, low2_reg);
645         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, high2_reg, 
646                                        bounds_reg, sizeof (MonoArrayBounds) + G_STRUCT_OFFSET (MonoArrayBounds, length));
647         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, high2_reg, realidx2_reg);
648         MONO_EMIT_NEW_COND_EXC (s, LE_UN, "IndexOutOfRangeException");
649
650         MONO_EMIT_NEW_BIALU (s, CEE_MUL, mult_reg, high2_reg, realidx1_reg);
651         MONO_EMIT_NEW_BIALU (s, CEE_ADD, sum_reg, mult_reg, realidx2_reg);
652         MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult2_reg, sum_reg, size);
653         MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult2_reg, state->left->reg1);
654         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
655 }
656
657 #
658 # conversions: conv_u can be implemented with AND, also all _ovf conversions?
659 #
660
661 reg: CEE_CONV_I1 (reg) {
662         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
663 }
664
665 reg: CEE_CONV_I2 (reg) {
666         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
667 }
668
669 reg: CEE_CONV_I4 (reg) {
670         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
671 }
672
673 reg: CEE_CONV_U1 (reg) {
674         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
675 }
676
677 reg: CEE_CONV_U2 (reg) {
678         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
679 }
680
681 reg: CEE_CONV_U4 (reg) {
682         if (sizeof (void *) == 8) {
683                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
684         } else {
685                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
686         }
687 }
688
689 reg: CEE_CONV_U (reg) {
690         if (sizeof (void *) == 8) {
691                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
692         } else {
693                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
694         }
695 }
696
697 reg: CEE_CONV_I (reg) {
698         if (sizeof (void *) == 8) {
699                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
700         } else {
701                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
702         }
703 }
704
705 reg: CEE_CONV_OVF_I4 (reg) {
706         if (sizeof (void *) == 8) {
707                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
708         } else {
709                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
710         }
711 }
712
713 reg: CEE_CONV_OVF_U4 (reg) {
714         if (sizeof (void *) == 8) {
715                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
716         } else {
717                 /* Keep in sync with CONV_OVF_I4_UN below, they are the same on 32-bit machines */              
718                 MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
719                 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
720                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
721         }
722 }
723
724 reg: CEE_CONV_OVF_I4_UN (reg) {
725         if (sizeof (void *) == 8) {
726                 MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
727         } else {
728                 /* Keep in sync with CONV_OVF_U4 above, they are the same on 32-bit machines */
729                 MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
730                 MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
731                 MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
732         }
733 }
734
735 reg: CEE_CONV_OVF_I1 (reg) {     
736         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
737         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
738         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
739         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
740         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
741 }
742
743 reg: CEE_CONV_OVF_I1_UN (reg) {
744         /* probe values between 0 to 127 */
745         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
746         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
747         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
748 }
749
750 reg: CEE_CONV_OVF_U1 (reg) {
751         /* probe value to be within 0 to 255 */
752         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
753         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
754         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
755 }
756
757 reg: CEE_CONV_OVF_U1_UN (reg) {
758         /* probe value to be within 0 to 255 */
759         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
760         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
761         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
762 }
763
764 reg: CEE_CONV_OVF_I2 (reg) {    
765         /* Probe value to be within -32768 and 32767 */
766         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
767         MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
768         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
769         MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
770         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
771 }
772
773 reg: CEE_CONV_OVF_I2_UN (reg) {
774         /* Convert uint value into short, value within 0 and 32767 */
775         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
776         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
777         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
778 }
779
780 reg: CEE_CONV_OVF_U2 (reg) {
781         /* Probe value to be within 0 and 65535 */
782         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
783         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
784         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
785 }
786
787 reg: CEE_CONV_OVF_U2_UN (reg) {
788         /* Probe value to be within 0 and 65535 */
789         MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
790         MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
791         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
792 }
793
794 #
795 # basic alu operations
796 #
797
798 reg: CEE_AND (reg, reg) {
799         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
800 }
801
802 reg: CEE_AND (reg, OP_ICONST) {
803         MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
804 }
805
806 reg: CEE_OR (reg, reg) {
807         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
808 }
809
810 reg: CEE_OR (reg, OP_ICONST) {
811         MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
812 }
813
814 reg: CEE_XOR (reg, reg) {
815         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
816 }
817
818 reg: CEE_XOR (reg, OP_ICONST) {
819         MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
820 }
821
822 reg: CEE_NEG (reg) {
823         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
824 }
825
826 reg: CEE_NOT (reg) {
827         MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
828 }
829
830 reg: CEE_ADD (reg, reg) {
831         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
832 }
833
834 reg: CEE_ADD (reg, OP_ICONST) {
835         MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
836 }
837
838 reg: CEE_ADD_OVF (reg, reg) {
839         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
840         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
841 }
842
843 reg: CEE_ADD_OVF_UN (reg, reg) {
844         MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
845         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
846 }
847
848 reg: CEE_SUB (reg, reg) {
849         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
850 }
851
852 reg: CEE_SUB (reg, CEE_LDIND_I4 (OP_REGVAR)) {
853         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->left->tree->dreg);
854 }
855
856 reg: CEE_SUB (reg, OP_ICONST) {
857         MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
858 }
859
860 reg: CEE_SUB_OVF (reg, reg) {
861         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
862         MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
863 }
864
865 reg: CEE_SUB_OVF_UN (reg, reg) {
866         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
867         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
868 }
869
870 #
871 # mult/div operations
872 #
873
874 reg: CEE_MUL (reg, reg) {
875         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
876 }
877
878 reg: CEE_MUL (reg, OP_ICONST) {
879         MONO_EMIT_BIALU_IMM (s, tree, OP_MUL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
880 }
881
882 reg: CEE_MUL_OVF (reg, reg) {
883         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
884 }
885
886 reg: CEE_MUL_OVF_UN (reg, reg) {
887         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
888 }
889
890 reg: CEE_DIV (reg, reg) {
891         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
892 }
893
894 #reg: CEE_DIV (reg, OP_ICONST) {
895 #       MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
896 #}
897
898 reg: CEE_DIV_UN (reg, reg) {
899         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
900 }
901
902 #reg: CEE_DIV_UN (reg, OP_ICONST) {
903 #       MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
904 #}
905
906 reg: CEE_REM (reg, reg) {
907         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
908 }
909
910 #reg: CEE_REM (reg, OP_ICONST) {
911 #       MONO_EMIT_BIALU_IMM (s, tree, OP_REM_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
912 #}
913
914 reg: CEE_REM_UN (reg, reg) {
915         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
916 }
917
918 #reg: CEE_REM_UN (reg, OP_ICONST) {
919 #       MONO_EMIT_BIALU_IMM (s, tree, OP_REM_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
920 #}
921
922 #
923 # shift operations
924 #
925
926 reg: CEE_SHL (reg, reg) {
927         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
928 }
929
930 reg: CEE_SHL (reg, OP_ICONST) {
931         MONO_EMIT_BIALU_IMM (s, tree, OP_SHL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
932 }
933
934 reg: CEE_SHR (reg, reg) {
935         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
936 }
937
938 reg: CEE_SHR (reg, OP_ICONST) {
939         MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
940 }
941
942 reg: CEE_SHR_UN (reg, reg) {
943         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
944 }
945
946 reg: CEE_SHR_UN (reg, OP_ICONST) {
947         MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
948 }
949
950
951 #
952 # other alu operations
953 #
954
955 reg: OP_CEQ (cflags) {  
956         tree->dreg = state->reg1;
957         mono_bblock_add_inst (s->cbb, tree);
958 }
959
960 reg: OP_CLT (cflags) {  
961         tree->dreg = state->reg1;
962         mono_bblock_add_inst (s->cbb, tree);
963 }
964
965 reg: OP_CLT_UN (cflags) {       
966         tree->dreg = state->reg1;
967         mono_bblock_add_inst (s->cbb, tree);
968 }
969
970 reg: OP_CGT (cflags) {  
971         tree->dreg = state->reg1;
972         mono_bblock_add_inst (s->cbb, tree);
973 }
974
975 reg: OP_CGT_UN (cflags) {       
976         tree->dreg = state->reg1;
977         mono_bblock_add_inst (s->cbb, tree);
978 }
979
980 #
981 # control flow commands 
982 #
983
984 stmt: OP_LABEL {
985         mono_bblock_add_inst (s->cbb, tree);
986 }
987
988 stmt: CEE_NOP "0" {
989 }
990
991 stmt: CEE_BREAK "0" {
992         mono_bblock_add_inst (s->cbb, tree);
993 }
994
995 stmt: CEE_SWITCH (reg) {
996         MonoInst *label;
997         int offset_reg = mono_regstate_next_int (s->rs);
998         int target_reg = mono_regstate_next_int (s->rs);
999         int n = GPOINTER_TO_INT (tree->klass);
1000         
1001         MONO_NEW_LABEL (s, label);
1002         mono_create_jump_table (s, label, tree->inst_many_bb, n);
1003
1004         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, n);
1005         MONO_EMIT_NEW_BRANCH_BLOCK (s, CEE_BGE_UN, tree->inst_many_bb [n]);
1006         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, offset_reg, state->left->reg1, 2);
1007         mono_bblock_add_inst (s->cbb, label);
1008          /* the backend must patch the address. we use 0xf0f0f0f0 to avoid the usage 
1009           * of special (short) opcodes on x86 */
1010         MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, 0xf0f0f0f0);
1011         MONO_EMIT_UNALU (s, tree, OP_BR_REG, -1, target_reg);
1012 }
1013
1014 stmt: CEE_BR "0" {
1015         mono_bblock_add_inst (s->cbb, tree);
1016 }
1017
1018 stmt: OP_ARGLIST (reg) {
1019         tree->sreg1 = state->left->reg1;
1020         mono_bblock_add_inst (s->cbb, tree);
1021 }
1022
1023 reg: CEE_CALL {
1024         tree->dreg = state->reg1;
1025         mono_bblock_add_inst (s->cbb, tree);
1026 }
1027
1028 reg: CEE_CALLVIRT (reg) {
1029         mini_emit_virtual_call (s, state, tree, CEE_CALL, OP_CALL_MEMBASE);
1030 }
1031
1032 stmt: OP_VOIDCALLVIRT (reg) {
1033         mini_emit_virtual_call (s, state, tree, OP_VOIDCALL, OP_VOIDCALL_MEMBASE);
1034 }
1035
1036 lreg: OP_LCALLVIRT (reg) {
1037         mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE);
1038 }
1039
1040 freg: OP_FCALLVIRT (reg) {
1041         mini_emit_virtual_call (s, state, tree, OP_FCALL, OP_FCALL_MEMBASE);
1042 }
1043
1044 stmt: OP_VCALLVIRT (reg, reg) {
1045         mini_emit_virtual_call (s, state, tree, OP_VCALL, OP_VCALL_MEMBASE);
1046 }
1047
1048 reg: OP_CALL_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_VOIDCALL {
1055         mono_bblock_add_inst (s->cbb, tree);
1056 }
1057
1058 stmt: OP_VOIDCALL_REG (reg) {
1059         tree->sreg1 = state->left->reg1;
1060         mono_bblock_add_inst (s->cbb, tree);
1061 }
1062
1063 freg: OP_FCALL {
1064         tree->dreg = state->reg1;
1065         mono_bblock_add_inst (s->cbb, tree);
1066 }
1067
1068 freg: OP_FCALL_REG (reg) {
1069         tree->sreg1 = state->left->reg1;
1070         tree->dreg = state->reg1;
1071         mono_bblock_add_inst (s->cbb, tree);
1072 }
1073
1074 lreg: OP_LCALL {
1075         tree->dreg = state->reg1;
1076         mono_bblock_add_inst (s->cbb, tree);
1077 }
1078
1079 lreg: OP_LCALL_REG (reg) {
1080         tree->sreg1 = state->left->reg1;
1081         tree->dreg = state->reg1;
1082         mono_bblock_add_inst (s->cbb, tree);
1083 }
1084
1085 stmt: OP_VCALL (reg) {
1086         mono_arch_emit_this_vret_args (s, (MonoCallInst*)tree, -1, -1, state->left->reg1);
1087         mono_bblock_add_inst (s->cbb, tree);
1088 }
1089
1090 stmt: OP_VCALL_REG (reg, reg) {
1091         mono_arch_emit_this_vret_args (s, (MonoCallInst*)tree, -1, -1, state->right->reg1);
1092         
1093         tree->sreg1 = state->left->reg1;
1094         mono_bblock_add_inst (s->cbb, tree);
1095 }
1096
1097 #
1098 # Optimized call instructions
1099 #
1100
1101 reg: OP_CALL_REG (OP_ICONST) {
1102         tree->opcode = CEE_CALL;
1103         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
1104         tree->dreg = state->reg1;
1105         mono_bblock_add_inst (s->cbb, tree);
1106 }
1107
1108 stmt: OP_VOIDCALL_REG (OP_ICONST) {
1109         tree->opcode = OP_VOIDCALL;
1110         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
1111         mono_bblock_add_inst (s->cbb, tree);
1112 }
1113
1114 freg: OP_FCALL_REG (OP_ICONST) {
1115         tree->opcode = OP_FCALL;
1116         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
1117         tree->dreg = state->reg1;
1118         mono_bblock_add_inst (s->cbb, tree);
1119 }
1120
1121 lreg: OP_LCALL_REG (OP_ICONST) {
1122         tree->opcode = OP_LCALL;
1123         ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
1124         tree->dreg = state->reg1;
1125         mono_bblock_add_inst (s->cbb, tree);
1126 }
1127
1128 stmt: CEE_RET "0" {
1129         mono_bblock_add_inst (s->cbb, tree);
1130 }
1131
1132 cflags: OP_COMPARE (reg, reg) {
1133         tree->sreg1 = state->left->reg1;
1134         tree->sreg2 = state->right->reg1;
1135         mono_bblock_add_inst (s->cbb, tree);
1136 }
1137
1138 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), reg) {
1139         tree->sreg1 = state->left->left->tree->dreg;
1140         tree->sreg2 = state->right->reg1;
1141         mono_bblock_add_inst (s->cbb, tree);
1142 }
1143
1144 cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), CEE_LDIND_I (OP_REGVAR)) {
1145         tree->sreg1 = state->left->left->tree->dreg;
1146         tree->sreg2 = state->right->left->tree->dreg;
1147         mono_bblock_add_inst (s->cbb, tree);
1148 }
1149
1150 cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST) {
1151         tree->opcode = OP_COMPARE_IMM;
1152         tree->sreg1 = state->left->left->tree->dreg;
1153         tree->inst_imm = state->right->tree->inst_c0;
1154         mono_bblock_add_inst (s->cbb, tree);
1155 }
1156
1157 cflags: OP_COMPARE (reg, OP_ICONST) {
1158         tree->opcode = OP_COMPARE_IMM;
1159         tree->sreg1 = state->left->reg1;
1160         tree->inst_imm = state->right->tree->inst_c0;
1161         mono_bblock_add_inst (s->cbb, tree);
1162 }
1163
1164 stmt: CEE_BNE_UN (cflags) {
1165         mono_bblock_add_inst (s->cbb, tree);
1166 }
1167
1168 stmt: CEE_BEQ (cflags) {
1169         mono_bblock_add_inst (s->cbb, tree);
1170 }
1171
1172 stmt: CEE_BLT (cflags) {
1173         mono_bblock_add_inst (s->cbb, tree);
1174 }
1175
1176 stmt: CEE_BLT_UN (cflags) {
1177         mono_bblock_add_inst (s->cbb, tree);
1178 }
1179
1180 stmt: CEE_BGT (cflags) {
1181         mono_bblock_add_inst (s->cbb, tree);
1182 }
1183
1184 stmt: CEE_BGT_UN (cflags) {
1185         mono_bblock_add_inst (s->cbb, tree);
1186 }
1187
1188 stmt: CEE_BGE  (cflags) {
1189         mono_bblock_add_inst (s->cbb, tree);
1190 }
1191
1192 stmt: CEE_BGE_UN (cflags) {
1193         mono_bblock_add_inst (s->cbb, tree);
1194 }
1195
1196 stmt: CEE_BLE  (cflags) {
1197         mono_bblock_add_inst (s->cbb, tree);
1198 }
1199
1200 stmt: CEE_BLE_UN (cflags) {
1201         mono_bblock_add_inst (s->cbb, tree);
1202 }
1203
1204 stmt: CEE_POP (reg)
1205
1206 # remove some common pops without side effects
1207 stmt: CEE_POP (OP_ICONST)
1208 stmt: CEE_POP (CEE_LDIND_REF (base))
1209 stmt: CEE_POP (CEE_LDIND_I4 (base))
1210 stmt: CEE_POP (CEE_LDIND_U1 (base))
1211
1212 stmt: CEE_JMP "0" {
1213         mono_bblock_add_inst (s->cbb, tree);
1214 }
1215
1216 # exception handling
1217
1218 stmt: CEE_THROW (reg) {
1219         MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->reg1);
1220 }
1221
1222 stmt: OP_THROW_OR_NULL (reg) {
1223         MonoInst *object_is_null;
1224
1225         MONO_NEW_LABEL (s, object_is_null);
1226
1227         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, 0, state->left->reg1, 0);
1228         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1229         MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->reg1);
1230         mono_bblock_add_inst (s->cbb, object_is_null);
1231 }
1232
1233 stmt: CEE_THROW (CEE_LDIND_REF (OP_REGVAR)) {
1234         MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->left->tree->dreg);
1235 }
1236
1237 stmt: OP_CALL_HANDLER {
1238         mono_bblock_add_inst (s->cbb, tree);
1239 }
1240
1241 stmt: OP_START_HANDLER "2" {
1242         mono_bblock_add_inst (s->cbb, tree);
1243 }
1244
1245 stmt: CEE_ENDFINALLY "2" {
1246         mono_bblock_add_inst (s->cbb, tree);
1247 }
1248
1249 stmt: OP_ENDFILTER (reg) "2" {
1250         MONO_EMIT_UNALU (s, tree, OP_ENDFILTER, -1, state->left->reg1);
1251 }
1252
1253 stmt: OP_CHECK_THIS (reg) {
1254         tree->sreg1 = state->left->reg1;
1255         tree->dreg = state->reg1;
1256         mono_bblock_add_inst (s->cbb, tree);
1257 }
1258
1259 # object related opcodes 
1260
1261 reg: CEE_ISINST (reg) {
1262         MonoClass *klass = tree->inst_newa_class;
1263         MonoInst *object_is_null, *end_label, *false_label;
1264         int obj_reg = state->left->reg1;
1265         int vtable_reg = mono_regstate_next_int (s->rs);
1266
1267         MONO_NEW_LABEL (s, object_is_null);
1268         MONO_NEW_LABEL (s, end_label);
1269         MONO_NEW_LABEL (s, false_label);
1270
1271         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1272         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1273
1274         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1275                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1276                 /* the object_is_null target simply copies the input register to the output */
1277                 mini_emit_isninst_iface_cast (s, vtable_reg, klass, false_label, object_is_null);
1278         } else {
1279                 int klass_reg = mono_regstate_next_int (s->rs);
1280
1281                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1282                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1283
1284                 if (klass->rank) {
1285                         int rank_reg = mono_regstate_next_int (s->rs);
1286                         int eclass_reg = mono_regstate_next_int (s->rs);
1287
1288                         MONO_EMIT_NEW_LOAD_MEMBASE (s, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1289                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
1290                         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
1291                         MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, cast_class));
1292                         if (klass->cast_class == mono_defaults.object_class) {
1293                                 int parent_reg = mono_regstate_next_int (s->rs);
1294                                 int const_reg;
1295                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, parent_reg, eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
1296                                 if (mono_compile_aot) {
1297                                         const_reg = mono_regstate_next_int (s->rs);
1298                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1299                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, parent_reg, const_reg);
1300                                 } else {
1301                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
1302                                 }
1303                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, object_is_null);
1304                                 if (mono_compile_aot) {
1305                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1306                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1307                                 } else {
1308                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1309                                 }
1310                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1311                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
1312                         } else if (klass->cast_class == mono_defaults.enum_class->parent) {
1313                                 int const_reg;
1314                                 
1315                                 if (mono_compile_aot) {
1316                                         const_reg = mono_regstate_next_int (s->rs);
1317                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1318                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1319                                 } else {
1320                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
1321                                 }
1322                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1323                                 if (mono_compile_aot) {
1324                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1325                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1326                                 } else {
1327                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1328                                 }
1329                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1330                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
1331                         } else if (klass->cast_class == mono_defaults.enum_class) {
1332                                 if (mono_compile_aot) {
1333                                         int const_reg = mono_regstate_next_int (s->rs);
1334                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1335                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1336                                 } else {
1337                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1338                                 }
1339                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1340                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false_label);
1341                         } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1342                                 mini_emit_isninst_iface_class_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
1343                         } else {
1344                                 if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
1345                                         /* Check that the object is a vector too */
1346                                         int bounds_reg = mono_regstate_next_int (s->rs);
1347                                         MONO_EMIT_NEW_LOAD_MEMBASE (s, bounds_reg, obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));
1348                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, bounds_reg, 0);
1349                                         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
1350                                 }
1351
1352                                 /* the object_is_null target simply copies the input register to the output */
1353                                 mini_emit_isninst_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
1354                         }
1355                 } else {
1356                         /* the object_is_null target simply copies the input register to the output */
1357                         mini_emit_isninst_cast (s, klass_reg, klass, false_label, object_is_null);
1358                 }
1359         }
1360
1361         mono_bblock_add_inst (s->cbb, false_label);
1362         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
1363         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1364         mono_bblock_add_inst (s->cbb, object_is_null);
1365         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1366         mono_bblock_add_inst (s->cbb, end_label);
1367 }
1368
1369 reg: OP_CISINST (reg) {
1370         /* This opcode takes as input an object reference and a class, and returns:
1371         0) if the object is an instance of the class,
1372         1) if the object is not instance of the class,
1373         2) if the object is a proxy whose type cannot be determined */
1374         
1375     MonoClass *klass = tree->inst_newa_class;
1376         MonoInst *end_label, *true_label, *false_label, *false2_label;
1377         MonoInst *no_proxy_label, *interface_fail_label;
1378         int obj_reg = state->left->reg1;
1379         int tmp_reg = mono_regstate_next_int (s->rs);
1380         int klass_reg = mono_regstate_next_int (s->rs);
1381
1382         MONO_NEW_LABEL (s, end_label);
1383         MONO_NEW_LABEL (s, true_label);
1384         MONO_NEW_LABEL (s, false_label);
1385         MONO_NEW_LABEL (s, false2_label);
1386
1387         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1388         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, false_label);
1389
1390         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1391                 MONO_NEW_LABEL (s, interface_fail_label);
1392                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1393                 mini_emit_isninst_iface_cast (s, tmp_reg, klass, interface_fail_label, true_label);
1394                 
1395                 mono_bblock_add_inst (s->cbb, interface_fail_label);
1396                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1397                 
1398                 if (mono_compile_aot) {
1399                         int tproxy_reg = mono_regstate_next_int (s->rs);
1400                         MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1401                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1402                 } else {
1403                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1404                 }
1405                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false_label);
1406                 
1407                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1408                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1409                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, false2_label);
1410                 
1411         } else {
1412                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1413                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1414                 
1415                 MONO_NEW_LABEL (s, no_proxy_label);
1416                 
1417                 if (mono_compile_aot) {
1418                         int tproxy_reg = mono_regstate_next_int (s->rs);
1419                         MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1420                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1421                 } else {
1422                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1423                 }
1424                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, no_proxy_label);
1425                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
1426                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
1427                 
1428                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1429                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1430                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, no_proxy_label);
1431                 
1432                 mini_emit_isninst_cast (s, klass_reg, klass, false2_label, true_label);
1433                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, false2_label);
1434                 
1435                 mono_bblock_add_inst (s->cbb, no_proxy_label);
1436                 mini_emit_isninst_cast (s, klass_reg, klass, false_label, true_label);
1437         }
1438
1439         mono_bblock_add_inst (s->cbb, false_label);
1440         MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
1441         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1442         mono_bblock_add_inst (s->cbb, false2_label);
1443         MONO_EMIT_NEW_ICONST (s, state->reg1, 2);
1444         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1445         mono_bblock_add_inst (s->cbb, true_label);
1446         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
1447         mono_bblock_add_inst (s->cbb, end_label);
1448 }
1449
1450 reg: OP_UNBOXCAST (reg) {
1451         MonoClass *klass = tree->inst_newa_class;
1452         int obj_reg = state->left->reg1;
1453         int vtable_reg = mono_regstate_next_int (s->rs);
1454         int klass_reg = mono_regstate_next_int (s->rs);
1455         int eclass_reg = mono_regstate_next_int (s->rs);
1456         int rank_reg = mono_regstate_next_int (s->rs);
1457
1458         MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1459         MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1460         MONO_EMIT_NEW_LOAD_MEMBASE (s, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1461         MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, element_class));
1462
1463         /* FIXME: generics */
1464         g_assert (klass->rank == 0);
1465
1466         // Check rank == 0
1467         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, 0);
1468         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1469
1470         if (mono_compile_aot) {
1471                 int const_reg = mono_regstate_next_int (s->rs);
1472                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass->element_class);
1473                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1474         }
1475         else {
1476                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, klass->element_class);
1477         }
1478         
1479         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1480         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1481 }
1482
1483 reg: CEE_CASTCLASS (reg) {
1484         MonoClass *klass = tree->inst_newa_class;
1485         MonoInst *object_is_null;
1486         int obj_reg = state->left->reg1;
1487         int vtable_reg = mono_regstate_next_int (s->rs);
1488
1489         MONO_NEW_LABEL (s, object_is_null);
1490
1491         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1492         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1493
1494         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1495                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1496                 mini_emit_castclass_iface (s, vtable_reg, klass);
1497         } else {
1498                 int klass_reg = mono_regstate_next_int (s->rs);
1499
1500                 MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1501                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1502
1503                 if (klass->rank) {
1504                         int rank_reg = mono_regstate_next_int (s->rs);
1505                         int eclass_reg = mono_regstate_next_int (s->rs);
1506
1507                         MONO_EMIT_NEW_LOAD_MEMBASE (s, rank_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, rank));
1508                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
1509                         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1510                         MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, cast_class));
1511                         if (klass->cast_class == mono_defaults.object_class) {
1512                                 int parent_reg = mono_regstate_next_int (s->rs);
1513                                 int const_reg;
1514                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, parent_reg, eclass_reg, G_STRUCT_OFFSET (MonoClass, parent));
1515                                 if (mono_compile_aot) {
1516                                         const_reg = mono_regstate_next_int (s->rs);
1517                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1518                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, parent_reg, const_reg);
1519                                 } else {
1520                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, parent_reg, mono_defaults.enum_class->parent);
1521                                 }
1522                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, object_is_null);
1523                                 if (mono_compile_aot) {
1524                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1525                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1526                                 } else {
1527                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1528                                 }
1529                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1530                         } else if (klass->cast_class == mono_defaults.enum_class->parent) {
1531                                 int const_reg = mono_regstate_next_int (s->rs);
1532                                 if (mono_compile_aot) {
1533                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class->parent);
1534                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1535                                 } else {
1536                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class->parent);
1537                                 }
1538                                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, object_is_null);
1539                                 if (mono_compile_aot) {
1540                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1541                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1542                                 } else {
1543                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1544                                 }
1545                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1546                         } else if (klass->cast_class == mono_defaults.enum_class) {
1547                                 if (mono_compile_aot) {
1548                                         int const_reg = mono_regstate_next_int (s->rs);
1549                                         MONO_EMIT_NEW_CLASSCONST (s, const_reg, mono_defaults.enum_class);
1550                                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, eclass_reg, const_reg);
1551                                 } else {
1552                                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, eclass_reg, mono_defaults.enum_class);
1553                                 }
1554                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1555                         } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1556                                 mini_emit_castclass_iface_class (s, eclass_reg, klass->cast_class);
1557                         } else {
1558                                 mini_emit_castclass (s, eclass_reg, klass->cast_class);
1559                         }
1560
1561                         if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
1562                                 /* Check that the object is a vector too */
1563                                 int bounds_reg = mono_regstate_next_int (s->rs);
1564                                 MONO_EMIT_NEW_LOAD_MEMBASE (s, bounds_reg, obj_reg, G_STRUCT_OFFSET (MonoArray, bounds));
1565                                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, bounds_reg, 0);
1566                                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1567                         }
1568                 } else {
1569                         mini_emit_castclass (s, klass_reg, klass);
1570                 }
1571         }
1572
1573         mono_bblock_add_inst (s->cbb, object_is_null);
1574         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
1575 }
1576
1577 reg: OP_CCASTCLASS (reg) {
1578         /* This opcode takes as input an object reference and a class, and returns:
1579         0) if the object is an instance of the class,
1580         1) if the object is a proxy whose type cannot be determined
1581         an InvalidCastException exception is thrown otherwhise*/
1582         
1583         MonoClass *klass = tree->inst_newa_class;
1584         MonoInst *end_label, *fail_label, *no_proxy_label, *ok_result_label;
1585         int obj_reg = state->left->reg1;
1586         int tmp_reg = mono_regstate_next_int (s->rs);
1587         int klass_reg = mono_regstate_next_int (s->rs);
1588
1589         MONO_NEW_LABEL (s, end_label);
1590         MONO_NEW_LABEL (s, ok_result_label);
1591
1592         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, obj_reg, 0);
1593         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, ok_result_label);
1594
1595         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1596         
1597                 MONO_NEW_LABEL (s, fail_label);
1598                 
1599                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1600                 mini_emit_isninst_iface_cast (s, tmp_reg, klass, fail_label, ok_result_label);
1601                 
1602                 mono_bblock_add_inst (s->cbb, fail_label);
1603                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1604
1605                 if (mono_compile_aot) {
1606                         int tproxy_reg = mono_regstate_next_int (s->rs);
1607                         MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1608                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1609                 } else {
1610                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1611                 }
1612                 
1613                 MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1614                 
1615                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
1616                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
1617                 
1618                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1619                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1620                 MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
1621                 
1622                 MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
1623                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1624                 
1625         } else {
1626
1627                 MONO_NEW_LABEL (s, no_proxy_label);
1628                 MONO_NEW_LABEL (s, fail_label);
1629                 
1630                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1631                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1632
1633                 if (mono_compile_aot) {
1634                         int tproxy_reg = mono_regstate_next_int (s->rs);
1635                         MONO_EMIT_NEW_CLASSCONST (s, tproxy_reg, mono_defaults.transparent_proxy_class);
1636                         MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, tproxy_reg);
1637                 } else {
1638                         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, mono_defaults.transparent_proxy_class);
1639                 }
1640                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, no_proxy_label);
1641                 
1642                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
1643                 MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
1644                 
1645                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
1646                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, tmp_reg, 0);
1647                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, no_proxy_label);
1648                 
1649                 mini_emit_isninst_cast (s, klass_reg, klass, fail_label, ok_result_label);
1650                 mono_bblock_add_inst (s->cbb, fail_label);
1651                 MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
1652                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BR, end_label);
1653                 
1654                 mono_bblock_add_inst (s->cbb, no_proxy_label);
1655                 mini_emit_castclass (s, klass_reg, klass);
1656         }
1657
1658         mono_bblock_add_inst (s->cbb, ok_result_label);
1659         MONO_EMIT_NEW_ICONST (s, state->reg1, 0);
1660         mono_bblock_add_inst (s->cbb, end_label);
1661 }
1662
1663 reg: CEE_NEWARR (reg),
1664 lreg: OP_LMUL (lreg, lreg),
1665 lreg: OP_LMUL_OVF (lreg, lreg),
1666 lreg: OP_LMUL_OVF_UN (lreg, lreg),
1667 lreg: OP_LDIV (lreg, lreg),
1668 lreg: OP_LDIV_UN (lreg, lreg),
1669 lreg: OP_LREM (lreg, lreg),
1670 lreg: OP_LREM_UN (lreg, lreg),
1671 lreg: OP_LSHL (lreg, reg),
1672 lreg: OP_LSHR (lreg, reg),
1673 lreg: OP_LSHR_UN (lreg, reg) {
1674         g_assert_not_reached ();
1675 }
1676
1677 #
1678 # string support
1679 #
1680 reg: OP_GETCHR (reg, reg) {
1681         int mult_reg = mono_regstate_next_int (s->rs);
1682         int add_reg = mono_regstate_next_int (s->rs);
1683         
1684         MONO_EMIT_BOUNDS_CHECK (s, state->left->reg1, MonoString, length, state->right->reg1);
1685         MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, mult_reg, state->right->reg1, 1);
1686         MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
1687         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, 
1688                                    add_reg, G_STRUCT_OFFSET (MonoString, chars));
1689 }
1690
1691 reg: OP_GETCHR (reg, OP_ICONST) {
1692         int ind = 2 * state->right->tree->inst_c0 + G_STRUCT_OFFSET (MonoString, chars);
1693
1694         MONO_EMIT_BOUNDS_CHECK_IMM (s, state->left->reg1, MonoString, length, state->right->tree->inst_c0);
1695         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, state->left->reg1, ind);
1696 }
1697
1698 reg: OP_STRLEN (reg) {  
1699         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
1700                                    state->left->reg1, G_STRUCT_OFFSET (MonoString, length));
1701 }
1702
1703 reg: OP_GETTYPE (reg) { 
1704         int vt_reg = mono_regstate_next_int (s->rs);
1705         MONO_EMIT_NEW_LOAD_MEMBASE (s, vt_reg, state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1706         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOAD_MEMBASE, state->reg1, vt_reg, G_STRUCT_OFFSET (MonoVTable, type));
1707 }
1708
1709 #
1710 # array support
1711 #
1712 reg: CEE_LDLEN (reg) {  
1713         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, 
1714                                    state->left->reg1, G_STRUCT_OFFSET (MonoArray, max_length));
1715 }
1716
1717 reg: OP_ARRAY_RANK (reg) {      
1718         int vtable_reg = mono_regstate_next_int (s->rs);
1719         int class_reg = mono_regstate_next_int (s->rs);
1720         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, vtable_reg, 
1721                                        state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1722         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, class_reg, 
1723                                        vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1724         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, 
1725                                        class_reg, G_STRUCT_OFFSET (MonoClass, rank));
1726 }
1727
1728 reg: OP_CHECK_ARRAY_TYPE (reg) {
1729         int vtable_reg = mono_regstate_next_int (s->rs);
1730         int class_reg = mono_regstate_next_int (s->rs);
1731         int elclass_reg = mono_regstate_next_int (s->rs);
1732
1733         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, vtable_reg, 
1734                                        state->left->reg1, G_STRUCT_OFFSET (MonoObject, vtable));
1735         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, class_reg, 
1736                                        vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
1737         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, elclass_reg, 
1738                                        class_reg, G_STRUCT_OFFSET (MonoClass, element_class));
1739         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, elclass_reg, tree->klass);
1740         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "ArrayTypeMismatchException");
1741         MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
1742 }
1743
1744 reg: CEE_LDELEMA (reg, OP_ICONST) "15" {
1745         guint32 size = mono_class_array_element_size (tree->klass);
1746
1747         int ind = size * state->right->tree->inst_c0 + G_STRUCT_OFFSET (MonoArray, vector);
1748
1749         MONO_EMIT_BOUNDS_CHECK_IMM (s, state->left->reg1, MonoArray, max_length, state->right->tree->inst_c0);
1750         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, ind);
1751 }
1752
1753 reg: CEE_LDELEMA (reg, reg) "20" {
1754         int mult_reg = mono_regstate_next_int (s->rs);
1755         int add_reg = mono_regstate_next_int (s->rs);
1756         guint32 size = mono_class_array_element_size (tree->klass);
1757
1758         MONO_EMIT_BOUNDS_CHECK (s, state->left->reg1, MonoArray, max_length, state->right->reg1);
1759         MONO_EMIT_NEW_BIALU_IMM (s, OP_MUL_IMM, mult_reg, state->right->reg1, size);
1760         MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
1761         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoArray, vector));
1762 }
1763
1764 reg: CEE_REFANYVAL (reg) {
1765         int klass_reg = mono_regstate_next_int (s->rs);
1766         MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass));
1767         if (mono_compile_aot) {
1768                 int const_reg = mono_regstate_next_int (s->rs);
1769                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, tree->inst_newa_class);
1770                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, klass_reg, const_reg);
1771         } else {
1772                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, klass_reg, tree->inst_newa_class);
1773         }
1774         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
1775         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, value));
1776 }       
1777
1778 reg: OP_REFANYTYPE (reg) {
1779         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
1780 }       
1781
1782 stmt: CEE_MKREFANY (OP_GROUP (reg, OP_ICONST), reg) {
1783         MonoClass *klass = (MonoClass*)(tree->inst_left->inst_right->inst_p0);
1784         if (mono_compile_aot) {
1785                 int const_reg = mono_regstate_next_int (s->rs);
1786                 int type_reg = mono_regstate_next_int (s->rs);
1787                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1788                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass), const_reg);
1789                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, type_reg, const_reg, G_STRUCT_OFFSET (MonoClass, byval_arg));
1790                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
1791         }
1792         else {
1793                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, type), &klass->byval_arg);
1794                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass), klass);
1795         }
1796         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, value), state->left->left->reg1);
1797 }
1798
1799 %%
1800
1801 /* 
1802  * Emit code which checks whenever the interface id of @klass is smaller than
1803  * than the value given by max_iid_reg.
1804 */
1805 static void
1806 mini_emit_max_iid_check (MonoCompile *s, int max_iid_reg, MonoClass *klass,
1807                                                  MonoInst *false_target)
1808 {
1809         if (mono_compile_aot) {
1810                 int iid_reg = mono_regstate_next_int (s->rs);
1811                 MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
1812                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, max_iid_reg, iid_reg);
1813         }
1814         else
1815                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1816         if (false_target)
1817                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1818         else
1819                 MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1820 }
1821
1822 /* Same as above, but obtains max_iid from a vtable */
1823 static void
1824 mini_emit_max_iid_check_vtable (MonoCompile *s, int vtable_reg, MonoClass *klass,
1825                                                                  MonoInst *false_target)
1826 {
1827         int max_iid_reg = mono_regstate_next_int (s->rs);
1828                 
1829         MONO_EMIT_NEW_LOAD_MEMBASE (s, max_iid_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, max_interface_id));
1830         mini_emit_max_iid_check (s, max_iid_reg, klass, false_target);
1831 }
1832
1833 /* Same as above, but obtains max_iid from a klass */
1834 static void
1835 mini_emit_max_iid_check_class (MonoCompile *s, int klass_reg, MonoClass *klass,
1836                                                                  MonoInst *false_target)
1837 {
1838         int max_iid_reg = mono_regstate_next_int (s->rs);
1839
1840         MONO_EMIT_NEW_LOAD_MEMBASE (s, max_iid_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, max_interface_id));          
1841         mini_emit_max_iid_check (s, max_iid_reg, klass, false_target);
1842 }
1843
1844 static void
1845 mini_emit_load_intf_reg (MonoCompile *s, int intf_reg, int ioffset_reg, MonoClass *klass)
1846 {
1847         if (mono_compile_aot) {
1848                 int iid_reg = mono_regstate_next_int (s->rs);
1849                 MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
1850                 /* FIXME: Do a shift instead */
1851 #if SIZEOF_VOID_P == 8
1852                 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 3);
1853 #else
1854                 MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 2);
1855 #endif
1856                 MONO_EMIT_NEW_BIALU (s, CEE_ADD, ioffset_reg, ioffset_reg, iid_reg);
1857                 MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, 0);
1858         }
1859         else
1860                 MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id * SIZEOF_VOID_P);
1861 }
1862
1863 /* Emit code which loads <vtable_reg>->interface_offsets [klass->interface_id] */
1864 static void
1865 mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, MonoClass *klass)
1866 {
1867         int ioffset_reg = mono_regstate_next_int (s->rs);
1868
1869         MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_offsets));
1870         mini_emit_load_intf_reg (s, intf_reg, ioffset_reg, klass);
1871 }
1872
1873 /* Emit code which loads <klass_reg>->interface_offsets [klass->interface_id] */
1874 static void
1875 mini_emit_load_intf_reg_class (MonoCompile *s, int intf_reg, int klass_reg, MonoClass *klass)
1876 {
1877         int ioffset_reg = mono_regstate_next_int (s->rs);
1878
1879         MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, interface_offsets));
1880         mini_emit_load_intf_reg (s, intf_reg, ioffset_reg, klass);
1881 }
1882
1883 void 
1884 mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop)
1885 {
1886         MonoMethod *method = ((MonoCallInst*)tree)->method;
1887         int vtable_reg, slot_reg, this_reg;
1888         MBState *state = st;
1889
1890         this_reg = state->left->reg1;
1891         mono_arch_emit_this_vret_args (cfg, (MonoCallInst*)tree, this_reg, state->left->tree->type, novirtop == OP_VCALL? state->right->reg1: -1);
1892
1893         if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) || 
1894             ((method->flags & METHOD_ATTRIBUTE_FINAL) && 
1895              method->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)) {
1896                 /* 
1897                  * the method is not virtual, we just need to ensure this is not null
1898                  * and then we can call the method directly.
1899                  */
1900                 if (method->klass->marshalbyref || method->klass == mono_defaults.object_class) {
1901                         method = ((MonoCallInst*)tree)->method = mono_marshal_get_remoting_invoke_with_check (method);
1902                 }
1903
1904                 if (!method->string_ctor)
1905                         MONO_EMIT_NEW_UNALU (cfg, OP_CHECK_THIS, -1, this_reg);
1906
1907                 tree->dreg = state->reg1;
1908                 tree->opcode = novirtop;
1909                 mono_bblock_add_inst (cfg->cbb, tree);
1910                 return;
1911         }
1912
1913         vtable_reg = mono_regstate_next_int (cfg->rs);
1914         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this_reg, G_STRUCT_OFFSET (MonoObject, vtable));
1915         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1916                 slot_reg = mono_regstate_next_int (cfg->rs);
1917                 mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass);
1918                 tree->inst_offset = method->slot * SIZEOF_VOID_P;
1919         } else {
1920                 slot_reg = vtable_reg;
1921                 tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (method->slot * SIZEOF_VOID_P);
1922         }
1923         
1924         tree->dreg = state->reg1;
1925         tree->opcode = virtop;
1926         tree->sreg1 = slot_reg;
1927         ((MonoCallInst*)tree)->virtual = TRUE;
1928         mono_bblock_add_inst (cfg->cbb, tree);
1929 }
1930
1931 void 
1932 mini_emit_isninst_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1933 {
1934         int idepth_reg = mono_regstate_next_int (s->rs);
1935         int stypes_reg = mono_regstate_next_int (s->rs);
1936         int stype = mono_regstate_next_int (s->rs);
1937
1938         if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1939                 MONO_EMIT_NEW_LOAD_MEMBASE (s, idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
1940                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1941                 MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
1942         }
1943         MONO_EMIT_NEW_LOAD_MEMBASE (s, stypes_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, supertypes));
1944         MONO_EMIT_NEW_LOAD_MEMBASE (s, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P));
1945         if (mono_compile_aot) {
1946                 int const_reg = mono_regstate_next_int (s->rs);
1947                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
1948                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, stype, const_reg);
1949         } else {
1950                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, stype, klass);
1951         }
1952         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, true_target);
1953 }
1954
1955 void 
1956 mini_emit_isninst_iface_cast (MonoCompile *s, int vtable_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1957 {
1958         int intf_reg = mono_regstate_next_int (s->rs);
1959
1960         mini_emit_max_iid_check_vtable (s, vtable_reg, klass, false_target);
1961         mini_emit_load_intf_reg_vtable (s, intf_reg, vtable_reg, klass);
1962         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
1963         /* the object_is_null target simply copies the input register to the output */
1964         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BNE_UN, true_target);
1965 }
1966
1967 /*
1968  * Variant of the above that takes a register to the class, not the vtable.
1969  * Note that inside interfaces_offsets the empty value is -1, not NULL, in this case.
1970  */
1971 void 
1972 mini_emit_isninst_iface_class_cast (MonoCompile *s, int klass_reg, MonoClass *klass, MonoInst *false_target, MonoInst *true_target)
1973 {
1974         int intf_reg = mono_regstate_next_int (s->rs);
1975
1976         mini_emit_max_iid_check_class (s, klass_reg, klass, false_target);
1977         mini_emit_load_intf_reg_class (s, intf_reg, klass_reg, klass);
1978         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, -1);
1979         /* the object_is_null target simply copies the input register to the output */
1980         MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BGE, true_target);
1981 }
1982
1983 void 
1984 mini_emit_castclass (MonoCompile *s, int klass_reg, MonoClass *klass)
1985 {
1986         int idepth_reg = mono_regstate_next_int (s->rs);
1987         int stypes_reg = mono_regstate_next_int (s->rs);
1988         int stype = mono_regstate_next_int (s->rs);
1989
1990         if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1991                 MONO_EMIT_NEW_LOAD_MEMBASE (s, idepth_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, idepth));
1992                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1993                 MONO_EMIT_NEW_COND_EXC (s, LT_UN, "InvalidCastException");
1994         }
1995         MONO_EMIT_NEW_LOAD_MEMBASE (s, stypes_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, supertypes));
1996         MONO_EMIT_NEW_LOAD_MEMBASE (s, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P));
1997         if (mono_compile_aot) {
1998                 int const_reg = mono_regstate_next_int (s->rs);
1999                 MONO_EMIT_NEW_CLASSCONST (s, const_reg, klass);
2000                 MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, stype, const_reg);
2001         } else {
2002                 MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, stype, klass);
2003         }
2004         MONO_EMIT_NEW_COND_EXC (s, NE_UN, "InvalidCastException");
2005 }
2006
2007 void 
2008 mini_emit_castclass_iface (MonoCompile *s, int vtable_reg, MonoClass *klass)
2009 {
2010         int intf_reg = mono_regstate_next_int (s->rs);
2011
2012         mini_emit_max_iid_check_vtable (s, vtable_reg, klass, NULL);
2013         mini_emit_load_intf_reg_vtable (s, intf_reg, vtable_reg, klass);
2014         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, 0);
2015         MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
2016 }
2017
2018 /*
2019  * Variant of the aboce that takes a register to the class, not the vtable.
2020  * Note that inside interfaces_offsets the empty value is -1, not NULL, in this case.
2021  */
2022 void 
2023 mini_emit_castclass_iface_class (MonoCompile *s, int klass_reg, MonoClass *klass)
2024 {
2025         int intf_reg = mono_regstate_next_int (s->rs);
2026
2027         mini_emit_max_iid_check_class (s, klass_reg, klass, NULL);
2028         mini_emit_load_intf_reg_class (s, intf_reg, klass_reg, klass);
2029         MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, intf_reg, -1);
2030         MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
2031 }
2032
2033 void 
2034 mini_emit_memcpy (MonoCompile *s, int destreg, int doffset, int srcreg, int soffset, int size, int align)
2035 {
2036         int cur_reg;
2037
2038         /* FIXME: consider alignment for archs that need it. */
2039         while (size >= 4) {
2040                 cur_reg = mono_regstate_next_int (s->rs);
2041                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, cur_reg, srcreg, soffset);
2042                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, doffset, cur_reg);
2043                 doffset += 4;
2044                 soffset += 4;
2045                 size -= 4;
2046         }
2047         while (size >= 2) {
2048                 cur_reg = mono_regstate_next_int (s->rs);
2049                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI2_MEMBASE, cur_reg, srcreg, soffset);
2050                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, doffset, cur_reg);
2051                 doffset += 2;
2052                 soffset += 2;
2053                 size -= 2;
2054         }
2055         while (size >= 1) {
2056                 cur_reg = mono_regstate_next_int (s->rs);
2057                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI1_MEMBASE, cur_reg, srcreg, soffset);
2058                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, doffset, cur_reg);
2059                 doffset += 1;
2060                 soffset += 1;
2061                 size -= 1;
2062         }
2063 }
2064
2065 void 
2066 mini_emit_memset (MonoCompile *s, int destreg, int offset, int size, int val, int alignl)
2067 {
2068         int val_reg = mono_regstate_next_int (s->rs);
2069
2070         MONO_EMIT_NEW_ICONST (s, val_reg, val);
2071
2072         while (size >= 4) {
2073                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
2074                 offset += 4;
2075                 size -= 4;
2076         }
2077         while (size >= 2) {
2078                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
2079                 offset += 2;
2080                 size -= 2;
2081         }
2082         while (size >= 1) {
2083                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
2084                 offset += 1;
2085                 size -= 1;
2086         }
2087 }
2088