8f454fe07ba251bfa9c6b40271442ab53ecbed01
[mono.git] / mono / mini / inssel-ia64.brg
1
2 int size_to_ia64_load_u_membase_inc (int size);
3 int size_to_ia64_store_membase_inc_reg (int size);
4
5 %%
6
7 #
8 # inssel-ia64.brg: burg file for special IA64 instructions
9 #
10 # Author:
11 #   Zoltan Varga (vargaz@gmail.com)
12 #
13 # (C) 2002 Ximian, Inc.
14 #
15
16 reg: CEE_LDIND_I8 (OP_REGVAR) {
17         state->reg1 = state->left->tree->dreg;
18 }
19
20 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
21         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
22 }
23
24 reg: CEE_LDIND_I1 (OP_REGVAR) {
25         MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
26
27 reg: CEE_LDIND_I2 (OP_REGVAR) {
28         MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
29
30 stmt: CEE_BEQ (fpcflags) {
31         tree->opcode = OP_FBEQ;
32         mono_bblock_add_inst (s->cbb, tree);
33 }
34
35 stmt: CEE_BNE_UN (fpcflags) {
36         tree->opcode = OP_FBNE_UN;
37         mono_bblock_add_inst (s->cbb, tree);
38 }
39
40 stmt: CEE_BLT (fpcflags) {
41         tree->opcode = OP_FBLT;
42         mono_bblock_add_inst (s->cbb, tree);
43 }
44
45 stmt: CEE_BLT_UN (fpcflags) {
46         tree->opcode = OP_FBLT_UN;
47         mono_bblock_add_inst (s->cbb, tree);
48 }
49
50 stmt: CEE_BGT (fpcflags) {
51         tree->opcode = OP_FBGT;
52         mono_bblock_add_inst (s->cbb, tree);
53 }
54
55 stmt: CEE_BGT_UN (fpcflags) {
56         tree->opcode = OP_FBGT_UN;
57         mono_bblock_add_inst (s->cbb, tree);
58 }
59
60 stmt: CEE_BGE  (fpcflags) {
61         tree->opcode = OP_FBGE;
62         mono_bblock_add_inst (s->cbb, tree);
63 }
64
65 stmt: CEE_BGE_UN (fpcflags) {
66         tree->opcode = OP_FBGE_UN;
67         mono_bblock_add_inst (s->cbb, tree);
68 }
69
70 stmt: CEE_BLE  (fpcflags) {
71         tree->opcode = OP_FBLE;
72         mono_bblock_add_inst (s->cbb, tree);
73 }
74
75 stmt: CEE_BLE_UN (fpcflags) {
76         tree->opcode = OP_FBLE_UN;
77         mono_bblock_add_inst (s->cbb, tree);
78 }
79
80 fpcflags: OP_COMPARE (freg, freg) {
81         tree->opcode = OP_FCOMPARE;
82         mono_bblock_add_inst (s->cbb, tree);
83 }
84
85 reg: OP_CEQ (fpcflags) {        
86         tree->dreg = state->reg1;
87         tree->opcode = OP_FCEQ;
88         mono_bblock_add_inst (s->cbb, tree);
89 }
90
91 reg: OP_CLT (fpcflags) {        
92         tree->dreg = state->reg1;
93         tree->opcode = OP_FCLT;
94         mono_bblock_add_inst (s->cbb, tree);
95 }
96
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);
101 }
102
103 reg: OP_CGT (fpcflags) {        
104         tree->dreg = state->reg1;
105         tree->opcode = OP_FCGT;
106         mono_bblock_add_inst (s->cbb, tree);
107 }
108
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);
113 }
114
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);
120 }
121
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);
127 }
128
129 stmt: OP_OUTARG_REG (reg) {     
130         /* FIXME: Move this to inssel.brg */
131         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
132
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);
137
138         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
139 }
140
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;
152         guint32 dreg;
153         MonoInst *base = state->left->left->tree;
154
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);
158
159         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
160 }
161
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;
166
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);
171
172         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
173 }
174
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;
181
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);
186
187         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
188 }
189
190 stmt: OP_OUTARG_FREG (freg) {
191         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
192
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);
197
198         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, TRUE);
199 }
200
201 stmt: OP_OUTARG (reg) {
202         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
203 }
204
205 stmt: OP_OUTARG (freg) {
206         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
207 }
208
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);
211 }
212
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;
217
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);
223
224         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
225 }
226
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);
232 }
233
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);
239 }
240
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);
249 }
250
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;
255
256         if (!sz)
257                 return;
258
259         mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0);
260 }
261
262 # This handles trees like outarg_vt (refanytype)
263 stmt: OP_OUTARG_VT (reg, base) {
264         MonoInst *stack_addr = state->right->tree;
265
266         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1);
267 }
268
269 stmt: OP_START_HANDLER {
270      mono_bblock_add_inst (s->cbb, tree);
271 }
272
273 stmt: CEE_ENDFINALLY {
274      mono_bblock_add_inst (s->cbb, tree);
275 }
276
277 stmt: OP_ENDFILTER (reg) {
278         tree->sreg1 = state->left->reg1;
279         mono_bblock_add_inst (s->cbb, tree);
280 }
281
282 reg: OP_LOCALLOC (reg) {
283         tree->sreg1 = state->left->reg1;
284         tree->dreg = state->reg1;
285         mono_bblock_add_inst (s->cbb, tree);
286 }
287
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;
295 }
296
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; 
304     
305         mono_bblock_add_inst (s->cbb, tree);
306 }
307
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; 
315     
316         mono_bblock_add_inst (s->cbb, tree);
317 }
318
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;
323
324         dest_reg = mono_regstate_next_int (s->rs);
325
326         if (state->left->tree->inst_basereg == s->frame_reg)
327                 /* Aligned by mono_allocate_stack_slots */
328                 align = 8;
329         else
330                 align = 4;
331
332         if (tree->inst_imm == 0)
333                 val_reg = IA64_R0;
334         else {
335                 val_reg = mono_regstate_next_int (s->rs);
336
337                 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
338         }
339
340         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);     
341
342         /* FIXME: Alignment */
343         for (unit = align; unit >= 1; unit = unit >> 1) {
344                 dest_reg2 = mono_regstate_next_int (s->rs);
345
346                 /* Use two destination regs to increase paralellism */
347                 if (size >= 2 * unit) {
348                         int diff = (size / (2 * unit)) * unit;
349                         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + diff);
350
351                         while (size >= (2 * unit)) {
352                                 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
353                                 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg2, 0, val_reg);
354                                 size -= 2 * unit;
355                         }
356
357                         if (size > 0)
358                                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, dest_reg, diff);
359                 }
360
361                 while (size >= unit) {
362                         MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
363                         size -= unit;
364                 }
365         }       
366
367 }
368
369 # Optimized memcpy implementation
370 stmt: OP_MEMCPY (base, base) "0" {
371         int cur_reg, src_reg, dest_reg, unit;
372         int size = tree->unused;
373         int align;
374
375         src_reg = mono_regstate_next_int (s->rs);
376         dest_reg = mono_regstate_next_int (s->rs);
377
378         if ((state->left->tree->inst_basereg == s->frame_reg) &&
379                 (state->right->tree->inst_basereg == s->frame_reg))
380                 /* Aligned by mono_allocate_stack_slots */
381                 align = 8;
382         else
383                 align = 4;
384
385         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);     
386         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, src_reg, state->right->tree->inst_basereg, state->right->tree->inst_offset);
387
388         /* FIXME: Alignment */
389         for (unit = align; unit >= 1; unit = unit >> 1) {
390
391                 while (size >= unit) {
392                         cur_reg = mono_regstate_next_int (s->rs);
393                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, size_to_ia64_load_u_membase_inc (unit), cur_reg, src_reg, 0);
394                         MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, cur_reg);
395                         size -= unit;
396                 }
397         }       
398 }
399
400 %%
401
402 int
403 size_to_ia64_load_u_membase_inc (int size)
404 {
405         switch (size) {
406         case 1:
407                 return OP_IA64_LOADU1_MEMBASE_INC;
408         case 2:
409                 return OP_IA64_LOADU2_MEMBASE_INC;
410         case 4:
411                 return OP_IA64_LOADU4_MEMBASE_INC;
412         case 8:
413                 return OP_IA64_LOADI8_MEMBASE_INC;
414         default:
415                 g_assert_not_reached ();
416                 return -1;
417         }
418 }
419
420 int
421 size_to_ia64_store_membase_inc_reg (int size)
422 {
423         switch (size) {
424         case 1:
425                 return OP_IA64_STOREI1_MEMBASE_INC_REG;
426         case 2:
427                 return OP_IA64_STOREI2_MEMBASE_INC_REG;
428         case 4:
429                 return OP_IA64_STOREI4_MEMBASE_INC_REG;
430         case 8:
431                 return OP_IA64_STOREI8_MEMBASE_INC_REG;
432         default:
433                 g_assert_not_reached ();
434                 return -1;
435         }
436 }