2 int size_to_ia64_load_u_membase_inc (int size);
3 int size_to_store_membase_reg (int size);
4 int size_to_ia64_store_membase_inc_reg (int size);
9 # inssel-ia64.brg: burg file for special IA64 instructions
12 # Zoltan Varga (vargaz@gmail.com)
14 # (C) 2002 Ximian, Inc.
17 reg: CEE_LDIND_I8 (OP_REGVAR) {
18 state->reg1 = state->left->tree->dreg;
21 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
22 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
25 reg: CEE_LDIND_I1 (OP_REGVAR) {
26 MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
28 reg: CEE_LDIND_I2 (OP_REGVAR) {
29 MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
31 stmt: CEE_BEQ (fpcflags) {
32 tree->opcode = OP_FBEQ;
33 mono_bblock_add_inst (s->cbb, tree);
36 stmt: CEE_BNE_UN (fpcflags) {
37 tree->opcode = OP_FBNE_UN;
38 mono_bblock_add_inst (s->cbb, tree);
41 stmt: CEE_BLT (fpcflags) {
42 tree->opcode = OP_FBLT;
43 mono_bblock_add_inst (s->cbb, tree);
46 stmt: CEE_BLT_UN (fpcflags) {
47 tree->opcode = OP_FBLT_UN;
48 mono_bblock_add_inst (s->cbb, tree);
51 stmt: CEE_BGT (fpcflags) {
52 tree->opcode = OP_FBGT;
53 mono_bblock_add_inst (s->cbb, tree);
56 stmt: CEE_BGT_UN (fpcflags) {
57 tree->opcode = OP_FBGT_UN;
58 mono_bblock_add_inst (s->cbb, tree);
61 stmt: CEE_BGE (fpcflags) {
62 tree->opcode = OP_FBGE;
63 mono_bblock_add_inst (s->cbb, tree);
66 stmt: CEE_BGE_UN (fpcflags) {
67 tree->opcode = OP_FBGE_UN;
68 mono_bblock_add_inst (s->cbb, tree);
71 stmt: CEE_BLE (fpcflags) {
72 tree->opcode = OP_FBLE;
73 mono_bblock_add_inst (s->cbb, tree);
76 stmt: CEE_BLE_UN (fpcflags) {
77 tree->opcode = OP_FBLE_UN;
78 mono_bblock_add_inst (s->cbb, tree);
81 fpcflags: OP_COMPARE (freg, freg) {
82 tree->opcode = OP_FCOMPARE;
83 mono_bblock_add_inst (s->cbb, tree);
86 reg: OP_CEQ (fpcflags) {
87 tree->dreg = state->reg1;
88 tree->opcode = OP_FCEQ;
89 mono_bblock_add_inst (s->cbb, tree);
92 reg: OP_CLT (fpcflags) {
93 tree->dreg = state->reg1;
94 tree->opcode = OP_FCLT;
95 mono_bblock_add_inst (s->cbb, tree);
98 reg: OP_CLT_UN (fpcflags) {
99 tree->dreg = state->reg1;
100 tree->opcode = OP_FCLT_UN;
101 mono_bblock_add_inst (s->cbb, tree);
104 reg: OP_CGT (fpcflags) {
105 tree->dreg = state->reg1;
106 tree->opcode = OP_FCGT;
107 mono_bblock_add_inst (s->cbb, tree);
110 reg: OP_CGT_UN (fpcflags) {
111 tree->dreg = state->reg1;
112 tree->opcode = OP_FCGT_UN;
113 mono_bblock_add_inst (s->cbb, tree);
116 freg: OP_LCONV_TO_R8 (reg) {
117 /* FIXME: Move this inssel-long.brg */
118 tree->sreg1 = state->left->reg1;
119 tree->dreg = state->reg1;
120 mono_bblock_add_inst (s->cbb, tree);
123 freg: OP_LCONV_TO_R4 (reg) {
124 /* FIXME: Move this inssel-long.brg */
125 tree->sreg1 = state->left->reg1;
126 tree->dreg = state->reg1;
127 mono_bblock_add_inst (s->cbb, tree);
130 stmt: OP_OUTARG_REG (reg) {
131 /* FIXME: Move this to inssel.brg */
132 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
134 tree->opcode = OP_MOVE;
135 tree->sreg1 = state->left->reg1;
136 tree->dreg = mono_regstate_next_int (s->rs);
137 mono_bblock_add_inst (s->cbb, tree);
139 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
142 stmt: OP_OUTARG_REG (CEE_LDIND_I (base)),
143 stmt: OP_OUTARG_REG (CEE_LDIND_REF (base)),
144 stmt: OP_OUTARG_REG (CEE_LDIND_I1 (base)),
145 stmt: OP_OUTARG_REG (CEE_LDIND_U1 (base)),
146 stmt: OP_OUTARG_REG (CEE_LDIND_I2 (base)),
147 stmt: OP_OUTARG_REG (CEE_LDIND_U2 (base)),
148 stmt: OP_OUTARG_REG (CEE_LDIND_I4 (base)),
149 stmt: OP_OUTARG_REG (CEE_LDIND_U4 (base)),
150 stmt: OP_OUTARG_REG (CEE_LDIND_I8 (base)) {
151 /* FIXME: Move this to inssel.brg or inssel-long.brg */
152 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
154 MonoInst *base = state->left->left->tree;
156 dreg = mono_regstate_next_int (s->rs);
157 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode),
158 dreg, base->inst_basereg, base->inst_offset);
160 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
163 stmt: OP_OUTARG_REG (OP_I8CONST),
164 stmt: OP_OUTARG_REG (OP_ICONST) {
165 /* FIXME: Move this to inssel.brg or inssel-long.brg */
166 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
168 tree->opcode = OP_ICONST;
169 tree->inst_c0 = state->left->tree->inst_c0;
170 tree->dreg = mono_regstate_next_int (s->rs);
171 mono_bblock_add_inst (s->cbb, tree);
173 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
176 stmt: OP_OUTARG_REG (CEE_LDIND_I (OP_REGVAR)),
177 stmt: OP_OUTARG_REG (CEE_LDIND_I8 (OP_REGVAR)),
178 stmt: OP_OUTARG_REG (CEE_LDIND_I4 (OP_REGVAR)),
179 stmt: OP_OUTARG_REG (CEE_LDIND_U4 (OP_REGVAR)),
180 stmt: OP_OUTARG_REG (CEE_LDIND_REF (OP_REGVAR)) {
181 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
183 tree->opcode = OP_MOVE;
184 tree->sreg1 = state->left->left->tree->dreg;
185 tree->dreg = mono_regstate_next_int (s->rs);
186 mono_bblock_add_inst (s->cbb, tree);
188 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
191 stmt: OP_OUTARG_FREG (freg) {
192 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
194 tree->opcode = OP_FMOVE;
195 tree->sreg1 = state->left->reg1;
196 tree->dreg = mono_regstate_next_float (s->rs);
197 mono_bblock_add_inst (s->cbb, tree);
199 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, TRUE);
202 stmt: OP_OUTARG (reg) {
203 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
206 stmt: OP_OUTARG (freg) {
207 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
210 stmt: OP_OUTARG_R4 (freg) {
211 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
214 stmt: OP_OUTARG_REG (OP_LDADDR (OP_REGOFFSET)),
215 stmt: OP_OUTARG_REG (CEE_LDOBJ (OP_REGOFFSET)) {
216 /* FIXME: Move this to inssel.brg */
217 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
219 tree->opcode = OP_ADD_IMM;
220 tree->sreg1 = state->left->left->tree->inst_basereg;
221 tree->inst_imm = state->left->left->tree->inst_offset;
222 tree->dreg = mono_regstate_next_int (s->rs);
223 mono_bblock_add_inst (s->cbb, tree);
225 mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
228 stmt: OP_SETRET (reg) {
229 tree->opcode = OP_MOVE;
230 tree->sreg1 = state->left->reg1;
231 tree->dreg = MONO_ARCH_RETREG1;
232 mono_bblock_add_inst (s->cbb, tree);
235 stmt: OP_SETRET (freg) {
236 tree->opcode = OP_FMOVE;
237 tree->sreg1 = state->left->reg1;
238 tree->dreg = MONO_ARCH_FRETREG1;
239 mono_bblock_add_inst (s->cbb, tree);
242 # Optimized call instructions
243 reg: OP_LCALL_REG (OP_ICONST),
244 reg: OP_LCALL_REG (OP_I8CONST) {
245 /* FIXME: Move this to inssel-long.brg */
246 tree->opcode = OP_LCALL;
247 ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
248 tree->dreg = state->reg1;
249 mono_bblock_add_inst (s->cbb, tree);
252 stmt: OP_OUTARG_VT (CEE_LDOBJ (base), base) {
253 MonoInst *vt = state->left->left->tree;
254 MonoInst *stack_addr = state->right->tree;
255 int sz = stack_addr->inst_imm;
260 mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0);
263 # This handles trees like outarg_vt (refanytype)
264 stmt: OP_OUTARG_VT (reg, base) {
265 MonoInst *stack_addr = state->right->tree;
267 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1);
270 stmt: OP_START_HANDLER {
271 mono_bblock_add_inst (s->cbb, tree);
274 stmt: CEE_ENDFINALLY {
275 mono_bblock_add_inst (s->cbb, tree);
278 stmt: OP_ENDFILTER (reg) {
279 tree->sreg1 = state->left->reg1;
280 mono_bblock_add_inst (s->cbb, tree);
283 reg: OP_LOCALLOC (reg) {
284 tree->sreg1 = state->left->reg1;
285 tree->dreg = state->reg1;
286 mono_bblock_add_inst (s->cbb, tree);
289 reg: CEE_LDIND_REF (OP_REGVAR),
290 reg: CEE_LDIND_I (OP_REGVAR),
291 reg: CEE_LDIND_I8 (OP_REGVAR),
292 reg: CEE_LDIND_I4 (OP_REGVAR),
293 reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
294 state->reg1 = state->left->tree->dreg;
295 tree->dreg = state->reg1;
298 reg: OP_ATOMIC_ADD_NEW_I4 (base, OP_ICONST),
299 reg: OP_ATOMIC_ADD_NEW_I8 (base, OP_ICONST) {
300 tree->opcode = tree->opcode == OP_ATOMIC_ADD_NEW_I4 ? OP_IA64_FETCHADD4_IMM : OP_IA64_FETCHADD8_IMM;
301 tree->dreg = state->reg1;
302 tree->inst_imm = state->right->tree->inst_imm;
303 tree->inst_basereg = state->left->tree->inst_basereg;
304 tree->inst_offset = state->left->tree->inst_offset;
306 mono_bblock_add_inst (s->cbb, tree);
308 int imm = state->right->tree->inst_imm;
310 MBCOND (imm == 1 || imm == 4 || imm == 8 || imm == 16 || imm == -1 || imm == -4 || imm == -8 || imm == -16);
314 reg: OP_ATOMIC_EXCHANGE_I4 (base, reg),
315 reg: OP_ATOMIC_EXCHANGE_I8 (base, reg),
316 reg: OP_ATOMIC_ADD_NEW_I4 (base, reg),
317 reg: OP_ATOMIC_ADD_NEW_I8 (base, reg) {
318 tree->opcode = tree->opcode;
319 tree->dreg = state->reg1;
320 tree->sreg2 = state->right->reg1;
321 tree->inst_basereg = state->left->tree->inst_basereg;
322 tree->inst_offset = state->left->tree->inst_offset;
324 mono_bblock_add_inst (s->cbb, tree);
327 # Optimized memset implementation
328 stmt: OP_MEMSET (base) "0" {
329 int dest_reg, dest_reg2, val_reg, unit, align;
330 int size = tree->unused;
332 dest_reg = mono_regstate_next_int (s->rs);
334 if (state->left->tree->inst_basereg == s->frame_reg)
335 /* Aligned by mono_allocate_stack_slots */
340 if (tree->inst_imm == 0)
343 val_reg = mono_regstate_next_int (s->rs);
345 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
348 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
350 for (unit = align; unit >= 1; unit = unit >> 1) {
351 dest_reg2 = mono_regstate_next_int (s->rs);
353 /* Use two destination regs to increase paralellism */
354 if (size >= 2 * unit) {
355 int diff = (size / (2 * unit)) * unit;
356 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + diff);
358 while (size >= (2 * unit)) {
359 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
360 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg2, 0, val_reg);
365 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, dest_reg, diff);
368 while (size >= unit) {
370 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_store_membase_reg (unit), dest_reg, 0, val_reg);
372 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
379 # Optimized memcpy implementation
380 stmt: OP_MEMCPY (base, base) "0" {
381 int cur_reg, src_reg, dest_reg, unit;
382 int size = tree->unused;
385 src_reg = mono_regstate_next_int (s->rs);
386 dest_reg = mono_regstate_next_int (s->rs);
388 if ((state->left->tree->inst_basereg == s->frame_reg) &&
389 (state->right->tree->inst_basereg == s->frame_reg))
390 /* Aligned by mono_allocate_stack_slots */
395 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
396 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, src_reg, state->right->tree->inst_basereg, state->right->tree->inst_offset);
398 for (unit = align; unit >= 1; unit = unit >> 1) {
399 while (size >= unit) {
400 cur_reg = mono_regstate_next_int (s->rs);
401 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, size_to_ia64_load_u_membase_inc (unit), cur_reg, src_reg, 0);
402 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, cur_reg);
411 size_to_ia64_load_u_membase_inc (int size)
415 return OP_IA64_LOADU1_MEMBASE_INC;
417 return OP_IA64_LOADU2_MEMBASE_INC;
419 return OP_IA64_LOADU4_MEMBASE_INC;
421 return OP_IA64_LOADI8_MEMBASE_INC;
423 g_assert_not_reached ();
429 size_to_store_membase_reg (int size)
433 return OP_STOREI1_MEMBASE_REG;
435 return OP_STOREI2_MEMBASE_REG;
437 return OP_STOREI4_MEMBASE_REG;
439 return OP_STOREI8_MEMBASE_REG;
441 g_assert_not_reached ();
447 size_to_ia64_store_membase_inc_reg (int size)
451 return OP_IA64_STOREI1_MEMBASE_INC_REG;
453 return OP_IA64_STOREI2_MEMBASE_INC_REG;
455 return OP_IA64_STOREI4_MEMBASE_INC_REG;
457 return OP_IA64_STOREI8_MEMBASE_INC_REG;
459 g_assert_not_reached ();