4 # inssel-sparc.brg: burg file for special sparc instructions
7 # Dietmar Maurer (dietmar@ximian.com)
8 # Paolo Molaro (lupus@ximian.com)
10 # (C) 2002 Ximian, Inc.
13 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
14 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
17 reg: CEE_LDIND_I8 (OP_REGVAR) {
18 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->tree->dreg);
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);
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);
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);
42 freg: OP_LCONV_TO_R8 (lreg) {
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);
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);
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);
63 freg: CEE_LDIND_R8 (OP_REGVAR) {
64 MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg);
67 freg: CEE_LDIND_R4 (OP_REGVAR) {
68 MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg);
71 reg: OP_LOCALLOC (reg) {
72 tree->sreg1 = state->left->reg1;
73 tree->dreg = state->reg1;
74 mono_bblock_add_inst (s->cbb, tree);
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);
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);
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);
92 base: OP_LDADDR (reg) {
94 tree->inst_basereg = mono_regstate_next_int (s->rs);
95 tree->inst_offset = 0;
97 MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->inst_basereg, state->left->tree->dreg, 0);
99 tree->inst_basereg = state->left->tree->dreg;
100 tree->inst_offset = 0;
103 stmt: OP_OUTARG (OP_LDADDR (reg)) {
104 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
106 tree->opcode = OP_SETREG;
107 tree->dreg = mono_regstate_next_int (s->rs);
108 tree->sreg1 = state->left->left->tree->dreg;
109 mono_bblock_add_inst (s->cbb, tree);
111 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
114 stmt: OP_SETRET (reg) {
115 tree->opcode = OP_MOVE;
116 tree->sreg1 = state->left->reg1;
117 tree->dreg = sparc_i0;
118 mono_bblock_add_inst (s->cbb, tree);
121 stmt: OP_SETRET (lreg) {
122 MONO_EMIT_NEW_UNALU (s, OP_MOVE, sparc_i0, state->left->reg2);
123 tree->opcode = OP_MOVE;
124 tree->sreg1 = state->left->reg1;
125 tree->dreg = sparc_i1;
126 mono_bblock_add_inst (s->cbb, tree);
129 stmt: OP_SETRET (freg) {
130 tree->opcode = OP_SETFRET;
131 tree->sreg1 = state->left->reg1;
132 tree->dreg = sparc_f0;
133 mono_bblock_add_inst (s->cbb, tree);
136 stmt: OP_SETRET (OP_ICONST) {
137 tree->opcode = OP_ICONST;
138 tree->inst_c0 = state->left->tree->inst_c0;
139 tree->dreg = sparc_i0;
140 mono_bblock_add_inst (s->cbb, tree);
143 stmt: OP_OUTARG (reg) {
144 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
146 tree->opcode = OP_SETREG;
147 tree->dreg = mono_regstate_next_int (s->rs);
148 tree->sreg1 = state->left->reg1;
149 mono_bblock_add_inst (s->cbb, tree);
151 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
154 stmt: OP_OUTARG (OP_REGVAR) {
155 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
157 tree->opcode = OP_SETREG;
158 tree->dreg = mono_regstate_next_int (s->rs);
159 tree->sreg1 = state->left->tree->dreg;
160 mono_bblock_add_inst (s->cbb, tree);
162 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
165 stmt: OP_OUTARG (OP_ICONST) {
166 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
168 tree->opcode = OP_SETREGIMM;
169 tree->dreg = mono_regstate_next_int (s->rs);
170 tree->inst_c0 = state->left->tree->inst_c0;
171 mono_bblock_add_inst (s->cbb, tree);
173 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
176 stmt: OP_OUTARG (OP_I8CONST) {
177 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
179 tree->opcode = OP_SETREGIMM;
180 tree->dreg = mono_regstate_next_int (s->rs);
181 tree->inst_c0 = state->left->tree->inst_c0;
182 mono_bblock_add_inst (s->cbb, tree);
184 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
186 MBCOND (sizeof (gpointer) == 8);
191 stmt: OP_OUTARG (CEE_LDIND_R4 (base)) {
192 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
194 tree->opcode = OP_LOADI4_MEMBASE;
195 tree->dreg = mono_regstate_next_int (s->rs);
196 tree->inst_basereg = state->left->left->tree->inst_basereg;
197 tree->inst_offset = state->left->left->tree->inst_offset;
198 mono_bblock_add_inst (s->cbb, tree);
200 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
203 stmt: OP_SPARC_OUTARG_FLOAT (freg) {
204 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
205 int dreg = mono_regstate_next_int (s->rs);
206 /* floating-point <-> integer transfer must go through memory */
207 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_right->inst_basereg,
208 tree->inst_right->inst_imm, state->left->reg1);
209 MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, tree->inst_right->inst_basereg, tree->inst_right->inst_imm);
211 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
214 stmt: OP_SPARC_OUTARG_REGPAIR (lreg) {
215 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
216 int dreg = mono_regstate_next_int (s->rs);
217 int dreg2 = mono_regstate_next_int (s->rs);
219 MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, state->left->reg2);
220 tree->opcode = OP_SETREG;
222 tree->sreg1 = state->left->reg1;
223 mono_bblock_add_inst (s->cbb, tree);
225 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
226 mono_call_inst_add_outarg_reg (s, call, dreg2, tree->backend.reg3 + 1, FALSE);
229 stmt: OP_SPARC_OUTARG_REGPAIR_FLOAT (freg) {
230 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
231 int dreg = mono_regstate_next_int (s->rs);
232 int dreg2 = mono_regstate_next_int (s->rs);
234 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_right->inst_basereg,
235 tree->inst_right->inst_imm, state->left->reg1);
236 /* floating-point <-> integer transfer must go through memory */
237 /* Load into a register pair */
238 MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, tree->inst_right->inst_basereg, tree->inst_right->inst_imm);
239 MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg2, tree->inst_right->inst_basereg, tree->inst_right->inst_imm + 4);
241 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
242 mono_call_inst_add_outarg_reg (s, call, dreg2, tree->backend.reg3 + 1, FALSE);
245 stmt: OP_SPARC_OUTARG_MEM (reg) {
246 guint32 offset = tree->inst_right->inst_imm;
247 if (mono_sparc_is_sparc64 ()) {
248 guint32 real_offset = tree->inst_right->inst_imm - MONO_SPARC_STACK_BIAS;
249 /* Correct for the additions in get_call_info () */
250 offset = MONO_SPARC_STACK_BIAS + (real_offset & ~(7));
251 tree->opcode = OP_STOREI8_MEMBASE_REG;
255 tree->opcode = OP_STOREI1_MEMBASE_REG;
256 else if (offset & 0x2)
257 tree->opcode = OP_STOREI2_MEMBASE_REG;
259 tree->opcode = OP_STOREI4_MEMBASE_REG;
261 tree->inst_destbasereg = tree->inst_right->inst_basereg;
262 tree->inst_offset = offset;
263 tree->sreg1 = state->left->reg1;
264 mono_bblock_add_inst (s->cbb, tree);
267 stmt: OP_SPARC_OUTARG_MEM (freg) {
268 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_right->inst_basereg,
269 tree->inst_right->inst_imm, state->left->reg1);
272 stmt: OP_SPARC_OUTARG_MEMPAIR (lreg) {
273 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, tree->inst_right->inst_basereg,
274 tree->inst_right->inst_imm, state->left->reg2);
275 tree->opcode = OP_STOREI4_MEMBASE_REG;
276 tree->inst_destbasereg = tree->inst_right->inst_basereg;
277 tree->inst_offset = tree->inst_right->inst_imm + 4;
278 tree->sreg1 = state->left->reg1;
279 mono_bblock_add_inst (s->cbb, tree);
282 stmt: OP_SPARC_OUTARG_MEMPAIR (freg) {
283 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_right->inst_basereg,
284 tree->inst_right->inst_imm, state->left->reg1);
287 stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (lreg) {
288 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
290 int dreg = mono_regstate_next_int (s->rs);
291 MONO_EMIT_NEW_UNALU (s, OP_SETREG, dreg, state->left->reg2);
292 tree->opcode = OP_STOREI4_MEMBASE_REG;
293 tree->inst_destbasereg = tree->inst_right->inst_basereg;
294 tree->inst_offset = tree->inst_right->inst_imm + 4;
295 tree->sreg1 = state->left->reg1;
296 mono_bblock_add_inst (s->cbb, tree);
298 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
301 stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (freg) {
302 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
304 int dreg = mono_regstate_next_int (s->rs);
305 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_right->inst_basereg,
306 tree->inst_right->inst_imm, state->left->reg1);
307 /* floating-point <-> integer transfer must go through memory */
308 /* Load most significant word into register */
309 MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, tree->inst_right->inst_basereg, tree->inst_right->inst_imm);
311 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
314 stmt: OP_SPARC_OUTARG_FLOAT_REG (freg) {
315 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
317 tree->opcode = OP_SPARC_SETFREG_FLOAT;
318 tree->dreg = mono_regstate_next_int (s->rs);
319 tree->sreg1 = state->left->reg1;
320 mono_bblock_add_inst (s->cbb, tree);
322 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE);
325 stmt: OP_SPARC_OUTARG_DOUBLE_REG (freg) {
326 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
328 tree->opcode = OP_SETFREG;
329 tree->dreg = mono_regstate_next_int (s->rs);
330 tree->sreg1 = state->left->reg1;
331 mono_bblock_add_inst (s->cbb, tree);
333 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE);
336 # Handles scalar valuetypes like RuntimeTypeHandle
337 reg: OP_OUTARG_VT (OP_ICONST) {
338 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, sparc_sp, tree->inst_c1, state->left->tree->inst_c0);
339 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
342 reg: OP_OUTARG_VT (OP_AOTCONST) {
343 MONO_EMIT_NEW_AOTCONST (s, state->reg1, state->left->tree->inst_p0, state->left->tree->inst_c1);
344 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, sparc_sp, tree->inst_c1, state->reg1);
345 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
348 # FIXME: Unify this with the previous rule
349 reg: OP_OUTARG_VT (OP_REFANYTYPE (reg)) {
350 MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
351 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, sparc_sp, tree->inst_c1, state->reg1);
352 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
355 reg: OP_OUTARG_VT (base) {
356 int size = tree->backend.size;
357 mini_emit_memcpy (s, sparc_sp, tree->inst_c1, state->left->tree->inst_basereg, state->left->tree->inst_offset, size, 0);
358 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
361 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
362 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
364 tree->opcode = OP_SETREG;
365 tree->sreg1 = state->left->left->tree->dreg;
366 tree->dreg = mono_regstate_next_int (s->rs);
367 mono_bblock_add_inst (s->cbb, tree);
369 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
372 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGOFFSET)) {
373 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
375 int dreg = mono_regstate_next_int (s->rs);
376 MONO_EMIT_NEW_LOAD_MEMBASE (s, dreg, state->left->left->tree->inst_basereg,
377 state->left->left->tree->inst_offset);
379 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
382 stmt: OP_OUTARG_VT (OP_ICONST) {
383 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
385 tree->opcode = OP_SETREGIMM;
386 tree->dreg = mono_regstate_next_int (s->rs);
387 tree->inst_imm = state->left->tree->inst_c0;
388 mono_bblock_add_inst (s->cbb, tree);
390 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
393 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
394 /* nothing to do: the value is already on the FP stack */
397 reg: CEE_LDIND_I1 (OP_REGVAR) {
398 MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->tree->dreg);
401 reg: CEE_LDIND_I2 (OP_REGVAR) {
402 MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->tree->dreg);
405 stmt: CEE_BNE_UN (fpcflags) {
406 tree->opcode = OP_FBNE_UN;
407 mono_bblock_add_inst (s->cbb, tree);
410 stmt: CEE_BEQ (fpcflags) {
411 tree->opcode = OP_FBEQ;
412 mono_bblock_add_inst (s->cbb, tree);
415 stmt: CEE_BLT (fpcflags) {
416 tree->opcode = OP_FBLT;
417 mono_bblock_add_inst (s->cbb, tree);
420 stmt: CEE_BLT_UN (fpcflags) {
421 tree->opcode = OP_FBLT_UN;
422 mono_bblock_add_inst (s->cbb, tree);
425 stmt: CEE_BGT (fpcflags) {
426 tree->opcode = OP_FBGT;
427 mono_bblock_add_inst (s->cbb, tree);
430 stmt: CEE_BGT_UN (fpcflags) {
431 tree->opcode = OP_FBGT_UN;
432 mono_bblock_add_inst (s->cbb, tree);
435 stmt: CEE_BGE (fpcflags) {
436 tree->opcode = OP_FBGE;
437 mono_bblock_add_inst (s->cbb, tree);
440 stmt: CEE_BGE_UN (fpcflags) {
441 tree->opcode = OP_FBGE_UN;
442 mono_bblock_add_inst (s->cbb, tree);
445 stmt: CEE_BLE (fpcflags) {
446 tree->opcode = OP_FBLE;
447 mono_bblock_add_inst (s->cbb, tree);
450 stmt: CEE_BLE_UN (fpcflags) {
451 tree->opcode = OP_FBLE_UN;
452 mono_bblock_add_inst (s->cbb, tree);
455 stmt: CEE_POP (freg) "0" {
459 stmt: OP_START_HANDLER {
460 mono_bblock_add_inst (s->cbb, tree);
463 stmt: CEE_ENDFINALLY {
464 //MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
465 //MONO_EMIT_NEW_LOAD_MEMBASE (s, sparc_o7, spvar->inst_basereg, spvar->inst_offset);
466 mono_bblock_add_inst (s->cbb, tree);
469 stmt: OP_ENDFILTER (reg) {
470 //MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
471 //MONO_EMIT_NEW_LOAD_MEMBASE (s, sparc_o7, spvar->inst_basereg, spvar->inst_offset);
472 tree->sreg1 = state->left->reg1;
473 mono_bblock_add_inst (s->cbb, tree);
476 stmt: OP_START_HANDLER {
479 stmt: CEE_ENDFINALLY {
480 mono_bblock_add_inst (s->cbb, tree);
483 stmt: OP_ENDFILTER (reg) {
484 tree->sreg1 = state->left->reg1;
485 tree->dreg = state->reg1;
486 mono_bblock_add_inst (s->cbb, tree);
489 reg: OP_CEQ (OP_COMPARE (freg, freg)) {
490 MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
491 state->left->right->reg1);
494 reg: OP_CLT (OP_COMPARE (freg, freg)) {
495 MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
496 state->left->right->reg1);
499 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {
500 MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
501 state->left->right->reg1);
504 reg: OP_CGT (OP_COMPARE (freg, freg)) {
505 MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
506 state->left->right->reg1);
509 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {
510 MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
511 state->left->right->reg1);
514 reg: OP_LOCALLOC (reg) {
515 tree->sreg1 = state->left->tree->dreg;
516 mono_bblock_add_inst (s->cbb, tree);
523 reg: CEE_LDIND_REF (OP_REGVAR),
524 reg: CEE_LDIND_I (OP_REGVAR),
525 reg: CEE_LDIND_I4 (OP_REGVAR),
526 reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
527 /* This rule might not work on all archs, hence it is sparc only */
528 state->reg1 = state->left->tree->dreg;
529 tree->dreg = state->reg1;
532 stmt: CEE_STIND_I1 (OP_REGVAR, OP_ICONST) {
533 tree->opcode = OP_ICONST;
534 tree->dreg = state->left->tree->dreg;
535 tree->inst_c0 = state->right->tree->inst_c0;
536 mono_bblock_add_inst (s->cbb, tree);
539 stmt: CEE_STIND_I2 (OP_REGVAR, OP_ICONST) {
540 tree->opcode = OP_ICONST;
541 tree->dreg = state->left->tree->dreg;
542 tree->inst_c0 = state->right->tree->inst_c0;
543 mono_bblock_add_inst (s->cbb, tree);
546 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (reg, OP_ICONST)) {
547 MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
550 stmt: CEE_STIND_REF (OP_REGVAR, CEE_ADD (reg, OP_ICONST)) {
551 MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
554 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_SUB (reg, OP_ICONST)) {
555 MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
558 stmt: CEE_STIND_REF (OP_REGVAR, CEE_SUB (reg, OP_ICONST)) {
559 MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->left->tree->dreg, state->right->left->reg1, state->right->right->tree->inst_c0);
562 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_ADD (reg, reg)) {
563 MONO_EMIT_BIALU (s, tree, CEE_ADD, state->left->tree->dreg, state->right->left->reg1, state->right->right->reg1);
566 stmt: CEE_STIND_REF (OP_REGVAR, CEE_ADD (reg, reg)) {
567 MONO_EMIT_BIALU (s, tree, CEE_ADD, state->left->tree->dreg, state->right->left->reg1, state->right->right->reg1);
570 stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4(base)) {
571 MONO_EMIT_LOAD_MEMBASE (s, tree, state->left->tree->dreg, state->right->left->tree->inst_basereg,
572 state->right->left->tree->inst_offset);
573 mono_bblock_add_inst (s->cbb, tree);
576 stmt: CEE_STIND_REF (OP_REGVAR, CEE_LDIND_REF(base)) {
577 MONO_EMIT_LOAD_MEMBASE (s, tree, state->left->tree->dreg, state->right->left->tree->inst_basereg,
578 state->right->left->tree->inst_offset);
579 mono_bblock_add_inst (s->cbb, tree);
582 stmt: OP_SETRET (CEE_LDIND_I1(base)),
583 stmt: OP_SETRET (CEE_LDIND_U1(base)),
584 stmt: OP_SETRET (CEE_LDIND_I2(base)),
585 stmt: OP_SETRET (CEE_LDIND_U2(base)),
586 stmt: OP_SETRET (CEE_LDIND_I(base)),
587 stmt: OP_SETRET (CEE_LDIND_REF(base)),
588 stmt: OP_SETRET (CEE_LDIND_I4(base)),
589 stmt: OP_SETRET (CEE_LDIND_U4(base)) {
590 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode),
591 sparc_i0, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset);
592 mono_bblock_add_inst (s->cbb, tree);
595 stmt: OP_SETRET (CEE_LDIND_I4(OP_REGVAR)) {
596 tree->opcode = OP_SETREG;
597 tree->dreg = sparc_i0;
598 tree->sreg1 = state->left->left->tree->dreg;
599 mono_bblock_add_inst (s->cbb, tree);
602 stmt: OP_SETRET (CEE_LDIND_I(OP_REGVAR)) {
603 tree->opcode = OP_SETREG;
604 tree->dreg = sparc_i0;
605 tree->sreg1 = state->left->left->tree->dreg;
606 mono_bblock_add_inst (s->cbb, tree);
609 stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)),
610 stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) {
611 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
613 tree->opcode = OP_SETREG;
614 tree->dreg = mono_regstate_next_int (s->rs);
615 tree->sreg1 = state->left->left->tree->dreg;
616 mono_bblock_add_inst (s->cbb, tree);
618 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
621 stmt: OP_OUTARG (CEE_LDIND_REF(base)) {
622 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
624 int dreg = mono_regstate_next_int (s->rs);
625 MONO_EMIT_LOAD_MEMBASE (s, tree, dreg, state->left->left->tree->inst_basereg,
626 state->left->left->tree->inst_offset);
627 mono_bblock_add_inst (s->cbb, tree);
629 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
632 stmt: OP_OUTARG (CEE_LDIND_I4(base)) {
633 MonoCallInst *call = (MonoCallInst*)tree->inst_right->inst_left;
635 int dreg = mono_regstate_next_int (s->rs);
636 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, dreg, state->left->left->tree->inst_basereg,
637 state->left->left->tree->inst_offset);
638 mono_bblock_add_inst (s->cbb, tree);
640 mono_call_inst_add_outarg_reg (s, call, dreg, tree->backend.reg3, FALSE);
643 reg: OP_LDADDR (OP_REGOFFSET) "1" {
644 if (state->left->tree->inst_offset) {
645 MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset);
647 tree->opcode = OP_MOVE;
648 tree->sreg1 = state->left->tree->inst_basereg;
649 tree->dreg = state->reg1;
651 mono_bblock_add_inst (s->cbb, tree);
654 lreg: OP_LNEG (lreg) "3" {
655 /* The one in inssel.brg doesn't work, this one is based on gcc code */
656 MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, 0, state->left->reg1);
657 MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, 0, state->left->reg2);
660 # FIXME: This rule was commented out in inssel.brg, why ?
661 reg: CEE_REM (reg, OP_ICONST) {
662 MONO_EMIT_BIALU_IMM (s, tree, OP_REM_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
666 reg: CEE_DIV (reg, OP_ICONST) {
667 MONO_EMIT_BIALU_IMM (s, tree, OP_DIV_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
670 reg: OP_LOCALLOC (OP_ICONST) {
671 tree->opcode = OP_SPARC_LOCALLOC_IMM;
672 tree->inst_c0 = state->left->tree->inst_c0;
673 tree->dreg = state->reg1;
674 mono_bblock_add_inst (s->cbb, tree);
677 # FIXME: Optimized MEMCPY for copying valuetypes
679 # Optimized version for initializing valuetypes on the stack
680 stmt: OP_MEMSET (OP_LDADDR(OP_REGOFFSET)) "0" {
681 int size = tree->backend.size;
682 int offset = state->left->left->tree->inst_offset;
683 int destreg = state->left->left->tree->inst_basereg;
686 if (tree->inst_imm) {
687 val_reg = mono_regstate_next_int (s->rs);
688 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
693 /* Target address must be dword aligned */
694 if ((tree->inst_imm == 0) && (size >= 8) &&
695 (destreg == sparc_fp) && (((offset - MONO_SPARC_STACK_BIAS) % 8) == 0)) {
696 if (!mono_sparc_is_v9 ()) {
698 MONO_EMIT_NEW_ICONST (s, sparc_g1, 0);
701 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
709 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, 0);
717 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
722 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
727 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
733 stmt: OP_MEMSET (reg) "0" {
734 int size = tree->backend.size;
736 int destreg = state->left->reg1;
739 if (tree->inst_imm) {
740 val_reg = mono_regstate_next_int (s->rs);
741 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
746 /* FIXME: This assumes the destination is dword aligned */
748 if ((tree->inst_imm == 0) && (size >= 8)) {
750 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_IMM, destreg, offset, sparc_g0);
758 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
763 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
768 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
775 stmt: CEE_STIND_R8 (base, OP_R8CONST) {
776 /* fp constants are pricy on SPARC */
777 guint64 d = *(guint64*)state->right->tree->inst_p0;
780 if (sizeof (gpointer) == 8) {
781 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI8_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset, sparc_g0);
784 /* STOREI8 would write %g1 as well */
785 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset, sparc_g0);
786 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset + 4, sparc_g0);
790 state->right->tree->dreg = state->reg1;
791 mono_bblock_add_inst (s->cbb, state->right->tree);
792 MONO_EMIT_STORE_MEMBASE (s, tree, OP_STORER8_MEMBASE_REG, state->left->tree->inst_basereg,
793 state->left->tree->inst_offset, state->reg1);