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