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