decc72c06903aede70a08d48e9c93dabb7a43519
[mono.git] / mono / mini / inssel-ia64.brg
1
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);
5
6 %%
7
8 #
9 # inssel-ia64.brg: burg file for special IA64 instructions
10 #
11 # Author:
12 #   Zoltan Varga (vargaz@gmail.com)
13 #
14 # (C) 2002 Ximian, Inc.
15 #
16
17 reg: CEE_LDIND_I8 (OP_REGVAR) {
18         state->reg1 = state->left->tree->dreg;
19 }
20
21 stmt: CEE_STIND_I8 (OP_REGVAR, reg) {
22         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1);
23 }
24
25 reg: CEE_LDIND_I1 (OP_REGVAR) {
26         MONO_EMIT_UNALU (s, tree, OP_SEXT_I1, state->reg1, state->left->tree->dreg);}
27
28 reg: CEE_LDIND_I2 (OP_REGVAR) {
29         MONO_EMIT_UNALU (s, tree, OP_SEXT_I2, state->reg1, state->left->tree->dreg);}
30
31 stmt: CEE_BEQ (fpcflags) {
32         tree->opcode = OP_FBEQ;
33         mono_bblock_add_inst (s->cbb, tree);
34 }
35
36 stmt: CEE_BNE_UN (fpcflags) {
37         tree->opcode = OP_FBNE_UN;
38         mono_bblock_add_inst (s->cbb, tree);
39 }
40
41 stmt: CEE_BLT (fpcflags) {
42         tree->opcode = OP_FBLT;
43         mono_bblock_add_inst (s->cbb, tree);
44 }
45
46 stmt: CEE_BLT_UN (fpcflags) {
47         tree->opcode = OP_FBLT_UN;
48         mono_bblock_add_inst (s->cbb, tree);
49 }
50
51 stmt: CEE_BGT (fpcflags) {
52         tree->opcode = OP_FBGT;
53         mono_bblock_add_inst (s->cbb, tree);
54 }
55
56 stmt: CEE_BGT_UN (fpcflags) {
57         tree->opcode = OP_FBGT_UN;
58         mono_bblock_add_inst (s->cbb, tree);
59 }
60
61 stmt: CEE_BGE  (fpcflags) {
62         tree->opcode = OP_FBGE;
63         mono_bblock_add_inst (s->cbb, tree);
64 }
65
66 stmt: CEE_BGE_UN (fpcflags) {
67         tree->opcode = OP_FBGE_UN;
68         mono_bblock_add_inst (s->cbb, tree);
69 }
70
71 stmt: CEE_BLE  (fpcflags) {
72         tree->opcode = OP_FBLE;
73         mono_bblock_add_inst (s->cbb, tree);
74 }
75
76 stmt: CEE_BLE_UN (fpcflags) {
77         tree->opcode = OP_FBLE_UN;
78         mono_bblock_add_inst (s->cbb, tree);
79 }
80
81 fpcflags: OP_COMPARE (freg, freg) {
82         tree->opcode = OP_FCOMPARE;
83         mono_bblock_add_inst (s->cbb, tree);
84 }
85
86 reg: OP_CEQ (fpcflags) {        
87         tree->dreg = state->reg1;
88         tree->opcode = OP_FCEQ;
89         mono_bblock_add_inst (s->cbb, tree);
90 }
91
92 reg: OP_CLT (fpcflags) {        
93         tree->dreg = state->reg1;
94         tree->opcode = OP_FCLT;
95         mono_bblock_add_inst (s->cbb, tree);
96 }
97
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);
102 }
103
104 reg: OP_CGT (fpcflags) {        
105         tree->dreg = state->reg1;
106         tree->opcode = OP_FCGT;
107         mono_bblock_add_inst (s->cbb, tree);
108 }
109
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);
114 }
115
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);
121 }
122
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);
128 }
129
130 stmt: OP_OUTARG_REG (reg) {     
131         /* FIXME: Move this to inssel.brg */
132         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
133
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);
138
139         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
140 }
141
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;
153         guint32 dreg;
154         MonoInst *base = state->left->left->tree;
155
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);
159
160         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
161 }
162
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;
167
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);
172
173         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
174 }
175
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;
182
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);
187
188         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
189 }
190
191 stmt: OP_OUTARG_FREG (freg) {
192         MonoCallInst *call = (MonoCallInst*)tree->inst_right;
193
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);
198
199         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, TRUE);
200 }
201
202 stmt: OP_OUTARG (reg) {
203         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
204 }
205
206 stmt: OP_OUTARG (freg) {
207         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, IA64_SP, tree->inst_imm, state->left->reg1);
208 }
209
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);
212 }
213
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;
218
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);
224
225         mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE);
226 }
227
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);
233 }
234
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);
240 }
241
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);
250 }
251
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;
256
257         if (!sz)
258                 return;
259
260         mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0);
261 }
262
263 # This handles trees like outarg_vt (refanytype)
264 stmt: OP_OUTARG_VT (reg, base) {
265         MonoInst *stack_addr = state->right->tree;
266
267         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1);
268 }
269
270 stmt: OP_START_HANDLER {
271      mono_bblock_add_inst (s->cbb, tree);
272 }
273
274 stmt: CEE_ENDFINALLY {
275      mono_bblock_add_inst (s->cbb, tree);
276 }
277
278 stmt: OP_ENDFILTER (reg) {
279         tree->sreg1 = state->left->reg1;
280         mono_bblock_add_inst (s->cbb, tree);
281 }
282
283 reg: OP_LOCALLOC (reg) {
284         tree->sreg1 = state->left->reg1;
285         tree->dreg = state->reg1;
286         mono_bblock_add_inst (s->cbb, tree);
287 }
288
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;
296 }
297
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; 
305     
306         mono_bblock_add_inst (s->cbb, tree);
307 } cost {
308         int imm = state->right->tree->inst_imm;
309
310         MBCOND (imm == 1 || imm == 4 || imm == 8 || imm == 16 || imm == -1 || imm == -4 || imm == -8 || imm == -16);
311         return 1;
312 }
313
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; 
323     
324         mono_bblock_add_inst (s->cbb, tree);
325 }
326
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;
331
332         dest_reg = mono_regstate_next_int (s->rs);
333
334         if (state->left->tree->inst_basereg == s->frame_reg)
335                 /* Aligned by mono_allocate_stack_slots */
336                 align = 8;
337         else
338                 align = 4;
339
340         if (tree->inst_imm == 0)
341                 val_reg = IA64_R0;
342         else {
343                 val_reg = mono_regstate_next_int (s->rs);
344
345                 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
346         }
347
348         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset);     
349
350         for (unit = align; unit >= 1; unit = unit >> 1) {
351                 dest_reg2 = mono_regstate_next_int (s->rs);
352
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);
357
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);
361                                 size -= 2 * unit;
362                         }
363
364                         if (size > 0)
365                                 MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, dest_reg, diff);
366                 }
367
368                 while (size >= unit) {
369                         if (size == unit)
370                                 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_store_membase_reg (unit), dest_reg, 0, val_reg);
371                         else
372                                 MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg);
373                         size -= unit;
374                 }
375         }       
376
377 }
378
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;
383         int align;
384
385         src_reg = mono_regstate_next_int (s->rs);
386         dest_reg = mono_regstate_next_int (s->rs);
387
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 */
391                 align = 8;
392         else
393                 align = 4;
394
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);
397
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);
403                         size -= unit;
404                 }
405         }       
406 }
407
408 %%
409
410 int
411 size_to_ia64_load_u_membase_inc (int size)
412 {
413         switch (size) {
414         case 1:
415                 return OP_IA64_LOADU1_MEMBASE_INC;
416         case 2:
417                 return OP_IA64_LOADU2_MEMBASE_INC;
418         case 4:
419                 return OP_IA64_LOADU4_MEMBASE_INC;
420         case 8:
421                 return OP_IA64_LOADI8_MEMBASE_INC;
422         default:
423                 g_assert_not_reached ();
424                 return -1;
425         }
426 }
427
428 int
429 size_to_store_membase_reg (int size)
430 {
431         switch (size) {
432         case 1:
433                 return OP_STOREI1_MEMBASE_REG;
434         case 2:
435                 return OP_STOREI2_MEMBASE_REG;
436         case 4:
437                 return OP_STOREI4_MEMBASE_REG;
438         case 8:
439                 return OP_STOREI8_MEMBASE_REG;
440         default:
441                 g_assert_not_reached ();
442                 return -1;
443         }
444 }
445
446 int
447 size_to_ia64_store_membase_inc_reg (int size)
448 {
449         switch (size) {
450         case 1:
451                 return OP_IA64_STOREI1_MEMBASE_INC_REG;
452         case 2:
453                 return OP_IA64_STOREI2_MEMBASE_INC_REG;
454         case 4:
455                 return OP_IA64_STOREI4_MEMBASE_INC_REG;
456         case 8:
457                 return OP_IA64_STOREI8_MEMBASE_INC_REG;
458         default:
459                 g_assert_not_reached ();
460                 return -1;
461         }
462 }