2004-10-14 Joe Shaw <joeshaw@novell.com>
[mono.git] / mono / mini / inssel-sparc.brg
1 %%
2
3 #
4 # inssel-sparc.brg: burg file for special sparc instructions
5 #
6 # Author:
7 #   Dietmar Maurer (dietmar@ximian.com)
8 #   Paolo Molaro (lupus@ximian.com)
9 #
10 # (C) 2002 Ximian, Inc.
11 #
12
13 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
14         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
15 }
16
17 reg: CEE_LDIND_I8 (OP_REGVAR) {
18         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->tree->dreg);
19 }
20
21 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
22         /* this should only happen for methods returning a long */
23         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg2);
24         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg + 1, state->right->reg1);
25 }
26
27 lreg: CEE_LDIND_I8 (OP_REGVAR) {
28         /* reg2 contains the most significant word */
29         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, state->left->tree->dreg);
30         tree->opcode = OP_SETREG;
31         tree->dreg = state->reg1;
32         tree->sreg1 = state->left->tree->dreg + 1;
33         mono_bblock_add_inst (s->cbb, tree);
34 }
35
36 freg: OP_LCONV_TO_R8 (lreg) {
37         tree->sreg1 = state->left->reg1;
38         tree->dreg = state->reg1;
39         mono_bblock_add_inst (s->cbb, tree);
40 }
41
42 freg: OP_LCONV_TO_R8 (lreg) {
43         /* Dummy rule */
44 }
45
46 freg: OP_LCONV_TO_R4 (lreg) {
47         tree->sreg1 = state->left->reg1;
48         tree->dreg = state->reg1;
49         mono_bblock_add_inst (s->cbb, tree);
50 }
51
52 freg: CEE_CONV_R_UN (reg) {
53         tree->sreg1 = state->left->reg1;
54         tree->dreg = state->reg1;
55         mono_bblock_add_inst (s->cbb, tree);
56 }
57
58 freg: OP_FCONV_TO_R4 (freg) "0" {
59         /* The conversion is done elsewhere */
60         MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->reg1);
61 }
62
63 freg: CEE_LDIND_R8 (OP_REGVAR) {
64         MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg);
65 }
66
67 freg: CEE_LDIND_R4 (OP_REGVAR) {
68         MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg);
69 }
70
71 reg: OP_LOCALLOC (reg) {
72         tree->sreg1 = state->left->reg1;
73         tree->dreg = state->reg1;
74         mono_bblock_add_inst (s->cbb, tree);
75 }
76
77 base: OP_SPARC_INARG_VT (base) {
78         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->tree->inst_basereg, 
79                                         state->left->tree->inst_offset);
80 }
81
82 reg: OP_LDADDR (OP_SPARC_INARG_VT (base)) {
83         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->tree->inst_basereg, 
84                                         state->left->left->tree->inst_offset);
85 }
86
87 reg: CEE_LDOBJ (OP_SPARC_INARG_VT (base)) {
88         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->tree->inst_basereg, 
89                                         state->left->left->tree->inst_offset);
90 }
91
92 base: OP_LDADDR (reg) {
93 /*
94         tree->inst_basereg = mono_regstate_next_int (s->rs);
95         tree->inst_offset = 0;
96
97         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->inst_basereg, state->left->tree->dreg, 0);
98 */
99         tree->inst_basereg = state->left->tree->dreg;
100         tree->inst_offset = 0;
101 }
102
103 stmt: OP_OUTARG (OP_LDADDR (reg)) {
104         tree->opcode = OP_SETREG;
105         tree->dreg = tree->unused;
106         tree->sreg1 = state->left->left->tree->dreg;
107         mono_bblock_add_inst (s->cbb, tree);
108 }
109
110 stmt: OP_SETRET (reg) {
111         tree->opcode = OP_MOVE;
112         tree->sreg1 = state->left->reg1;
113         tree->dreg = sparc_i0;
114         mono_bblock_add_inst (s->cbb, tree);
115 }
116
117 stmt: OP_SETRET (lreg) {
118         MONO_EMIT_NEW_UNALU (s, OP_MOVE, sparc_i0, state->left->reg2);
119         tree->opcode = OP_MOVE;
120         tree->sreg1 = state->left->reg1;
121         tree->dreg = sparc_i1;
122         mono_bblock_add_inst (s->cbb, tree);
123 }
124
125 stmt: OP_SETRET (freg) {
126         tree->opcode = OP_SETFRET;
127         tree->sreg1 = state->left->reg1;
128         tree->dreg = sparc_f0;
129         mono_bblock_add_inst (s->cbb, tree);
130 }
131
132 stmt: OP_SETRET (OP_ICONST) {
133         tree->opcode = OP_ICONST;
134         tree->inst_c0 = state->left->tree->inst_c0;
135         tree->dreg = sparc_i0;
136         mono_bblock_add_inst (s->cbb, tree);
137 }
138
139 stmt: OP_OUTARG (reg) {
140         tree->opcode = OP_SETREG;
141         tree->dreg = tree->unused;
142         tree->sreg1 = state->left->reg1;
143         mono_bblock_add_inst (s->cbb, tree);
144 }
145
146 stmt: OP_OUTARG (OP_REGVAR) {
147         tree->opcode = OP_SETREG;
148         tree->dreg = tree->unused;
149         tree->sreg1 = state->left->tree->dreg;
150         mono_bblock_add_inst (s->cbb, tree);
151 }
152
153 stmt: OP_OUTARG (freg) {
154         /* floating-point <-> integer transfer must go through memory */
155         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_basereg,
156                                                                 tree->inst_imm, state->left->reg1);
157         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm);
158 }
159
160 stmt: OP_OUTARG (OP_ICONST) {
161         tree->opcode = OP_SETREGIMM;
162         tree->dreg = tree->unused;
163         tree->inst_c0 = state->left->tree->inst_c0;
164         mono_bblock_add_inst (s->cbb, tree);
165 }
166
167 stmt: OP_OUTARG (OP_I8CONST) {
168         tree->opcode = OP_SETREGIMM;
169         tree->dreg = tree->unused;
170         tree->inst_c0 = state->left->tree->inst_c0;
171         mono_bblock_add_inst (s->cbb, tree);
172 } cost {
173         MBCOND (sizeof (gpointer) == 8);
174
175         return 0;
176 }
177
178 stmt: OP_OUTARG (CEE_LDIND_R4 (base)) {
179         tree->opcode = OP_LOADI4_MEMBASE;
180         tree->dreg = tree->unused;
181         tree->inst_basereg = state->left->left->tree->inst_basereg;
182         tree->inst_offset = state->left->left->tree->inst_offset;
183         mono_bblock_add_inst (s->cbb, tree);
184 }
185
186 stmt: OP_SPARC_OUTARG_REGPAIR (lreg) {
187         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
188         tree->opcode = OP_SETREG;
189         tree->dreg = tree->unused + 1;
190         tree->sreg1 = state->left->reg1;
191         mono_bblock_add_inst (s->cbb, tree);
192 }
193
194 stmt: OP_SPARC_OUTARG_REGPAIR (freg) {
195         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg,
196                                                                 tree->inst_imm, state->left->reg1);
197         /* floating-point <-> integer transfer must go through memory */
198         /* Load into a register pair */
199         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm);
200         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused + 1, tree->inst_basereg, tree->inst_imm + 4);
201 }
202
203 stmt: OP_SPARC_OUTARG_MEM (reg) {
204         guint32 offset = tree->inst_imm;
205         if (mono_sparc_is_sparc64 ()) {
206                 guint32 real_offset = tree->inst_imm - MONO_SPARC_STACK_BIAS;
207                 /* Correct for the additions in get_call_info () */
208                 offset = MONO_SPARC_STACK_BIAS + (real_offset & ~(7));
209             tree->opcode = OP_STOREI8_MEMBASE_REG;
210         }
211         else {
212                 if (tree->inst_imm & 0x1)
213                         tree->opcode = OP_STOREI1_MEMBASE_REG;
214                 else if (tree->inst_imm & 0x2)
215                         tree->opcode = OP_STOREI2_MEMBASE_REG;
216                 else
217                         tree->opcode = OP_STOREI4_MEMBASE_REG;
218         }
219         tree->inst_destbasereg = tree->inst_basereg;
220         tree->inst_offset = offset;
221         tree->sreg1 = state->left->reg1;
222         mono_bblock_add_inst (s->cbb, tree);
223 }
224
225 stmt: OP_SPARC_OUTARG_MEM (freg) {
226         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_basereg,
227                                                                 tree->inst_imm, state->left->reg1);
228 }
229
230 stmt: OP_SPARC_OUTARG_MEMPAIR (lreg) {
231         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, tree->inst_basereg,
232                                                                 tree->inst_imm, state->left->reg2);
233         tree->opcode = OP_STOREI4_MEMBASE_REG;
234         tree->inst_destbasereg = tree->inst_basereg;
235         tree->inst_offset = tree->inst_imm + 4;
236         tree->sreg1 = state->left->reg1;
237         mono_bblock_add_inst (s->cbb, tree);
238 }
239
240 stmt: OP_SPARC_OUTARG_MEMPAIR (freg) {
241         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg,
242                                                                 tree->inst_imm, state->left->reg1);
243 }
244
245 stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (lreg) {
246         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
247         tree->opcode = OP_STOREI4_MEMBASE_REG;
248         tree->inst_destbasereg = tree->inst_basereg;
249         tree->inst_offset = tree->inst_imm + 4;
250         tree->sreg1 = state->left->reg1;
251         mono_bblock_add_inst (s->cbb, tree);
252 }
253
254 stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (freg) {
255         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg,
256                                                                 tree->inst_imm, state->left->reg1);
257         /* floating-point <-> integer transfer must go through memory */
258         /* Load most significant word into register */
259         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm);
260 }
261
262 stmt: OP_SPARC_OUTARG_FLOAT_REG (freg) {
263         tree->opcode = OP_SPARC_SETFREG_FLOAT;
264         tree->dreg = tree->unused;
265         tree->sreg1 = state->left->reg1;
266         mono_bblock_add_inst (s->cbb, tree);
267 }       
268
269 stmt: OP_SPARC_OUTARG_DOUBLE_REG (freg) {
270         tree->opcode = OP_SETFREG;
271         tree->dreg = tree->unused;
272         tree->sreg1 = state->left->reg1;
273         mono_bblock_add_inst (s->cbb, tree);
274 }       
275
276 # Handles scalar valuetypes like RuntimeTypeHandle
277 reg: OP_OUTARG_VT (OP_ICONST) {
278         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, sparc_sp, tree->inst_c1, state->left->tree->inst_c0);
279         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
280 }
281
282 reg: OP_OUTARG_VT (OP_AOTCONST) {
283         MONO_EMIT_NEW_AOTCONST (s, state->reg1, state->left->tree->inst_p0, state->left->tree->inst_c1);
284         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, sparc_sp, tree->inst_c1, state->reg1);
285         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
286 }
287
288 # FIXME: Unify this with the previous rule
289 reg: OP_OUTARG_VT (OP_REFANYTYPE (reg)) {
290         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
291         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, sparc_sp, tree->inst_c1, state->reg1);
292         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
293 }       
294
295 reg: OP_OUTARG_VT (base) {
296         int size = tree->unused;
297         mini_emit_memcpy (s, sparc_sp, tree->inst_c1, state->left->tree->inst_basereg, state->left->tree->inst_offset, size, 0);
298         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
299 }
300
301 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
302         tree->opcode = OP_SETREG;
303         tree->sreg1 = state->left->left->tree->dreg;
304         tree->dreg = tree->unused;
305         mono_bblock_add_inst (s->cbb, tree);
306 }
307
308 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGOFFSET)) {
309         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, state->left->left->tree->inst_basereg, 
310                                                                 state->left->left->tree->inst_offset);
311 }
312
313 stmt: OP_OUTARG_VT (OP_ICONST) {
314         tree->opcode = OP_SETREGIMM;
315         tree->dreg = tree->unused;
316         tree->inst_imm = state->left->tree->inst_c0;
317         mono_bblock_add_inst (s->cbb, tree);
318 }
319
320 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
321         /* nothing to do: the value is already on the FP stack */
322 }
323
324 reg: CEE_LDIND_I1 (OP_REGVAR) {
325         MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->tree->dreg);
326 }
327
328 reg: CEE_LDIND_I2 (OP_REGVAR) {
329         MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->tree->dreg);
330 }
331
332 stmt: CEE_BNE_UN (fpcflags) {
333         tree->opcode = OP_FBNE_UN;
334         mono_bblock_add_inst (s->cbb, tree);
335 }
336
337 stmt: CEE_BEQ (fpcflags) {
338         tree->opcode = OP_FBEQ;
339         mono_bblock_add_inst (s->cbb, tree);
340 }
341
342 stmt: CEE_BLT (fpcflags) {
343         tree->opcode = OP_FBLT;
344         mono_bblock_add_inst (s->cbb, tree);
345 }
346
347 stmt: CEE_BLT_UN (fpcflags) {
348         tree->opcode = OP_FBLT_UN;
349         mono_bblock_add_inst (s->cbb, tree);
350 }
351
352 stmt: CEE_BGT (fpcflags) {
353         tree->opcode = OP_FBGT;
354         mono_bblock_add_inst (s->cbb, tree);
355 }
356
357 stmt: CEE_BGT_UN (fpcflags) {
358         tree->opcode = OP_FBGT_UN;
359         mono_bblock_add_inst (s->cbb, tree);
360 }
361
362 stmt: CEE_BGE  (fpcflags) {
363         tree->opcode = OP_FBGE;
364         mono_bblock_add_inst (s->cbb, tree);
365 }
366
367 stmt: CEE_BGE_UN (fpcflags) {
368         tree->opcode = OP_FBGE_UN;
369         mono_bblock_add_inst (s->cbb, tree);
370 }
371
372 stmt: CEE_BLE  (fpcflags) {
373         tree->opcode = OP_FBLE;
374         mono_bblock_add_inst (s->cbb, tree);
375 }
376
377 stmt: CEE_BLE_UN (fpcflags) {
378         tree->opcode = OP_FBLE_UN;
379         mono_bblock_add_inst (s->cbb, tree);
380 }
381
382 stmt: CEE_POP (freg) "0" {
383         /* nothing to do */
384 }     
385
386 stmt: OP_START_HANDLER {
387      mono_bblock_add_inst (s->cbb, tree);
388 }
389
390 stmt: CEE_ENDFINALLY {
391         //MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
392         //MONO_EMIT_NEW_LOAD_MEMBASE (s, sparc_o7, spvar->inst_basereg, spvar->inst_offset); 
393         mono_bblock_add_inst (s->cbb, tree);
394 }
395
396 stmt: OP_ENDFILTER (reg) {
397         //MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
398         //MONO_EMIT_NEW_LOAD_MEMBASE (s, sparc_o7, spvar->inst_basereg, spvar->inst_offset); 
399         tree->sreg1 = state->left->reg1;
400         mono_bblock_add_inst (s->cbb, tree);
401 }
402
403 stmt: OP_START_HANDLER {
404 }
405
406 stmt: CEE_ENDFINALLY {
407         mono_bblock_add_inst (s->cbb, tree);
408 }
409
410 stmt: OP_ENDFILTER (reg) {
411         tree->sreg1 = state->left->reg1;
412         tree->dreg = state->reg1;
413         mono_bblock_add_inst (s->cbb, tree);
414 }
415
416 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
417         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
418                          state->left->right->reg1);
419 }
420
421 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
422         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
423                          state->left->right->reg1);
424 }
425
426 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
427         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
428                          state->left->right->reg1);
429 }
430
431 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
432         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
433                          state->left->right->reg1);
434 }
435
436 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
437         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
438                          state->left->right->reg1);
439 }
440
441 reg: OP_LOCALLOC (reg) {
442         tree->sreg1 = state->left->tree->dreg;
443         mono_bblock_add_inst (s->cbb, tree);
444 }
445
446 #
447 # Optimizations
448 #
449
450 reg: CEE_LDIND_REF (OP_REGVAR),
451 reg: CEE_LDIND_I (OP_REGVAR),
452 reg: CEE_LDIND_I4 (OP_REGVAR),
453 reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
454         /* This rule might not work on all archs, hence it is sparc only */
455         state->reg1 = state->left->tree->dreg;
456         tree->dreg = state->reg1;
457 }
458
459 stmt: CEE_STIND_I1 (OP_REGVAR, OP_ICONST) {
460         tree->opcode = OP_ICONST;
461         tree->dreg = state->left->tree->dreg;
462         tree->inst_c0 = state->right->tree->inst_c0;
463         mono_bblock_add_inst (s->cbb, tree);
464 }
465
466 stmt: CEE_STIND_I2 (OP_REGVAR, OP_ICONST) {
467         tree->opcode = OP_ICONST;
468         tree->dreg = state->left->tree->dreg;
469         tree->inst_c0 = state->right->tree->inst_c0;
470         mono_bblock_add_inst (s->cbb, tree);
471 }
472
473 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (reg, OP_ICONST)) {
474         MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
475 }
476
477 stmt: CEE_STIND_REF (OP_REGVAR, CEE_ADD (reg, OP_ICONST)) {
478         MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
479 }
480
481 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (reg, OP_ICONST)) {
482         MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
483 }
484
485 stmt: CEE_STIND_REF (OP_REGVAR, CEE_SUB (reg, OP_ICONST)) {
486         MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
487 }
488
489 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (reg, reg)) {
490         MONO_EMIT_BIALU (s, tree, CEE_ADD, state->left->tree->dreg, state->right->left->reg1, state->right->right->reg1);
491 }
492
493 stmt: CEE_STIND_REF (OP_REGVAR, CEE_ADD (reg, reg)) {
494         MONO_EMIT_BIALU (s, tree, CEE_ADD, state->left->tree->dreg, state->right->left->reg1, state->right->right->reg1);
495 }
496
497 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4(base)) {
498         MONO_EMIT_LOAD_MEMBASE (s, tree, state->left->tree->dreg, state->right->left->tree->inst_basereg, 
499                                 state->right->left->tree->inst_offset); 
500         mono_bblock_add_inst (s->cbb, tree);
501 }
502
503 stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF(base)) {
504         MONO_EMIT_LOAD_MEMBASE (s, tree, state->left->tree->dreg, state->right->left->tree->inst_basereg, 
505                                 state->right->left->tree->inst_offset); 
506         mono_bblock_add_inst (s->cbb, tree);
507 }
508
509 stmt: OP_SETRET (CEE_LDIND_I1(base)),
510 stmt: OP_SETRET (CEE_LDIND_U1(base)),
511 stmt: OP_SETRET (CEE_LDIND_I2(base)),
512 stmt: OP_SETRET (CEE_LDIND_U2(base)),
513 stmt: OP_SETRET (CEE_LDIND_I(base)),
514 stmt: OP_SETRET (CEE_LDIND_REF(base)),
515 stmt: OP_SETRET (CEE_LDIND_I4(base)),
516 stmt: OP_SETRET (CEE_LDIND_U4(base)) {
517         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode), 
518                 sparc_i0, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset); 
519         mono_bblock_add_inst (s->cbb, tree);
520 }
521
522 stmt: OP_SETRET (CEE_LDIND_I4(OP_REGVAR)) {
523         tree->opcode = OP_SETREG;
524         tree->dreg = sparc_i0;
525         tree->sreg1 = state->left->left->tree->dreg;
526         mono_bblock_add_inst (s->cbb, tree);
527 }
528
529 stmt: OP_SETRET (CEE_LDIND_I(OP_REGVAR)) {
530         tree->opcode = OP_SETREG;
531         tree->dreg = sparc_i0;
532         tree->sreg1 = state->left->left->tree->dreg;
533         mono_bblock_add_inst (s->cbb, tree);
534 }
535
536 stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) {
537         tree->opcode = OP_SETREG;
538         tree->dreg = tree->unused;
539         tree->sreg1 = state->left->left->tree->dreg;
540         mono_bblock_add_inst (s->cbb, tree);
541 }
542
543 stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) {
544         tree->opcode = OP_SETREG;
545         tree->dreg = tree->unused;
546         tree->sreg1 = state->left->left->tree->dreg;
547         mono_bblock_add_inst (s->cbb, tree);
548 }
549
550 stmt: OP_OUTARG (CEE_LDIND_REF(base)) {
551         MONO_EMIT_LOAD_MEMBASE (s, tree, tree->unused, state->left->left->tree->inst_basereg, 
552                                 state->left->left->tree->inst_offset);  
553         mono_bblock_add_inst (s->cbb, tree);
554 }
555
556 stmt: OP_OUTARG (CEE_LDIND_I4(base)) {
557         MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, tree->unused, state->left->left->tree->inst_basereg, 
558                                 state->left->left->tree->inst_offset);  
559         mono_bblock_add_inst (s->cbb, tree);
560 }
561
562 reg: OP_LDADDR (OP_REGOFFSET) "1" {
563         if (state->left->tree->inst_offset) {
564                 MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset);
565         } else {
566                 tree->opcode = OP_MOVE;
567                 tree->sreg1 = state->left->tree->inst_basereg;
568                 tree->dreg = state->reg1;
569         }
570         mono_bblock_add_inst (s->cbb, tree);
571 }
572
573 # FIXME: This rule was commented out in inssel.brg, why ?
574 reg: CEE_REM (reg, OP_ICONST) {
575         MONO_EMIT_BIALU_IMM (s, tree, OP_REM_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
576 }
577
578 # This one too
579 reg: CEE_DIV (reg, OP_ICONST) {
580         MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
581 }
582
583 reg: OP_LOCALLOC (OP_ICONST) {
584         tree->opcode = OP_SPARC_LOCALLOC_IMM;
585         tree->inst_c0 = state->left->tree->inst_c0;
586         tree->dreg = state->reg1;
587         mono_bblock_add_inst (s->cbb, tree);
588 }
589
590 # FIXME: Optimized MEMCPY for copying valuetypes
591
592 # Optimized version for initializing valuetypes on the stack
593 stmt: OP_MEMSET (OP_LDADDR(OP_REGOFFSET)) "0" {
594         int size = tree->unused;
595         int offset = state->left->left->tree->inst_offset;
596         int destreg = state->left->left->tree->inst_basereg;
597         int val_reg;
598
599         if (tree->inst_imm) {
600                 val_reg = mono_regstate_next_int (s->rs);
601                 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
602         }
603         else
604                 val_reg = sparc_g0;
605
606         /* Target address must be dword aligned */
607         if ((tree->inst_imm == 0) && (size >= 8) && 
608                 (destreg == sparc_fp) && (((offset - MONO_SPARC_STACK_BIAS) % 8) == 0)) {
609                 if (!mono_sparc_is_v9 ()) {
610                         /* Use STD */
611                         MONO_EMIT_NEW_ICONST (s, sparc_g1, 0);
612
613                         while (size >= 8) {
614                                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
615                                 offset += 8;
616                                 size -= 8;
617                         }
618                 }
619                 else {
620                         /* Use STX imm */
621                         while (size >= 8) {
622                                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, 0);
623                                 offset += 8;
624                                 size -= 8;
625                         }
626                 }
627         }
628                 
629         while (size >= 4) {
630                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
631                 offset += 4;
632                 size -= 4;
633         }
634         while (size >= 2) {
635                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
636                 offset += 2;
637                 size -= 2;
638         }
639         while (size >= 1) {
640                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
641                 offset += 1;
642                 size -= 1;
643         }
644 }               
645
646 stmt: OP_MEMSET (reg) "0" {
647         int size = tree->unused;
648         int offset = 0;
649         int destreg = state->left->reg1;
650         int val_reg;
651
652         if (tree->inst_imm) {
653                 val_reg = mono_regstate_next_int (s->rs);
654                 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
655         }
656         else
657                 val_reg = sparc_g0;
658
659         /* FIXME: This assumes the destination is dword aligned */
660         /*
661         if ((tree->inst_imm == 0) && (size >= 8)) {
662                 while (size >= 8) {
663                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, sparc_g0);
664                         offset += 8;
665                         size -= 8;
666                 }
667         }
668         */
669                 
670         while (size >= 4) {
671                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
672                 offset += 4;
673                 size -= 4;
674         }
675         while (size >= 2) {
676                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
677                 offset += 2;
678                 size -= 2;
679         }
680         while (size >= 1) {
681                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
682                 offset += 1;
683                 size -= 1;
684         }
685 }
686
687
688 stmt: CEE_STIND_R8 (base, OP_R8CONST) {
689         /* fp constants are pricy on SPARC */
690         guint64 d = *(guint64*)state->right->tree->inst_p0;
691
692         if (d == 0) {
693                 if (sizeof (gpointer) == 8) {
694                         MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI8_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset, sparc_g0);
695                 }
696                 else {
697                         /* STOREI8 would write %g1 as well */
698                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset, sparc_g0);
699                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset + 4, sparc_g0);
700                 }
701         }
702         else {
703                 state->right->tree->dreg = state->reg1;
704                 mono_bblock_add_inst (s->cbb, state->right->tree);
705                 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORER8_MEMBASE_REG, state->left->tree->inst_basereg,
706                                          state->left->tree->inst_offset, state->reg1);
707         }
708 }
709
710 %%