2004-02-15 Miguel de Icaza <miguel@ximian.com>
[mono.git] / mono / mini / inssel-sparc.brg
1 %%
2
3 #
4 # inssel-sparc.brg: burg file for special sparc 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: CEE_STIND_I8 (OP_REGVAR, lreg) {
14         /* this should only happen for methods returning a long */
15         MONO_EMIT_NEW_UNALU (s, OP_MOVE, sparc_o0, state->right->reg2);
16         MONO_EMIT_NEW_UNALU (s, OP_MOVE, sparc_o1, state->right->reg1);
17 }
18
19 lreg: CEE_LDIND_I8 (OP_REGVAR) {
20         /* reg2 contains the most significant word */
21         MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, state->left->tree->dreg);
22         tree->opcode = OP_SETREG;
23         tree->dreg = state->reg1;
24         tree->sreg1 = state->left->tree->dreg + 1;
25         mono_bblock_add_inst (s->cbb, tree);
26 }
27
28 freg: OP_LCONV_TO_R8 (lreg) {
29         mono_bblock_add_inst (s->cbb, tree);
30 }
31
32 freg: OP_LCONV_TO_R4 (lreg) {
33         mono_bblock_add_inst (s->cbb, tree);
34 }
35
36 freg: CEE_CONV_R_UN (reg) {
37         mono_bblock_add_inst (s->cbb, tree);
38 }
39
40 reg: OP_LOCALLOC (OP_ICONST) {
41         /* microcoded in mini-sparc.c */
42         tree->sreg1 = mono_regstate_next_int (s->rs);
43         MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0);
44         mono_bblock_add_inst (s->cbb, tree);
45 }
46
47 reg: OP_LOCALLOC (reg) {
48         mono_bblock_add_inst (s->cbb, tree);
49 }
50
51 base: OP_SPARC_INARG_VT (base) {
52         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->tree->inst_basereg, 
53                                         state->left->tree->inst_offset);
54 }
55
56 reg: OP_LDADDR (OP_SPARC_INARG_VT (base)) {
57         MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->left->tree->inst_basereg, 
58                                         state->left->left->tree->inst_offset);
59 }
60
61 base: OP_LDADDR (reg) {
62 /*
63         tree->inst_basereg = mono_regstate_next_int (s->rs);
64         tree->inst_offset = 0;
65
66         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->inst_basereg, state->left->tree->dreg, 0);
67 */
68         tree->inst_basereg = state->left->tree->dreg;
69         tree->inst_offset = 0;
70 }
71
72 stmt: OP_OUTARG (OP_LDADDR (reg)) {
73         tree->opcode = OP_SETREG;
74         tree->dreg = tree->unused;
75         tree->sreg1 = state->left->left->tree->dreg;
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 = sparc_i0;
83         mono_bblock_add_inst (s->cbb, tree);
84 }
85
86 stmt: OP_SETRET (lreg) {
87         MONO_EMIT_NEW_UNALU (s, OP_MOVE, sparc_i0, state->left->reg2);
88         tree->opcode = OP_MOVE;
89         tree->sreg1 = state->left->reg1;
90         tree->dreg = sparc_i1;
91         mono_bblock_add_inst (s->cbb, tree);
92 }
93
94 stmt: OP_SETRET (freg) {
95         MONO_EMIT_UNALU (s, tree, OP_FMOVE, sparc_f0, state->left->reg1);
96         mono_bblock_add_inst (s->cbb, tree);
97 }
98
99 stmt: OP_SETRET (OP_ICONST) {
100         tree->opcode = OP_ICONST;
101         tree->inst_c0 = state->left->tree->inst_c0;
102         tree->dreg = sparc_i0;
103         mono_bblock_add_inst (s->cbb, tree);
104 }
105
106 stmt: OP_OUTARG (reg) {
107         tree->opcode = OP_SETREG;
108         tree->dreg = tree->unused;
109         tree->sreg1 = state->left->reg1;
110         mono_bblock_add_inst (s->cbb, tree);
111 }
112
113 stmt: OP_OUTARG (OP_REGVAR) {
114         tree->opcode = OP_SETREG;
115         tree->dreg = tree->unused;
116         tree->sreg1 = state->left->tree->dreg;
117         mono_bblock_add_inst (s->cbb, tree);
118 }
119
120 stmt: OP_OUTARG (freg) {
121         /* floating-point <-> integer transfer must go through memory */
122         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_basereg,
123                                                                 tree->inst_imm, state->left->reg1);
124         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm);
125 }
126
127 stmt: OP_OUTARG (OP_ICONST) {
128         tree->opcode = OP_SETREGIMM;
129         tree->dreg = tree->unused;
130         tree->inst_c0 = state->left->tree->inst_c0;
131         mono_bblock_add_inst (s->cbb, tree);
132 }
133
134 stmt: OP_OUTARG (CEE_LDIND_R4 (base)) {
135         tree->opcode = OP_LOADI4_MEMBASE;
136         tree->dreg = tree->unused;
137         tree->inst_basereg = state->left->left->tree->inst_basereg;
138         tree->inst_offset = state->left->left->tree->inst_offset;
139         mono_bblock_add_inst (s->cbb, tree);
140 }
141
142 stmt: OP_SPARC_OUTARG_REGPAIR (lreg) {
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_SPARC_OUTARG_REGPAIR (freg) {
151         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg,
152                                                                 tree->inst_imm, state->left->reg1);
153         /* floating-point <-> integer transfer must go through memory */
154         /* Load into a register pair */
155         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm);
156         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused + 1, tree->inst_basereg, tree->inst_imm + 4);
157 }
158
159 stmt: OP_SPARC_OUTARG_MEM (reg) {
160         if (tree->inst_imm & 0x1)
161                 tree->opcode = OP_STOREI1_MEMBASE_REG;
162         else if (tree->inst_imm & 0x2)
163                 tree->opcode = OP_STOREI2_MEMBASE_REG;
164         else
165                 tree->opcode = OP_STOREI4_MEMBASE_REG;
166         tree->inst_destbasereg = tree->inst_basereg;
167         tree->inst_offset = tree->inst_imm;
168         tree->sreg1 = state->left->reg1;
169         mono_bblock_add_inst (s->cbb, tree);
170 }
171
172 stmt: OP_SPARC_OUTARG_MEM (freg) {
173         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, tree->inst_basereg,
174                                                                 tree->inst_imm, state->left->reg1);
175 }
176
177 stmt: OP_SPARC_OUTARG_MEMPAIR (lreg) {
178         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, tree->inst_basereg,
179                                                                 tree->inst_imm, state->left->reg2);
180         tree->opcode = OP_STOREI4_MEMBASE_REG;
181         tree->inst_destbasereg = tree->inst_basereg;
182         tree->inst_offset = tree->inst_imm + 4;
183         tree->sreg1 = state->left->reg1;
184         mono_bblock_add_inst (s->cbb, tree);
185 }
186
187 stmt: OP_SPARC_OUTARG_MEMPAIR (freg) {
188         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg,
189                                                                 tree->inst_imm, state->left->reg1);
190 }
191
192 stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (lreg) {
193         MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2);
194         tree->opcode = OP_STOREI4_MEMBASE_REG;
195         tree->inst_destbasereg = tree->inst_basereg;
196         tree->inst_offset = tree->inst_imm + 4;
197         tree->sreg1 = state->left->reg1;
198         mono_bblock_add_inst (s->cbb, tree);
199 }
200
201 stmt: OP_SPARC_OUTARG_SPLIT_REG_STACK (freg) {
202         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, tree->inst_basereg,
203                                                                 tree->inst_imm, state->left->reg1);
204         /* floating-point <-> integer transfer must go through memory */
205         /* Load most significant word into register */
206         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, tree->inst_basereg, tree->inst_imm);
207 }
208
209 # Handles scalar valuetypes like RuntimeTypeHandle
210 reg: OP_OUTARG_VT (OP_ICONST) {
211         int size = tree->unused;
212         MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, sparc_sp, tree->inst_c1, state->left->tree->inst_c0);
213         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
214 }
215
216 reg: OP_OUTARG_VT (base) {
217         int size = tree->unused;
218         mini_emit_memcpy (s, sparc_sp, tree->inst_c1, state->left->tree->inst_basereg, state->left->tree->inst_offset, size, 0);
219         MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, sparc_sp, tree->inst_c1);
220 }
221
222 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) {
223         tree->opcode = OP_SETREG;
224         tree->sreg1 = state->left->left->tree->dreg;
225         tree->dreg = tree->unused;
226         mono_bblock_add_inst (s->cbb, tree);
227 }
228
229 stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGOFFSET)) {
230         MONO_EMIT_NEW_LOAD_MEMBASE (s, tree->unused, state->left->left->tree->inst_basereg, 
231                                                                 state->left->left->tree->inst_offset);
232 }
233
234 stmt: OP_OUTARG_VT (OP_ICONST) {
235         tree->opcode = OP_SETREGIMM;
236         tree->dreg = tree->unused;
237         tree->inst_imm = state->left->tree->inst_c0;
238         mono_bblock_add_inst (s->cbb, tree);
239 }
240
241 stmt: CEE_STIND_R8 (OP_REGVAR, freg) {
242         /* nothing to do: the value is already on the FP stack */
243 }
244
245 reg: CEE_LDIND_I2 (OP_REGVAR) {
246         /* All regs are 32 bit */
247         tree->opcode = OP_MOVE;
248         tree->sreg1 = state->left->tree->dreg;
249         tree->dreg = state->reg1;
250         mono_bblock_add_inst (s->cbb, tree);
251 }
252
253 stmt: CEE_BNE_UN (fpcflags) {
254         tree->opcode = OP_FBNE_UN;
255         mono_bblock_add_inst (s->cbb, tree);
256 }
257
258 stmt: CEE_BEQ (fpcflags) {
259         tree->opcode = OP_FBEQ;
260         mono_bblock_add_inst (s->cbb, tree);
261 }
262
263 stmt: CEE_BLT (fpcflags) {
264         tree->opcode = OP_FBLT;
265         mono_bblock_add_inst (s->cbb, tree);
266 }
267
268 stmt: CEE_BLT_UN (fpcflags) {
269         tree->opcode = OP_FBLT_UN;
270         mono_bblock_add_inst (s->cbb, tree);
271 }
272
273 stmt: CEE_BGT (fpcflags) {
274         tree->opcode = OP_FBGT;
275         mono_bblock_add_inst (s->cbb, tree);
276 }
277
278 stmt: CEE_BGT_UN (fpcflags) {
279         tree->opcode = OP_FBGT_UN;
280         mono_bblock_add_inst (s->cbb, tree);
281 }
282
283 stmt: CEE_BGE  (fpcflags) {
284         tree->opcode = OP_FBGE;
285         mono_bblock_add_inst (s->cbb, tree);
286 }
287
288 stmt: CEE_BGE_UN (fpcflags) {
289         tree->opcode = OP_FBGE_UN;
290         mono_bblock_add_inst (s->cbb, tree);
291 }
292
293 stmt: CEE_BLE  (fpcflags) {
294         tree->opcode = OP_FBLE;
295         mono_bblock_add_inst (s->cbb, tree);
296 }
297
298 stmt: CEE_BLE_UN (fpcflags) {
299         tree->opcode = OP_FBLE_UN;
300         mono_bblock_add_inst (s->cbb, tree);
301 }
302
303 stmt: CEE_POP (freg) "0" {
304         /* nothing to do */
305 }     
306
307 stmt: OP_START_HANDLER {
308 }
309
310 stmt: CEE_ENDFINALLY {
311 }
312
313 stmt: OP_ENDFILTER (reg) {
314 }
315
316 reg: OP_CEQ (OP_COMPARE (freg, freg)) { 
317         MONO_EMIT_BIALU (s, tree, OP_FCEQ, state->reg1, state->left->left->reg1,
318                          state->left->right->reg1);
319 }
320
321 reg: OP_CLT (OP_COMPARE (freg, freg)) { 
322         MONO_EMIT_BIALU (s, tree, OP_FCLT, state->reg1, state->left->left->reg1,
323                          state->left->right->reg1);
324 }
325
326 reg: OP_CLT_UN (OP_COMPARE (freg, freg)) {      
327         MONO_EMIT_BIALU (s, tree, OP_FCLT_UN, state->reg1, state->left->left->reg1,
328                          state->left->right->reg1);
329 }
330
331 reg: OP_CGT (OP_COMPARE (freg, freg)) { 
332         MONO_EMIT_BIALU (s, tree, OP_FCGT, state->reg1, state->left->left->reg1,
333                          state->left->right->reg1);
334 }
335
336 reg: OP_CGT_UN (OP_COMPARE (freg, freg)) {      
337         MONO_EMIT_BIALU (s, tree, OP_FCGT_UN, state->reg1, state->left->left->reg1,
338                          state->left->right->reg1);
339 }
340
341 #
342 # Optimizations
343 #
344
345 stmt: OP_SETRET (CEE_LDIND_REF(base)) {
346         MONO_EMIT_LOAD_MEMBASE (s, tree, sparc_i0, state->left->left->tree->inst_basereg, 
347                                 state->left->left->tree->inst_offset);  
348         mono_bblock_add_inst (s->cbb, tree);
349 }
350
351 stmt: OP_SETRET (CEE_LDIND_I4(base)) {
352         MONO_EMIT_LOAD_MEMBASE (s, tree, sparc_i0, state->left->left->tree->inst_basereg, 
353                                 state->left->left->tree->inst_offset);  
354         mono_bblock_add_inst (s->cbb, tree);
355 }
356
357 stmt: OP_SETRET (CEE_LDIND_I(base)) {
358         MONO_EMIT_LOAD_MEMBASE (s, tree, sparc_i0, state->left->left->tree->inst_basereg, 
359                                 state->left->left->tree->inst_offset);  
360         mono_bblock_add_inst (s->cbb, tree);
361 }
362
363 stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) {
364         tree->opcode = OP_SETREG;
365         tree->dreg = tree->unused;
366         tree->sreg1 = state->left->left->tree->dreg;
367         mono_bblock_add_inst (s->cbb, tree);
368 }
369
370 stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) {
371         tree->opcode = OP_SETREG;
372         tree->dreg = tree->unused;
373         tree->sreg1 = state->left->left->tree->dreg;
374         mono_bblock_add_inst (s->cbb, tree);
375 }
376
377 reg: OP_LDADDR (OP_REGOFFSET) "1" {
378         if (state->left->tree->inst_offset) {
379                 MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset);
380         } else {
381                 tree->opcode = OP_MOVE;
382                 tree->sreg1 = state->left->tree->inst_basereg;
383                 tree->dreg = state->reg1;
384         }
385         mono_bblock_add_inst (s->cbb, tree);
386 }
387
388 stmt: OP_MEMSET (reg) "0" {
389         int size = tree->unused;
390         int offset = 0;
391         int destreg = state->left->reg1;
392         int val_reg;
393
394         if (tree->inst_imm) {
395                 val_reg = mono_regstate_next_int (s->rs);
396                 MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm);
397         }
398         else
399                 val_reg = sparc_g0;
400
401         if ((tree->inst_imm == 0) && (size >= 8)) {
402                 MONO_EMIT_NEW_ICONST (s, sparc_g1, 0);
403
404                 while (size >= 8) {
405                         MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
406                         offset += 8;
407                         size -= 8;
408                 }
409         }
410                 
411         while (size >= 4) {
412                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
413                 offset += 4;
414                 size -= 4;
415         }
416         while (size >= 2) {
417                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
418                 offset += 2;
419                 size -= 2;
420         }
421         while (size >= 1) {
422                 MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
423                 offset += 1;
424                 size -= 1;
425         }
426 }
427
428 %%