2004-04-29 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mono / mini / inssel-ppc.brg
1 %%
2
3 #
4 # inssel-ppc.brg: burg file for special ppc instructions
5 #
6 # Author:
7 #   Dietmar Maurer (dietmar@ximian.com)
8 #   Paolo Molaro (lupus@ximian.com)
9 #
10 # (C) 2002 Ximian, Inc.
11 #
12
13 stmt: OP_START_HANDLER {
14         MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
15         /*MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, spvar->inst_basereg, spvar->inst_offset, ppc_sp);
16         */
17         tree->inst_left = spvar;
18         mono_bblock_add_inst (s->cbb, tree);
19 }
20
21 stmt: CEE_ENDFINALLY {
22         MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
23         tree->inst_left = spvar;
24         mono_bblock_add_inst (s->cbb, tree);
25 }
26
27 stmt: OP_ENDFILTER (reg) {
28         MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region);
29         tree->inst_left = spvar;
30         tree->sreg1 = state->left->reg1;
31         mono_bblock_add_inst (s->cbb, tree);
32 }
33
34 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
35         /* this should only happen for methods returning a long */
36         MONO_EMIT_NEW_UNALU (s, OP_MOVE, ppc_r3, state->right->reg1);
37         MONO_EMIT_NEW_UNALU (s, OP_MOVE, ppc_r4, state->right->reg2);
38 }
39
40 lreg: OP_LNEG (lreg) "2" {
41         MONO_EMIT_NEW_BIALU_IMM (s, OP_PPC_SUBFIC, state->reg1, state->left->reg1, 0);
42         MONO_EMIT_UNALU (s, tree, OP_PPC_SUBFZE, state->reg2, state->left->reg2);
43 }
44
45 freg: OP_LCONV_TO_R8 (lreg) {
46         tree->dreg = state->reg1;
47         tree->sreg1 = state->left->reg1;
48         tree->sreg2 = state->left->reg2;
49         mono_bblock_add_inst (s->cbb, tree);
50 }
51
52 freg: OP_LCONV_TO_R4 (lreg) {
53         tree->dreg = state->reg1;
54         tree->sreg1 = state->left->reg1;
55         tree->sreg2 = state->left->reg2;
56         mono_bblock_add_inst (s->cbb, tree);
57 }
58
59 freg: CEE_CONV_R_UN (reg) {
60         tree->dreg = state->reg1;
61         tree->sreg1 = state->left->reg1;
62         mono_bblock_add_inst (s->cbb, tree);
63 }
64
65 reg: OP_LOCALLOC (OP_ICONST) {
66         /* microcoded in mini-ppc.c */
67         tree->sreg1 = mono_regstate_next_int (s->rs);
68         tree->dreg = state->reg1;
69         MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
70         mono_bblock_add_inst (s->cbb, tree);
71 }
72
73 reg: OP_LOCALLOC (reg) {
74         tree->dreg = state->reg1;
75         tree->sreg1 = state->left->reg1;
76         mono_bblock_add_inst (s->cbb, tree);
77 }
78
79 stmt: OP_SETRET (reg) {
80         tree->opcode = OP_MOVE;
81         tree->sreg1 = state->left->reg1;
82         tree->dreg = ppc_r3;
83         mono_bblock_add_inst (s->cbb, tree);
84 }
85
86 stmt: OP_SETRET (lreg) {
87         tree->opcode = OP_SETLRET;
88         tree->sreg1 = state->left->reg1;
89         tree->sreg2 = state->left->reg2;
90         tree->dreg = ppc_r3;
91         mono_bblock_add_inst (s->cbb, tree);
92 }
93
94 stmt: OP_SETRET (freg) {
95         tree->opcode = OP_FMOVE;
96         tree->sreg1 = state->left->reg1;
97         tree->dreg = ppc_f1;
98         mono_bblock_add_inst (s->cbb, tree);
99 }
100
101 stmt: OP_SETRET (OP_ICONST) {
102         tree->opcode = OP_ICONST;
103         tree->inst_c0 = state->left->tree->inst_c0;
104         tree->dreg = ppc_r3;
105         mono_bblock_add_inst (s->cbb, tree);
106 }
107
108 stmt: OP_OUTARG (reg) {
109         if (tree->inst_imm) {
110                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
111                 return;
112         }
113         tree->opcode = OP_SETREG;
114         tree->dreg = tree->unused;
115         tree->sreg1 = state->left->reg1;
116         mono_bblock_add_inst (s->cbb, tree);
117 }
118
119 stmt: OP_OUTARG (OP_REGVAR) {
120         if (tree->inst_imm) {
121                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->tree->dreg);
122                 return;
123         }
124         tree->opcode = OP_SETREG;
125         tree->dreg = tree->unused;
126         tree->sreg1 = state->left->tree->dreg;
127         mono_bblock_add_inst (s->cbb, tree);
128 }
129
130 stmt: OP_OUTARG (lreg) {
131         if (tree->inst_imm) {
132                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg2);
133                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm + 4, state->left->reg1);
134                 return;
135         }
136         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
137         tree->opcode = OP_SETREG;
138         tree->dreg = tree->unused + 1;
139         tree->sreg1 = state->left->reg1;
140         mono_bblock_add_inst (s->cbb, tree);
141 }
142
143 stmt: OP_OUTARG (OP_ICONST) {
144         if (tree->inst_imm) {
145                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, s->frame_reg, tree->inst_imm, state->left->tree->inst_c0);
146                 return;
147         }
148         tree->opcode = OP_SETREGIMM;
149         tree->dreg = tree->unused;
150         tree->inst_c0 = state->left->tree->inst_c0;
151         mono_bblock_add_inst (s->cbb, tree);
152 }
153
154 #stmt: OP_OUTARG (CEE_LDIND_I4 (base)) {
155 #       tree->opcode = OP_X86_PUSH_MEMBASE;
156 #       tree->inst_basereg = state->left->left->tree->inst_basereg;
157 #       tree->inst_offset = state->left->left->tree->inst_offset;
158 #       mono_bblock_add_inst (s->cbb, tree);
159 #}
160
161 #stmt: OP_OUTARG (CEE_LDIND_U4 (base)) {
162 #       tree->opcode = OP_X86_PUSH_MEMBASE;
163 #       tree->inst_basereg = state->left->left->tree->inst_basereg;
164 #       tree->inst_offset = state->left->left->tree->inst_offset;
165 #       mono_bblock_add_inst (s->cbb, tree);
166 #}
167
168 #stmt: OP_OUTARG (CEE_LDIND_I (base)) {
169 #       tree->opcode = OP_X86_PUSH_MEMBASE;
170 #       tree->inst_basereg = state->left->left->tree->inst_basereg;
171 #       tree->inst_offset = state->left->left->tree->inst_offset;
172 #       mono_bblock_add_inst (s->cbb, tree);
173 #}
174
175 #stmt: OP_OUTARG (CEE_LDIND_REF (base)) {
176 #       tree->opcode = OP_X86_PUSH_MEMBASE;
177 #       tree->inst_basereg = state->left->left->tree->inst_basereg;
178 #       tree->inst_offset = state->left->left->tree->inst_offset;
179 #       mono_bblock_add_inst (s->cbb, tree);
180 #}
181
182 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
183         if (tree->inst_imm) {
184                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->left->tree->dreg);
185                 return;
186         }
187         tree->opcode = OP_SETREG;
188         tree->sreg1 = state->left->left->tree->dreg;
189         tree->dreg = tree->unused;
190         mono_bblock_add_inst (s->cbb, tree);
191 }
192
193 #stmt: OP_OUTARG (CEE_LDOBJ (reg)) {
194 #       tree->opcode = OP_X86_PUSH;
195 #       tree->sreg1 = state->left->reg1;
196 #       mono_bblock_add_inst (s->cbb, tree);
197 #}
198
199 stmt: OP_OUTARG (freg) {
200         if (tree->inst_imm) {
201                 int opcode = (tree->unused & 0xff00) == 0x0400? OP_STORER4_MEMBASE_REG: OP_STORER8_MEMBASE_REG;
202                 MONO_EMIT_NEW_STORE_MEMBASE (s, opcode, s->frame_reg, tree->inst_imm, state->left->reg1);
203                 return;
204         }
205         tree->opcode = OP_SETFREG;
206         tree->sreg1 = state->left->reg1;
207         tree->dreg = tree->unused & 0xff;
208         mono_bblock_add_inst (s->cbb, tree);
209 }
210
211 stmt: OP_OUTARG_R4 (freg) {
212         if (tree->inst_imm) {
213                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
214                 return;
215         }
216         tree->opcode = OP_SETFREG;
217         tree->sreg1 = state->left->reg1;
218         tree->dreg = tree->unused;
219         mono_bblock_add_inst (s->cbb, tree);
220 }
221
222 stmt: OP_OUTARG_R8 (freg) {
223         if (tree->inst_imm) {
224                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
225                 return;
226         }
227         tree->opcode = OP_SETFREG;
228         tree->sreg1 = state->left->reg1;
229         tree->dreg = tree->unused;
230         mono_bblock_add_inst (s->cbb, tree);
231 }
232
233 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
234         MonoInst *vt = state->left->left->tree;
235         int start_reg = tree->unused & 0xff;
236         int nregs = (tree->unused >> 8) & 0xff;
237         int ovf_size = (tree->unused >> 16) & 0xffff;
238         int i, tmpr, soffset;
239         soffset = vt->inst_offset;
240         for (i = 0; i < nregs; ++i) {
241                 tmpr = mono_regstate_next_int (s->rs);
242                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg, soffset);
243                 MONO_EMIT_NEW_UNALU (s, OP_SETREG, start_reg + i, tmpr);
244                 soffset += sizeof (gpointer);
245         }
246         //g_print ("vt size: %d at R%d + %d\n", tree->inst_imm, vt->inst_basereg, vt->inst_offset);
247         if (ovf_size != 0) {
248                 mini_emit_memcpy (s, s->frame_reg, tree->inst_imm + (soffset - vt->inst_offset), vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0);
249         }
250 }
251
252 stmt: OP_OUTARG_VT (OP_ICONST) {
253         int start_reg = tree->unused & 0xff;
254         int nregs = (tree->unused >> 8) & 0xff;
255         if (nregs) {
256                 tree->opcode = OP_SETREGIMM;
257                 tree->dreg = start_reg;
258                 tree->inst_c0 = state->left->tree->inst_c0;
259                 mono_bblock_add_inst (s->cbb, tree);
260         } else {
261                 g_assert_not_reached ();
262         }
263 }
264
265 stmt: OP_OUTARG_VT (reg) {
266         int start_reg = tree->unused & 0xff;
267         int nregs = (tree->unused >> 8) & 0xff;
268         if (nregs) {
269                 tree->opcode = OP_SETREG;
270                 tree->dreg = start_reg;
271                 tree->sreg1 = state->left->tree->dreg;
272                 mono_bblock_add_inst (s->cbb, tree);
273         } else {
274                 g_assert_not_reached ();
275         }
276 }
277
278 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
279         /* nothing to do: the value is already on the FP stack */
280 }
281
282 stmt: CEE_BNE_UN (fpcflags) {
283         tree->opcode = OP_FBNE_UN;
284         mono_bblock_add_inst (s->cbb, tree);
285 }
286
287 stmt: CEE_BEQ (fpcflags) {
288         tree->opcode = OP_FBEQ;
289         mono_bblock_add_inst (s->cbb, tree);
290 }
291
292 stmt: CEE_BLT (fpcflags) {
293         tree->opcode = OP_FBLT;
294         mono_bblock_add_inst (s->cbb, tree);
295 }
296
297 stmt: CEE_BLT_UN (fpcflags) {
298         tree->opcode = OP_FBLT_UN;
299         mono_bblock_add_inst (s->cbb, tree);
300 }
301
302 stmt: CEE_BGT (fpcflags) {
303         tree->opcode = OP_FBGT;
304         mono_bblock_add_inst (s->cbb, tree);
305 }
306
307 stmt: CEE_BGT_UN (fpcflags) {
308         tree->opcode = OP_FBGT_UN;
309         mono_bblock_add_inst (s->cbb, tree);
310 }
311
312 stmt: CEE_BGE  (fpcflags) {
313         tree->opcode = OP_FBGE;
314         mono_bblock_add_inst (s->cbb, tree);
315 }
316
317 stmt: CEE_BGE_UN (fpcflags) {
318         tree->opcode = OP_FBGE_UN;
319         mono_bblock_add_inst (s->cbb, tree);
320 }
321
322 stmt: CEE_BLE  (fpcflags) {
323         tree->opcode = OP_FBLE;
324         mono_bblock_add_inst (s->cbb, tree);
325 }
326
327 stmt: CEE_BLE_UN (fpcflags) {
328         tree->opcode = OP_FBLE_UN;
329         mono_bblock_add_inst (s->cbb, tree);
330 }
331
332 stmt: CEE_POP (freg) "0" {
333         /* nothing to do */
334 }     
335
336 freg: OP_LCONV_TO_R8 (lreg) {
337         /* nothing to do - emulated */
338 }
339
340 freg: OP_LCONV_TO_R4 (lreg) {
341         /* nothing to do - emulated */
342 }
343
344 freg: OP_LCONV_TO_R_UN (lreg) {
345         /* nothing to do - emulated */
346 }
347
348 freg: OP_FREM (freg, freg) {
349         /* nothing to do - emulated */
350 }
351
352 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
353         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
354                          state->left->right->reg1);
355 }
356
357 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
358         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
359                          state->left->right->reg1);
360 }
361
362 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
363         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
364                          state->left->right->reg1);
365 }
366
367 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
368         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
369                          state->left->right->reg1);
370 }
371
372 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
373         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
374                          state->left->right->reg1);
375 }
376
377 reg: CEE_ADD_OVF (reg, reg) "0" {
378         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
379 }
380
381 %%