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