5 # inssel-ia64.brg: burg file for special IA64 instructions
8 # Zoltan Varga (vargaz@gmail.com)
10 # (C) 2002 Ximian, Inc.
13 reg: CEE_LDIND_I8 (OP_REGVAR) {
14 state->reg1 = state->left->tree->dreg;
17 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
18 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
21 reg: CEE_LDIND_I1 (OP_REGVAR) {
22 MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
24 reg: CEE_LDIND_I2 (OP_REGVAR) {
25 MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
27 stmt: CEE_BEQ (fpcflags) {
28 tree->opcode = OP_FBEQ;
29 mono_bblock_add_inst (s->cbb, tree);
32 stmt: CEE_BNE_UN (fpcflags) {
33 tree->opcode = OP_FBNE_UN;
34 mono_bblock_add_inst (s->cbb, tree);
37 stmt: CEE_BLT (fpcflags) {
38 tree->opcode = OP_FBLT;
39 mono_bblock_add_inst (s->cbb, tree);
42 stmt: CEE_BLT_UN (fpcflags) {
43 tree->opcode = OP_FBLT_UN;
44 mono_bblock_add_inst (s->cbb, tree);
47 stmt: CEE_BGT (fpcflags) {
48 tree->opcode = OP_FBGT;
49 mono_bblock_add_inst (s->cbb, tree);
52 stmt: CEE_BGT_UN (fpcflags) {
53 tree->opcode = OP_FBGT_UN;
54 mono_bblock_add_inst (s->cbb, tree);
57 stmt: CEE_BGE (fpcflags) {
58 tree->opcode = OP_FBGE;
59 mono_bblock_add_inst (s->cbb, tree);
62 stmt: CEE_BGE_UN (fpcflags) {
63 tree->opcode = OP_FBGE_UN;
64 mono_bblock_add_inst (s->cbb, tree);
67 stmt: CEE_BLE (fpcflags) {
68 tree->opcode = OP_FBLE;
69 mono_bblock_add_inst (s->cbb, tree);
72 stmt: CEE_BLE_UN (fpcflags) {
73 tree->opcode = OP_FBLE_UN;
74 mono_bblock_add_inst (s->cbb, tree);
77 fpcflags: OP_COMPARE (freg, freg) {
78 tree->opcode = OP_FCOMPARE;
79 mono_bblock_add_inst (s->cbb, tree);
82 reg: OP_CEQ (fpcflags) {
83 tree->dreg = state->reg1;
84 tree->opcode = OP_FCEQ;
85 mono_bblock_add_inst (s->cbb, tree);
88 reg: OP_CLT (fpcflags) {
89 tree->dreg = state->reg1;
90 tree->opcode = OP_FCLT;
91 mono_bblock_add_inst (s->cbb, tree);
94 reg: OP_CLT_UN (fpcflags) {
95 tree->dreg = state->reg1;
96 tree->opcode = OP_FCLT_UN;
97 mono_bblock_add_inst (s->cbb, tree);
100 reg: OP_CGT (fpcflags) {
101 tree->dreg = state->reg1;
102 tree->opcode = OP_FCGT;
103 mono_bblock_add_inst (s->cbb, tree);
106 reg: OP_CGT_UN (fpcflags) {
107 tree->dreg = state->reg1;
108 tree->opcode = OP_FCGT_UN;
109 mono_bblock_add_inst (s->cbb, tree);
112 freg: OP_LCONV_TO_R8 (reg) {
113 /* FIXME: Move this inssel-long.brg */
114 tree->sreg1 = state->left->reg1;
115 tree->dreg = state->reg1;
116 mono_bblock_add_inst (s->cbb, tree);
119 freg: OP_LCONV_TO_R4 (reg) {
120 /* FIXME: Move this inssel-long.brg */
121 tree->sreg1 = state->left->reg1;
122 tree->dreg = state->reg1;
123 mono_bblock_add_inst (s->cbb, tree);
126 stmt: OP_OUTARG_REG (reg) {
127 /* FIXME: Move this to inssel.brg */
128 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
130 tree->opcode = OP_MOVE;
131 tree->sreg1 = state->left->reg1;
132 tree->dreg = mono_regstate_next_int (s->rs);
133 mono_bblock_add_inst (s->cbb, tree);
135 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
138 stmt: OP_OUTARG_REG (CEE_LDIND_I (base)),
139 stmt: OP_OUTARG_REG (CEE_LDIND_REF (base)),
140 stmt: OP_OUTARG_REG (CEE_LDIND_I1 (base)),
141 stmt: OP_OUTARG_REG (CEE_LDIND_U1 (base)),
142 stmt: OP_OUTARG_REG (CEE_LDIND_I2 (base)),
143 stmt: OP_OUTARG_REG (CEE_LDIND_U2 (base)),
144 stmt: OP_OUTARG_REG (CEE_LDIND_I4 (base)),
145 stmt: OP_OUTARG_REG (CEE_LDIND_U4 (base)),
146 stmt: OP_OUTARG_REG (CEE_LDIND_I8 (base)) {
147 /* FIXME: Move this to inssel.brg or inssel-long.brg */
148 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
150 MonoInst *base = state->left->left->tree;
152 dreg = mono_regstate_next_int (s->rs);
153 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode),
154 dreg, base->inst_basereg, base->inst_offset);
156 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
159 stmt: OP_OUTARG_REG (OP_I8CONST),
160 stmt: OP_OUTARG_REG (OP_ICONST) {
161 /* FIXME: Move this to inssel.brg or inssel-long.brg */
162 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
164 tree->opcode = OP_ICONST;
165 tree->inst_c0 = state->left->tree->inst_c0;
166 tree->dreg = mono_regstate_next_int (s->rs);
167 mono_bblock_add_inst (s->cbb, tree);
169 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
172 stmt: OP_OUTARG_REG (CEE_LDIND_I (OP_REGVAR)),
173 stmt: OP_OUTARG_REG (CEE_LDIND_I8 (OP_REGVAR)),
174 stmt: OP_OUTARG_REG (CEE_LDIND_I4 (OP_REGVAR)),
175 stmt: OP_OUTARG_REG (CEE_LDIND_U4 (OP_REGVAR)),
176 stmt: OP_OUTARG_REG (CEE_LDIND_REF (OP_REGVAR)) {
177 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
179 tree->opcode = OP_MOVE;
180 tree->sreg1 = state->left->left->tree->dreg;
181 tree->dreg = mono_regstate_next_int (s->rs);
182 mono_bblock_add_inst (s->cbb, tree);
184 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
187 stmt: OP_OUTARG_FREG (freg) {
188 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
190 tree->opcode = OP_FMOVE;
191 tree->sreg1 = state->left->reg1;
192 tree->dreg = mono_regstate_next_float (s->rs);
193 mono_bblock_add_inst (s->cbb, tree);
195 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE);
198 stmt: OP_OUTARG (reg) {
199 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
202 stmt: OP_OUTARG (freg) {
203 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
206 stmt: OP_OUTARG_R4 (freg) {
207 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
210 stmt: OP_OUTARG_REG (OP_LDADDR (OP_REGOFFSET)),
211 stmt: OP_OUTARG_REG (CEE_LDOBJ (OP_REGOFFSET)) {
212 /* FIXME: Move this to inssel.brg */
213 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
215 tree->opcode = OP_ADD_IMM;
216 tree->sreg1 = state->left->left->tree->inst_basereg;
217 tree->inst_imm = state->left->left->tree->inst_offset;
218 tree->dreg = mono_regstate_next_int (s->rs);
219 mono_bblock_add_inst (s->cbb, tree);
221 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, FALSE);
224 stmt: OP_SETRET (reg) {
225 tree->opcode = OP_MOVE;
226 tree->sreg1 = state->left->reg1;
227 tree->dreg = MONO_ARCH_RETREG1;
228 mono_bblock_add_inst (s->cbb, tree);
231 stmt: OP_SETRET (freg) {
232 tree->opcode = OP_FMOVE;
233 tree->sreg1 = state->left->reg1;
234 tree->dreg = MONO_ARCH_FRETREG1;
235 mono_bblock_add_inst (s->cbb, tree);
238 # Optimized call instructions
239 reg: OP_LCALL_REG (OP_ICONST),
240 reg: OP_LCALL_REG (OP_I8CONST) {
241 /* FIXME: Move this to inssel-long.brg */
242 tree->opcode = OP_LCALL;
243 ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
244 tree->dreg = state->reg1;
245 mono_bblock_add_inst (s->cbb, tree);
248 stmt: OP_OUTARG_VT (CEE_LDOBJ (base), base) {
249 MonoInst *vt = state->left->left->tree;
250 MonoInst *stack_addr = state->right->tree;
251 int sz = stack_addr->inst_imm;
256 mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0);
259 # This handles trees like outarg_vt (refanytype)
260 stmt: OP_OUTARG_VT (reg, base) {
261 MonoInst *stack_addr = state->right->tree;
263 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1);
266 stmt: OP_START_HANDLER {
267 mono_bblock_add_inst (s->cbb, tree);
270 stmt: CEE_ENDFINALLY {
271 mono_bblock_add_inst (s->cbb, tree);
274 stmt: OP_ENDFILTER (reg) {
275 tree->sreg1 = state->left->reg1;
276 mono_bblock_add_inst (s->cbb, tree);
279 reg: OP_LOCALLOC (reg) {
280 tree->sreg1 = state->left->reg1;
281 tree->dreg = state->reg1;
282 mono_bblock_add_inst (s->cbb, tree);
285 reg: CEE_LDIND_REF (OP_REGVAR),
286 reg: CEE_LDIND_I (OP_REGVAR),
287 reg: CEE_LDIND_I8 (OP_REGVAR),
288 reg: CEE_LDIND_I4 (OP_REGVAR),
289 reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
290 state->reg1 = state->left->tree->dreg;
291 tree->dreg = state->reg1;
294 reg: OP_ATOMIC_ADD_NEW_I4 (base, OP_ICONST),
295 reg: OP_ATOMIC_ADD_NEW_I8 (base, OP_ICONST) {
296 tree->opcode = tree->opcode == OP_ATOMIC_ADD_NEW_I4 ? OP_ATOMIC_ADD_IMM_NEW_I4 : OP_ATOMIC_ADD_IMM_NEW_I8;
297 tree->dreg = state->reg1;
298 tree->inst_imm = state->right->tree->inst_imm;
299 tree->inst_basereg = state->left->tree->inst_basereg;
300 tree->inst_offset = state->left->tree->inst_offset;
302 mono_bblock_add_inst (s->cbb, tree);
304 int imm = state->right->tree->inst_imm;
306 MBCOND (imm == 1 || imm == 4 || imm == 8 || imm == 16 || imm == -1 || imm == -4 || imm == -8 || imm == -16);
310 reg: OP_ATOMIC_EXCHANGE_I4 (base, reg),
311 reg: OP_ATOMIC_EXCHANGE_I8 (base, reg),
312 reg: OP_ATOMIC_ADD_NEW_I4 (base, reg),
313 reg: OP_ATOMIC_ADD_NEW_I8 (base, reg) {
314 tree->opcode = tree->opcode;
315 tree->dreg = state->reg1;
316 tree->sreg2 = state->right->reg1;
317 tree->inst_basereg = state->left->tree->inst_basereg;
318 tree->inst_offset = state->left->tree->inst_offset;
320 mono_bblock_add_inst (s->cbb, tree);
323 reg: OP_ATOMIC_ADD_IMM_NEW_I4 (base),
324 reg: OP_ATOMIC_ADD_IMM_NEW_I8 (base) {
325 tree->opcode = tree->opcode;
326 tree->dreg = state->reg1;
327 tree->inst_basereg = state->left->tree->inst_basereg;
328 tree->inst_offset = state->left->tree->inst_offset;
330 mono_bblock_add_inst (s->cbb, tree);
333 # Optimized memset implementation
334 stmt: OP_MEMSET (base) "0" {
335 int dest_reg, dest_reg2, val_reg, unit, align;
336 int size = tree->backend.size;
338 dest_reg = mono_regstate_next_int (s->rs);
340 if (state->left->tree->inst_basereg == s->frame_reg)
341 /* Aligned by mono_allocate_stack_slots */
346 if (tree->inst_imm == 0)
349 val_reg = mono_regstate_next_int (s->rs);
351 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
354 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
356 for (unit = align; unit >= 1; unit = unit >> 1) {
357 dest_reg2 = mono_regstate_next_int (s->rs);
359 /* Use two destination regs to increase paralellism */
360 if (size >= 2 * unit) {
361 int diff = (size / (2 * unit)) * unit;
362 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + diff);
364 while (size >= (2 * unit)) {
365 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
366 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg2, 0, val_reg);
371 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, dest_reg, diff);
374 while (size >= unit) {
376 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_store_membase_reg (unit), dest_reg, 0, val_reg);
378 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
385 # Optimized memcpy implementation
386 stmt: OP_MEMCPY (base, base) "0" {
387 int cur_reg, src_reg, dest_reg, unit;
388 int size = tree->backend.size;
391 src_reg = mono_regstate_next_int (s->rs);
392 dest_reg = mono_regstate_next_int (s->rs);
394 if ((state->left->tree->inst_basereg == s->frame_reg) &&
395 (state->right->tree->inst_basereg == s->frame_reg))
396 /* Aligned by mono_allocate_stack_slots */
401 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
402 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, src_reg, state->right->tree->inst_basereg, state->right->tree->inst_offset);
404 for (unit = align; unit >= 1; unit = unit >> 1) {
405 while (size >= unit) {
406 cur_reg = mono_regstate_next_int (s->rs);
407 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, size_to_ia64_load_u_membase_inc (unit), cur_reg, src_reg, 0);
408 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, cur_reg);
417 size_to_ia64_load_u_membase_inc (int size)
421 return OP_IA64_LOADU1_MEMBASE_INC;
423 return OP_IA64_LOADU2_MEMBASE_INC;
425 return OP_IA64_LOADU4_MEMBASE_INC;
427 return OP_IA64_LOADI8_MEMBASE_INC;
429 g_assert_not_reached ();
435 size_to_store_membase_reg (int size)
439 return OP_STOREI1_MEMBASE_REG;
441 return OP_STOREI2_MEMBASE_REG;
443 return OP_STOREI4_MEMBASE_REG;
445 return OP_STOREI8_MEMBASE_REG;
447 g_assert_not_reached ();
453 size_to_ia64_store_membase_inc_reg (int size)
457 return OP_IA64_STOREI1_MEMBASE_INC_REG;
459 return OP_IA64_STOREI2_MEMBASE_INC_REG;
461 return OP_IA64_STOREI4_MEMBASE_INC_REG;
463 return OP_IA64_STOREI8_MEMBASE_INC_REG;
465 g_assert_not_reached ();