2ddcafe01962b64d18344af52a9575e62e3861f8
[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 lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" {
35         /* SBB sets the condition code */
36         MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
37         MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2);
38         /* FIXME: This is wrong on ppc, see also compilation of tests/exception6.cs
39         MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");*/
40 }
41 stmt: CEE_STIND_I8 (OP_REGVAR, lreg) {
42         /* this should only happen for methods returning a long */
43         MONO_EMIT_NEW_UNALU (s, OP_MOVE, ppc_r3, state->right->reg1);
44         MONO_EMIT_NEW_UNALU (s, OP_MOVE, ppc_r4, state->right->reg2);
45 }
46
47 lreg: OP_LNEG (lreg) "2" {
48         MONO_EMIT_NEW_BIALU_IMM (s, OP_PPC_SUBFIC, state->reg1, state->left->reg1, 0);
49         MONO_EMIT_UNALU (s, tree, OP_PPC_SUBFZE, state->reg2, state->left->reg2);
50 }
51
52 freg: OP_LCONV_TO_R8 (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: OP_LCONV_TO_R4 (lreg) {
60         tree->dreg = state->reg1;
61         tree->sreg1 = state->left->reg1;
62         tree->sreg2 = state->left->reg2;
63         mono_bblock_add_inst (s->cbb, tree);
64 }
65
66 freg: CEE_CONV_R_UN (reg) {
67         tree->dreg = state->reg1;
68         tree->sreg1 = state->left->reg1;
69         mono_bblock_add_inst (s->cbb, tree);
70 }
71
72 reg: OP_LOCALLOC (OP_ICONST) {
73         /* microcoded in mini-ppc.c */
74         tree->sreg1 = mono_regstate_next_int (s->rs);
75         tree->dreg = state->reg1;
76         MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
77         mono_bblock_add_inst (s->cbb, tree);
78 }
79
80 reg: OP_LOCALLOC (reg) {
81         tree->dreg = state->reg1;
82         tree->sreg1 = state->left->reg1;
83         mono_bblock_add_inst (s->cbb, tree);
84 }
85
86 stmt: OP_SETRET (reg) {
87         tree->opcode = OP_MOVE;
88         tree->sreg1 = state->left->reg1;
89         tree->dreg = ppc_r3;
90         mono_bblock_add_inst (s->cbb, tree);
91 }
92
93 stmt: OP_SETRET (lreg) {
94         tree->opcode = OP_SETLRET;
95         tree->sreg1 = state->left->reg1;
96         tree->sreg2 = state->left->reg2;
97         tree->dreg = ppc_r3;
98         mono_bblock_add_inst (s->cbb, tree);
99 }
100
101 stmt: OP_SETRET (freg) {
102         tree->opcode = OP_FMOVE;
103         tree->sreg1 = state->left->reg1;
104         tree->dreg = ppc_f1;
105         mono_bblock_add_inst (s->cbb, tree);
106 }
107
108 stmt: OP_SETRET (OP_ICONST) {
109         tree->opcode = OP_ICONST;
110         tree->inst_c0 = state->left->tree->inst_c0;
111         tree->dreg = ppc_r3;
112         mono_bblock_add_inst (s->cbb, tree);
113 }
114
115 stmt: OP_OUTARG (reg) {
116         if (tree->inst_imm) {
117                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
118                 return;
119         }
120         tree->opcode = OP_SETREG;
121         tree->dreg = tree->unused;
122         tree->sreg1 = state->left->reg1;
123         mono_bblock_add_inst (s->cbb, tree);
124 }
125
126 stmt: OP_OUTARG (OP_REGVAR) {
127         if (tree->inst_imm) {
128                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->tree->dreg);
129                 return;
130         }
131         tree->opcode = OP_SETREG;
132         tree->dreg = tree->unused;
133         tree->sreg1 = state->left->tree->dreg;
134         mono_bblock_add_inst (s->cbb, tree);
135 }
136
137 stmt: OP_OUTARG (lreg) {
138         if (tree->inst_imm) {
139                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg2);
140                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm + 4, state->left->reg1);
141                 return;
142         }
143         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
144         tree->opcode = OP_SETREG;
145         tree->dreg = tree->unused + 1;
146         tree->sreg1 = state->left->reg1;
147         mono_bblock_add_inst (s->cbb, tree);
148 }
149
150 stmt: OP_OUTARG (OP_ICONST) {
151         if (tree->inst_imm) {
152                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, s->frame_reg, tree->inst_imm, state->left->tree->inst_c0);
153                 return;
154         }
155         tree->opcode = OP_SETREGIMM;
156         tree->dreg = tree->unused;
157         tree->inst_c0 = state->left->tree->inst_c0;
158         mono_bblock_add_inst (s->cbb, tree);
159 }
160
161 #stmt: OP_OUTARG (CEE_LDIND_I4 (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_U4 (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_I (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 (base)) {
183 #       tree->opcode = OP_X86_PUSH_MEMBASE;
184 #       tree->inst_basereg = state->left->left->tree->inst_basereg;
185 #       tree->inst_offset = state->left->left->tree->inst_offset;
186 #       mono_bblock_add_inst (s->cbb, tree);
187 #}
188
189 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
190         if (tree->inst_imm) {
191                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->left->tree->dreg);
192                 return;
193         }
194         tree->opcode = OP_SETREG;
195         tree->sreg1 = state->left->left->tree->dreg;
196         tree->dreg = tree->unused;
197         mono_bblock_add_inst (s->cbb, tree);
198 }
199
200 #stmt: OP_OUTARG (CEE_LDOBJ (reg)) {
201 #       tree->opcode = OP_X86_PUSH;
202 #       tree->sreg1 = state->left->reg1;
203 #       mono_bblock_add_inst (s->cbb, tree);
204 #}
205
206 stmt: OP_OUTARG (freg) {
207         if (tree->inst_imm) {
208                 int opcode = (tree->unused & 0xff00) == 0x0400? OP_STORER4_MEMBASE_REG: OP_STORER8_MEMBASE_REG;
209                 MONO_EMIT_NEW_STORE_MEMBASE (s, opcode, s->frame_reg, tree->inst_imm, state->left->reg1);
210                 return;
211         }
212         tree->opcode = OP_SETFREG;
213         tree->sreg1 = state->left->reg1;
214         tree->dreg = tree->unused & 0xff;
215         mono_bblock_add_inst (s->cbb, tree);
216 }
217
218 stmt: OP_OUTARG_R4 (freg) {
219         if (tree->inst_imm) {
220                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
221                 return;
222         }
223         tree->opcode = OP_SETFREG;
224         tree->sreg1 = state->left->reg1;
225         tree->dreg = tree->unused;
226         mono_bblock_add_inst (s->cbb, tree);
227 }
228
229 stmt: OP_OUTARG_R8 (freg) {
230         if (tree->inst_imm) {
231                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, s->frame_reg, tree->inst_imm, state->left->reg1);
232                 return;
233         }
234         tree->opcode = OP_SETFREG;
235         tree->sreg1 = state->left->reg1;
236         tree->dreg = tree->unused;
237         mono_bblock_add_inst (s->cbb, tree);
238 }
239
240 stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) {
241         MonoInst *vt = state->left->left->tree;
242         int start_reg = tree->unused & 0xff;
243         int nregs = (tree->unused >> 8) & 0xff;
244         int ovf_size = (tree->unused >> 16) & 0xffff;
245         int i, tmpr, soffset;
246         soffset = vt->inst_offset;
247         for (i = 0; i < nregs; ++i) {
248                 tmpr = mono_regstate_next_int (s->rs);
249                 MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg, soffset);
250                 MONO_EMIT_NEW_UNALU (s, OP_SETREG, start_reg + i, tmpr);
251                 soffset += sizeof (gpointer);
252         }
253         //g_print ("vt size: %d at R%d + %d\n", tree->inst_imm, vt->inst_basereg, vt->inst_offset);
254         if (ovf_size != 0) {
255                 mini_emit_memcpy (s, s->frame_reg, tree->inst_imm + (soffset - vt->inst_offset), vt->inst_basereg, soffset, ovf_size * sizeof (gpointer), 0);
256         }
257 }
258
259 stmt: OP_OUTARG_VT (OP_ICONST) {
260         int start_reg = tree->unused & 0xff;
261         int nregs = (tree->unused >> 8) & 0xff;
262         if (nregs) {
263                 tree->opcode = OP_SETREGIMM;
264                 tree->dreg = start_reg;
265                 tree->inst_c0 = state->left->tree->inst_c0;
266                 mono_bblock_add_inst (s->cbb, tree);
267         } else {
268                 g_assert_not_reached ();
269         }
270 }
271
272 stmt: OP_OUTARG_VT (reg) {
273         int start_reg = tree->unused & 0xff;
274         int nregs = (tree->unused >> 8) & 0xff;
275         if (nregs) {
276                 tree->opcode = OP_SETREG;
277                 tree->dreg = start_reg;
278                 tree->sreg1 = state->left->tree->dreg;
279                 mono_bblock_add_inst (s->cbb, tree);
280         } else {
281                 g_assert_not_reached ();
282         }
283 }
284
285 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
286         /* nothing to do: the value is already on the FP stack */
287 }
288
289 stmt: CEE_BNE_UN (fpcflags) {
290         tree->opcode = OP_FBNE_UN;
291         mono_bblock_add_inst (s->cbb, tree);
292 }
293
294 stmt: CEE_BEQ (fpcflags) {
295         tree->opcode = OP_FBEQ;
296         mono_bblock_add_inst (s->cbb, tree);
297 }
298
299 stmt: CEE_BLT (fpcflags) {
300         tree->opcode = OP_FBLT;
301         mono_bblock_add_inst (s->cbb, tree);
302 }
303
304 stmt: CEE_BLT_UN (fpcflags) {
305         tree->opcode = OP_FBLT_UN;
306         mono_bblock_add_inst (s->cbb, tree);
307 }
308
309 stmt: CEE_BGT (fpcflags) {
310         tree->opcode = OP_FBGT;
311         mono_bblock_add_inst (s->cbb, tree);
312 }
313
314 stmt: CEE_BGT_UN (fpcflags) {
315         tree->opcode = OP_FBGT_UN;
316         mono_bblock_add_inst (s->cbb, tree);
317 }
318
319 stmt: CEE_BGE  (fpcflags) {
320         tree->opcode = OP_FBGE;
321         mono_bblock_add_inst (s->cbb, tree);
322 }
323
324 stmt: CEE_BGE_UN (fpcflags) {
325         tree->opcode = OP_FBGE_UN;
326         mono_bblock_add_inst (s->cbb, tree);
327 }
328
329 stmt: CEE_BLE  (fpcflags) {
330         tree->opcode = OP_FBLE;
331         mono_bblock_add_inst (s->cbb, tree);
332 }
333
334 stmt: CEE_BLE_UN (fpcflags) {
335         tree->opcode = OP_FBLE_UN;
336         mono_bblock_add_inst (s->cbb, tree);
337 }
338
339 stmt: CEE_POP (freg) "0" {
340         /* nothing to do */
341 }     
342
343 freg: OP_LCONV_TO_R8 (lreg) {
344         /* nothing to do - emulated */
345 }
346
347 freg: OP_LCONV_TO_R4 (lreg) {
348         /* nothing to do - emulated */
349 }
350
351 freg: OP_LCONV_TO_R_UN (lreg) {
352         /* nothing to do - emulated */
353 }
354
355 freg: OP_FREM (freg, freg) {
356         /* nothing to do - emulated */
357 }
358
359 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
360         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
361                          state->left->right->reg1);
362 }
363
364 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
365         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
366                          state->left->right->reg1);
367 }
368
369 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
370         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
371                          state->left->right->reg1);
372 }
373
374 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
375         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
376                          state->left->right->reg1);
377 }
378
379 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
380         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
381                          state->left->right->reg1);
382 }
383
384 reg: CEE_ADD_OVF (reg, reg) "0" {
385         MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
386 }
387
388 %%