* src/vm/jit/sparc64/emit.c: Implemented trace enter/exit functions.
[cacao.git] / src / vm / jit / sparc64 / emit.c
1 /* src/vm/jit/sparc64/emit.c - Sparc code emitter functions
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Christian Thalinger
28             Alexander Jordan
29
30    Changes: 
31
32    $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
33
34 */
35
36 #include "vm/types.h"
37
38 #include "md-abi.h"
39
40 #include "vm/jit/sparc64/codegen.h"
41
42 #include "vm/exceptions.h"
43 #include "vm/stringlocal.h" /* XXX for gen_resolvebranch */
44 #include "vm/jit/abi-asm.h"
45 #include "vm/jit/asmpart.h"
46 #include "vm/jit/dseg.h"
47 #include "vm/jit/emit-common.h"
48 #include "vm/jit/jit.h"
49 #include "vm/jit/replace.h"
50
51
52 /* emit_load *******************************************************************
53
54    Emits a possible load of an operand.
55
56 *******************************************************************************/
57
58 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
59 {
60         codegendata  *cd;
61         s4            disp;
62         s4            reg;
63
64         /* get required compiler data */
65
66         cd = jd->cd;
67
68         if (src->flags & INMEMORY) {
69                 COUNT_SPILLS;
70
71                 disp = src->vv.regoff * 8;
72
73                 if (IS_FLT_DBL_TYPE(src->type))
74                         M_DLD(tempreg, REG_SP, disp);
75                 else
76                         M_LDX(tempreg, REG_SP, disp);
77
78                 reg = tempreg;
79         }
80         else
81                 reg = src->vv.regoff;
82
83         return reg;
84 }
85
86
87 /* emit_store ******************************************************************
88
89    Emits a possible store to variable.
90
91 *******************************************************************************/
92
93 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
94 {
95         codegendata  *cd;
96         s4            disp;
97
98         /* get required compiler data */
99
100         cd = jd->cd;
101
102         if (dst->flags & INMEMORY) {
103                 COUNT_SPILLS;
104
105                 disp = dst->vv.regoff * 8;
106
107                 if (IS_FLT_DBL_TYPE(dst->type))
108                         M_DST(d, REG_SP, disp);
109                 else
110                         M_STX(d, REG_SP, disp);
111         }
112 }
113
114
115 /* emit_copy *******************************************************************
116
117    Generates a register/memory to register/memory copy.
118
119 *******************************************************************************/
120
121 void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
122 {
123         codegendata  *cd;
124         registerdata *rd;
125         s4            s1, d;
126
127         /* get required compiler data */
128
129         cd = jd->cd;
130         rd = jd->rd;
131
132         if ((src->vv.regoff != dst->vv.regoff) ||
133                 ((src->flags ^ dst->flags) & INMEMORY)) {
134
135                 /* If one of the variables resides in memory, we can eliminate
136                    the register move from/to the temporary register with the
137                    order of getting the destination register and the load. */
138
139                 if (IS_INMEMORY(src->flags)) {
140                         d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
141                         s1 = emit_load(jd, iptr, src, d);
142                 }
143                 else {
144                         s1 = emit_load(jd, iptr, src, REG_IFTMP);
145                         d = codegen_reg_of_var(iptr->opc, dst, s1);
146                 }
147
148                 if (s1 != d) {
149                         if (IS_FLT_DBL_TYPE(src->type))
150                                 M_FMOV(s1, d);
151                 else
152                                 M_MOV(s1, d);
153                 }
154
155                 emit_store(jd, iptr, dst, d);
156         }
157 }
158
159
160 /* emit_iconst *****************************************************************
161
162    XXX
163
164 *******************************************************************************/
165
166 void emit_iconst(codegendata *cd, s4 d, s4 value)
167 {
168         s4 disp;
169
170         if ((value >= -4096) && (value <= 4095)) {
171                 M_XOR(REG_ZERO, value, d);
172         } else {
173                 disp = dseg_adds4(cd, value);
174                 M_ILD(d, REG_PV_CALLEE, disp);
175         }
176 }
177
178
179 /* emit_lconst *****************************************************************
180
181    XXX
182
183 *******************************************************************************/
184
185 void emit_lconst(codegendata *cd, s4 d, s8 value)
186 {
187         s4 disp;
188
189         if ((value >= -4096) && (value <= 4095)) {
190                 M_XOR(REG_ZERO, value, d);      
191         } else {
192                 disp = dseg_adds8(cd, value);
193                 M_LDX(d, REG_PV_CALLEE, disp);
194         }
195 }
196
197
198 /* emit_exception_stubs ********************************************************
199
200    Generates the code for the exception stubs.
201
202 *******************************************************************************/
203
204 void emit_exception_stubs(jitdata *jd)
205 {
206 }
207
208 /* emit_patcher_stubs **********************************************************
209
210    Generates the code for the patcher stubs.
211
212 *******************************************************************************/
213
214 void emit_patcher_stubs(jitdata *jd)
215 {
216 }
217
218 /* emit_replacement_stubs ******************************************************
219
220    Generates the code for the replacement stubs.
221
222 *******************************************************************************/
223
224 void emit_replacement_stubs(jitdata *jd)
225 {
226 }
227
228 /* emit_verbosecall_enter ******************************************************
229
230    Generates the code for the call trace.
231
232 *******************************************************************************/
233
234 #if !defined(NDEBUG)
235 void emit_verbosecall_enter(jitdata *jd)
236 {
237         methodinfo   *m;
238         codegendata  *cd;
239         registerdata *rd;
240         methoddesc   *md;
241         s4            disp;
242         s4            i, t;
243
244         /* get required compiler data */
245
246         m  = jd->m;
247         cd = jd->cd;
248         rd = jd->rd;
249
250         md = m->parseddesc;
251
252         /* mark trace code */
253
254         M_NOP;
255
256         M_LDA(REG_SP, REG_SP, -(1 + WINSAVE_CNT + FLT_ARG_CNT) * 8);
257
258         /* save float argument registers */
259
260         for (i = 0; i < FLT_ARG_CNT; i++)
261                 M_DST(rd->argfltregs[i], REG_SP, BIAS + (WINSAVE_CNT + 1 + i) * 8);
262
263         /* save temporary registers for leaf methods */
264 /* XXX no leaf optimization yet
265         if (jd->isleafmethod) {
266                 for (i = 0; i < INT_TMP_CNT; i++)
267                         M_LST(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
268
269                 for (i = 0; i < FLT_TMP_CNT; i++)
270                         M_DST(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
271         }
272 */
273         /* load float arguments into integer registers */
274
275         for (i = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
276                 t = md->paramtypes[i].type;
277
278                 if (IS_FLT_DBL_TYPE(t)) {
279                         if (IS_2_WORD_TYPE(t)) {
280                                 M_DST(rd->argfltregs[i], REG_SP, USESTACK);
281                                 M_LDX(rd->argintregs[i], REG_SP, USESTACK);
282                         }
283                         else {
284                                 M_DST(rd->argfltregs[i], REG_SP, USESTACK);
285                                 M_LDX(rd->argintregs[i], REG_SP, USESTACK);
286                         }
287                 }
288         }
289
290         disp = dseg_add_address(cd, m);
291         M_ALD(REG_ITMP1, REG_PV_CALLEE, disp);
292         M_AST(REG_ITMP1, REG_SP, USESTACK);
293         disp = dseg_add_functionptr(cd, builtin_trace_args);
294         M_ALD(REG_PV_CALLER, REG_PV_CALLEE, disp);
295         M_JMP(REG_RA_CALLER, REG_PV_CALLER, REG_ZERO);
296         M_NOP;
297
298         /* restore float argument registers */
299
300         for (i = 0; i < FLT_ARG_CNT; i++)
301                 M_DLD(rd->argfltregs[i], REG_SP, BIAS + (WINSAVE_CNT + 1 + i) * 8);
302
303         /* restore temporary registers for leaf methods */
304 /* XXX no leaf optimization yet
305         if (jd->isleafmethod) {
306                 for (i = 0; i < INT_TMP_CNT; i++)
307                         M_LLD(rd->tmpintregs[i], REG_SP, (2 + ARG_CNT + i) * 8);
308
309                 for (i = 0; i < FLT_TMP_CNT; i++)
310                         M_DLD(rd->tmpfltregs[i], REG_SP, (2 + ARG_CNT + INT_TMP_CNT + i) * 8);
311         }
312 */
313         M_LDA(REG_SP, REG_SP, (1 + WINSAVE_CNT + FLT_ARG_CNT) * 8);
314
315         /* mark trace code */
316
317         M_NOP;
318 }
319 #endif /* !defined(NDEBUG) */
320
321
322 /* emit_verbosecall_exit *******************************************************
323
324    Generates the code for the call trace.
325
326 *******************************************************************************/
327
328 #if !defined(NDEBUG)
329 void emit_verbosecall_exit(jitdata *jd)
330 {
331         methodinfo   *m;
332         codegendata  *cd;
333         registerdata *rd;
334         s4            disp;
335
336         /* get required compiler data */
337
338         m  = jd->m;
339         cd = jd->cd;
340         rd = jd->rd;
341
342         /* mark trace code */
343
344         M_NOP;
345
346         M_LDA(REG_SP, REG_SP, -2 * 8);           /* keep stack 16-byte aligned ???*/
347
348         M_DST(REG_FRESULT, REG_SP, USESTACK + (1 * 8));
349
350         disp = dseg_add_address(cd, m);
351         M_ALD(rd->argintregs[0], REG_PV_CALLEE, disp);
352
353         M_MOV(REG_RESULT_CALLEE, rd->argintregs[1]);
354         M_DMOV(REG_FRESULT, rd->argfltregs[2]);
355         M_FMOV(REG_FRESULT, rd->argfltregs[3]);
356
357         disp = dseg_add_functionptr(cd, builtin_displaymethodstop);
358         M_ALD(REG_ITMP3, REG_PV_CALLEE, disp);
359         M_JMP(REG_RA_CALLER, REG_ITMP3, REG_ZERO);
360         M_NOP;
361
362         M_DLD(REG_FRESULT, REG_SP, USESTACK + (1 * 8));
363
364         M_LDA(REG_SP, REG_SP, 2 * 8);
365
366         /* mark trace code */
367
368         M_NOP;
369 }
370 #endif /* !defined(NDEBUG) */
371
372
373 /*
374  * These are local overrides for various environment variables in Emacs.
375  * Please do not remove this and leave it at the end of the file, where
376  * Emacs will automagically detect them.
377  * ---------------------------------------------------------------------
378  * Local variables:
379  * mode: c
380  * indent-tabs-mode: t
381  * c-basic-offset: 4
382  * tab-width: 4
383  * End:
384  * vim:noexpandtab:sw=4:ts=4:
385  */