2 int size_to_ia64_load_u_membase_inc (int size);
3 int size_to_ia64_store_membase_inc_reg (int size);
8 # inssel-ia64.brg: burg file for special IA64 instructions
11 # Zoltan Varga (vargaz@gmail.com)
13 # (C) 2002 Ximian, Inc.
16 reg: CEE_LDIND_I8 (OP_REGVAR) {
17 state->reg1 = state->left->tree->dreg;
20 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
21 MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
24 reg: CEE_LDIND_I1 (OP_REGVAR) {
25 MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
27 reg: CEE_LDIND_I2 (OP_REGVAR) {
28 MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
30 stmt: CEE_BEQ (fpcflags) {
31 tree->opcode = OP_FBEQ;
32 mono_bblock_add_inst (s->cbb, tree);
35 stmt: CEE_BNE_UN (fpcflags) {
36 tree->opcode = OP_FBNE_UN;
37 mono_bblock_add_inst (s->cbb, tree);
40 stmt: CEE_BLT (fpcflags) {
41 tree->opcode = OP_FBLT;
42 mono_bblock_add_inst (s->cbb, tree);
45 stmt: CEE_BLT_UN (fpcflags) {
46 tree->opcode = OP_FBLT_UN;
47 mono_bblock_add_inst (s->cbb, tree);
50 stmt: CEE_BGT (fpcflags) {
51 tree->opcode = OP_FBGT;
52 mono_bblock_add_inst (s->cbb, tree);
55 stmt: CEE_BGT_UN (fpcflags) {
56 tree->opcode = OP_FBGT_UN;
57 mono_bblock_add_inst (s->cbb, tree);
60 stmt: CEE_BGE (fpcflags) {
61 tree->opcode = OP_FBGE;
62 mono_bblock_add_inst (s->cbb, tree);
65 stmt: CEE_BGE_UN (fpcflags) {
66 tree->opcode = OP_FBGE_UN;
67 mono_bblock_add_inst (s->cbb, tree);
70 stmt: CEE_BLE (fpcflags) {
71 tree->opcode = OP_FBLE;
72 mono_bblock_add_inst (s->cbb, tree);
75 stmt: CEE_BLE_UN (fpcflags) {
76 tree->opcode = OP_FBLE_UN;
77 mono_bblock_add_inst (s->cbb, tree);
80 fpcflags: OP_COMPARE (freg, freg) {
81 tree->opcode = OP_FCOMPARE;
82 mono_bblock_add_inst (s->cbb, tree);
85 reg: OP_CEQ (fpcflags) {
86 tree->dreg = state->reg1;
87 tree->opcode = OP_FCEQ;
88 mono_bblock_add_inst (s->cbb, tree);
91 reg: OP_CLT (fpcflags) {
92 tree->dreg = state->reg1;
93 tree->opcode = OP_FCLT;
94 mono_bblock_add_inst (s->cbb, tree);
97 reg: OP_CLT_UN (fpcflags) {
98 tree->dreg = state->reg1;
99 tree->opcode = OP_FCLT_UN;
100 mono_bblock_add_inst (s->cbb, tree);
103 reg: OP_CGT (fpcflags) {
104 tree->dreg = state->reg1;
105 tree->opcode = OP_FCGT;
106 mono_bblock_add_inst (s->cbb, tree);
109 reg: OP_CGT_UN (fpcflags) {
110 tree->dreg = state->reg1;
111 tree->opcode = OP_FCGT_UN;
112 mono_bblock_add_inst (s->cbb, tree);
115 freg: OP_LCONV_TO_R8 (reg) {
116 /* FIXME: Move this inssel-long.brg */
117 tree->sreg1 = state->left->reg1;
118 tree->dreg = state->reg1;
119 mono_bblock_add_inst (s->cbb, tree);
122 freg: OP_LCONV_TO_R4 (reg) {
123 /* FIXME: Move this inssel-long.brg */
124 tree->sreg1 = state->left->reg1;
125 tree->dreg = state->reg1;
126 mono_bblock_add_inst (s->cbb, tree);
129 stmt: OP_OUTARG_REG (reg) {
130 /* FIXME: Move this to inssel.brg */
131 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
133 tree->opcode = OP_MOVE;
134 tree->sreg1 = state->left->reg1;
135 tree->dreg = mono_regstate_next_int (s->rs);
136 mono_bblock_add_inst (s->cbb, tree);
138 mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
141 stmt: OP_OUTARG_REG (CEE_LDIND_I (base)),
142 stmt: OP_OUTARG_REG (CEE_LDIND_REF (base)),
143 stmt: OP_OUTARG_REG (CEE_LDIND_I1 (base)),
144 stmt: OP_OUTARG_REG (CEE_LDIND_U1 (base)),
145 stmt: OP_OUTARG_REG (CEE_LDIND_I2 (base)),
146 stmt: OP_OUTARG_REG (CEE_LDIND_U2 (base)),
147 stmt: OP_OUTARG_REG (CEE_LDIND_I4 (base)),
148 stmt: OP_OUTARG_REG (CEE_LDIND_U4 (base)),
149 stmt: OP_OUTARG_REG (CEE_LDIND_I8 (base)) {
150 /* FIXME: Move this to inssel.brg or inssel-long.brg */
151 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
153 MonoInst *base = state->left->left->tree;
155 dreg = mono_regstate_next_int (s->rs);
156 MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode),
157 dreg, base->inst_basereg, base->inst_offset);
159 mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
162 stmt: OP_OUTARG_REG (OP_I8CONST),
163 stmt: OP_OUTARG_REG (OP_ICONST) {
164 /* FIXME: Move this to inssel.brg or inssel-long.brg */
165 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
167 tree->opcode = OP_ICONST;
168 tree->inst_c0 = state->left->tree->inst_c0;
169 tree->dreg = mono_regstate_next_int (s->rs);
170 mono_bblock_add_inst (s->cbb, tree);
172 mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
175 stmt: OP_OUTARG_REG (CEE_LDIND_I (OP_REGVAR)),
176 stmt: OP_OUTARG_REG (CEE_LDIND_I8 (OP_REGVAR)),
177 stmt: OP_OUTARG_REG (CEE_LDIND_I4 (OP_REGVAR)),
178 stmt: OP_OUTARG_REG (CEE_LDIND_U4 (OP_REGVAR)),
179 stmt: OP_OUTARG_REG (CEE_LDIND_REF (OP_REGVAR)) {
180 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
182 tree->opcode = OP_MOVE;
183 tree->sreg1 = state->left->left->tree->dreg;
184 tree->dreg = mono_regstate_next_int (s->rs);
185 mono_bblock_add_inst (s->cbb, tree);
187 mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
190 stmt: OP_OUTARG_FREG (freg) {
191 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
193 tree->opcode = OP_FMOVE;
194 tree->sreg1 = state->left->reg1;
195 tree->dreg = mono_regstate_next_float (s->rs);
196 mono_bblock_add_inst (s->cbb, tree);
198 mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE);
201 stmt: OP_OUTARG (reg) {
202 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
205 stmt: OP_OUTARG (freg) {
206 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
209 stmt: OP_OUTARG_R4 (freg) {
210 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
213 stmt: OP_OUTARG_REG (OP_LDADDR (OP_REGOFFSET)),
214 stmt: OP_OUTARG_REG (CEE_LDOBJ (OP_REGOFFSET)) {
215 /* FIXME: Move this to inssel.brg */
216 MonoCallInst *call = (MonoCallInst*)tree->inst_right;
218 tree->opcode = OP_ADD_IMM;
219 tree->sreg1 = state->left->left->tree->inst_basereg;
220 tree->inst_imm = state->left->left->tree->inst_offset;
221 tree->dreg = mono_regstate_next_int (s->rs);
222 mono_bblock_add_inst (s->cbb, tree);
224 mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE);
227 stmt: OP_SETRET (reg) {
228 tree->opcode = OP_MOVE;
229 tree->sreg1 = state->left->reg1;
230 tree->dreg = MONO_ARCH_RETREG1;
231 mono_bblock_add_inst (s->cbb, tree);
234 stmt: OP_SETRET (freg) {
235 tree->opcode = OP_FMOVE;
236 tree->sreg1 = state->left->reg1;
237 tree->dreg = MONO_ARCH_FRETREG1;
238 mono_bblock_add_inst (s->cbb, tree);
241 # Optimized call instructions
242 reg: OP_LCALL_REG (OP_ICONST),
243 reg: OP_LCALL_REG (OP_I8CONST) {
244 /* FIXME: Move this to inssel-long.brg */
245 tree->opcode = OP_LCALL;
246 ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
247 tree->dreg = state->reg1;
248 mono_bblock_add_inst (s->cbb, tree);
251 stmt: OP_OUTARG_VT (CEE_LDOBJ (base), base) {
252 MonoInst *vt = state->left->left->tree;
253 MonoInst *stack_addr = state->right->tree;
254 int sz = stack_addr->inst_imm;
259 mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0);
262 # This handles trees like outarg_vt (refanytype)
263 stmt: OP_OUTARG_VT (reg, base) {
264 MonoInst *stack_addr = state->right->tree;
266 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1);
269 stmt: OP_START_HANDLER {
270 mono_bblock_add_inst (s->cbb, tree);
273 stmt: CEE_ENDFINALLY {
274 mono_bblock_add_inst (s->cbb, tree);
277 stmt: OP_ENDFILTER (reg) {
278 tree->sreg1 = state->left->reg1;
279 mono_bblock_add_inst (s->cbb, tree);
282 reg: OP_LOCALLOC (reg) {
283 tree->sreg1 = state->left->reg1;
284 tree->dreg = state->reg1;
285 mono_bblock_add_inst (s->cbb, tree);
288 reg: CEE_LDIND_REF (OP_REGVAR),
289 reg: CEE_LDIND_I (OP_REGVAR),
290 reg: CEE_LDIND_I8 (OP_REGVAR),
291 reg: CEE_LDIND_I4 (OP_REGVAR),
292 reg: CEE_LDIND_U4 (OP_REGVAR) "0" {
293 state->reg1 = state->left->tree->dreg;
294 tree->dreg = state->reg1;
297 reg: OP_ATOMIC_ADD_NEW_I4 (base, OP_ICONST),
298 reg: OP_ATOMIC_ADD_NEW_I8 (base, OP_ICONST) {
299 tree->opcode = tree->opcode == OP_ATOMIC_ADD_NEW_I4 ? OP_IA64_FETCHADD4_IMM : OP_IA64_FETCHADD8_IMM;
300 tree->dreg = state->reg1;
301 tree->inst_imm = state->right->tree->inst_imm;
302 tree->inst_basereg = state->left->tree->inst_basereg;
303 tree->inst_offset = state->left->tree->inst_offset;
305 mono_bblock_add_inst (s->cbb, tree);
308 reg: OP_ATOMIC_EXCHANGE_I4 (base, reg),
309 reg: OP_ATOMIC_EXCHANGE_I8 (base, reg) {
310 tree->opcode = tree->opcode;
311 tree->dreg = state->reg1;
312 tree->sreg2 = state->right->reg1;
313 tree->inst_basereg = state->left->tree->inst_basereg;
314 tree->inst_offset = state->left->tree->inst_offset;
316 mono_bblock_add_inst (s->cbb, tree);
319 # Optimized memset implementation
320 stmt: OP_MEMSET (base) "0" {
321 int dest_reg, dest_reg2, val_reg, unit, align;
322 int size = tree->unused;
324 dest_reg = mono_regstate_next_int (s->rs);
326 if (state->left->tree->inst_basereg == s->frame_reg)
327 /* Aligned by mono_allocate_stack_slots */
332 if (tree->inst_imm == 0)
335 val_reg = mono_regstate_next_int (s->rs);
337 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
340 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
342 /* FIXME: Alignment */
343 for (unit = align; unit >= 1; unit = unit >> 1) {
344 dest_reg2 = mono_regstate_next_int (s->rs);
346 /* Use two destination regs to increase paralellism */
347 if (size >= 2 * unit) {
348 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + unit);
350 while (size >= (2 * unit)) {
351 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
352 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg2, 0, val_reg);
357 while (size >= unit) {
358 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
365 # Optimized memcpy implementation
366 stmt: OP_MEMCPY (base, base) "0" {
367 int cur_reg, src_reg, dest_reg, unit;
368 int size = tree->unused;
371 src_reg = mono_regstate_next_int (s->rs);
372 dest_reg = mono_regstate_next_int (s->rs);
374 if ((state->left->tree->inst_basereg == s->frame_reg) &&
375 (state->right->tree->inst_basereg == s->frame_reg))
376 /* Aligned by mono_allocate_stack_slots */
381 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);
382 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, src_reg, state->right->tree->inst_basereg, state->right->tree->inst_offset);
384 /* FIXME: Alignment */
385 for (unit = align; unit >= 1; unit = unit >> 1) {
387 while (size >= unit) {
388 cur_reg = mono_regstate_next_int (s->rs);
389 MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, size_to_ia64_load_u_membase_inc (unit), cur_reg, src_reg, 0);
390 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, cur_reg);
399 size_to_ia64_load_u_membase_inc (int size)
403 return OP_IA64_LOADU1_MEMBASE_INC;
405 return OP_IA64_LOADU2_MEMBASE_INC;
407 return OP_IA64_LOADU4_MEMBASE_INC;
409 return OP_IA64_LOADI8_MEMBASE_INC;
411 g_assert_not_reached ();
417 size_to_ia64_store_membase_inc_reg (int size)
421 return OP_IA64_STOREI1_MEMBASE_INC_REG;
423 return OP_IA64_STOREI2_MEMBASE_INC_REG;
425 return OP_IA64_STOREI4_MEMBASE_INC_REG;
427 return OP_IA64_STOREI8_MEMBASE_INC_REG;
429 g_assert_not_reached ();