1 /* src/vm/jit/powerpc64/emit.c - PowerPC code emitter functions
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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
31 $Id: emitfuncs.c 4398 2006-01-31 23:43:08Z twisti $
43 #include "vm/jit/powerpc64/codegen.h"
45 #include "vm/builtin.h"
46 #include "vm/jit/emit-common.h"
47 #include "vm/jit/jit.h"
50 /* emit_load *******************************************************************
52 Emits a possible load of an operand.
54 *******************************************************************************/
56 s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
62 /* get required compiler data */
66 if (src->flags & INMEMORY) {
69 disp = src->vv.regoff * 8;
71 if (IS_FLT_DBL_TYPE(src->type)) {
72 if (IS_2_WORD_TYPE(src->type))
73 M_DLD(tempreg, REG_SP, disp);
75 M_FLD(tempreg, REG_SP, disp);
78 /* if (IS_2_WORD_TYPE(src->type))
79 M_LLD(tempreg, REG_SP, disp);
81 M_ILD(tempreg, REG_SP, disp);
83 M_LLD(tempreg, REG_SP, disp);
95 /* emit_store ******************************************************************
97 Emits a possible store to a variable.
99 *******************************************************************************/
101 void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
105 /* get required compiler data */
109 if (dst->flags & INMEMORY) {
112 if (IS_FLT_DBL_TYPE(dst->type)) {
113 if (IS_2_WORD_TYPE(dst->type))
114 M_DST(d, REG_SP, dst->vv.regoff * 8);
116 M_FST(d, REG_SP, dst->vv.regoff * 8);
119 M_LST(d, REG_SP, dst->vv.regoff * 8);
125 /* emit_copy *******************************************************************
127 Generates a register/memory to register/memory copy.
129 *******************************************************************************/
131 void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
137 /* get required compiler data */
142 if ((src->vv.regoff != dst->vv.regoff) ||
143 ((src->flags ^ dst->flags) & INMEMORY)) {
145 /* If one of the variables resides in memory, we can eliminate
146 the register move from/to the temporary register with the
147 order of getting the destination register and the load. */
149 if (IS_INMEMORY(src->flags)) {
150 d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
151 s1 = emit_load(jd, iptr, src, d);
154 s1 = emit_load(jd, iptr, src, REG_IFTMP);
155 d = codegen_reg_of_var(iptr->opc, dst, s1);
159 if (IS_FLT_DBL_TYPE(src->type))
165 emit_store(jd, iptr, dst, d);
170 /* emit_iconst *****************************************************************
174 *******************************************************************************/
176 void emit_iconst(codegendata *cd, s4 d, s4 value)
180 if ((value >= -32768) && (value <= 32767)) {
181 M_LDA_INTERN(d, REG_ZERO, value);
183 disp = dseg_adds4(cd, value);
184 M_ILD(d, REG_PV, disp);
188 void emit_lconst(codegendata *cd, s4 d, s8 value)
191 if ((value >= -32768) && (value <= 32767)) {
192 M_LDA_INTERN(d, REG_ZERO, value);
194 disp = dseg_adds8(cd, value);
195 M_LLD(d, REG_PV, disp);
200 /* emit_verbosecall_enter ******************************************************
202 * Generates the code for the call trace.
204 ********************************************************************************/
206 void emit_verbosecall_enter (jitdata *jd)
215 /* get required compiler data */
223 /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
227 /* setup stack for TRACE_ARGS_NUM registers */
228 /* == LA_SIZE + PA_SIZE + 8 (methodinfo argument) + TRACE_ARGS_NUM*8 + 8 (itmp1) */
230 /* in nativestubs no Place to save the LR (Link Register) would be needed */
231 /* but since the stack frame has to be aligned the 4 Bytes would have to */
232 /* be padded again */
234 #if defined(__DARWIN__)
235 stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
237 stack_size = LA_SIZE + PA_SIZE + 8 + TRACE_ARGS_NUM * 8 + 8;
240 /* mark trace code */
244 M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
245 M_STDU(REG_SP, REG_SP, -stack_size);
247 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
248 t = md->paramtypes[p].type;
249 if (IS_INT_LNG_TYPE(t)) {
250 if (!md->params[p].inmemory) { /* Param in Arg Reg */
251 M_LST(rd->argintregs[md->params[p].regoff], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
252 } else { /* Param on Stack */
253 s1 = (md->params[p].regoff + cd->stackframesize) * 8 + stack_size;
254 M_LLD(REG_ITMP2, REG_SP, s1);
255 M_LST(REG_ITMP2, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
257 } else { /* IS_FLT_DBL_TYPE(t) */
258 if (!md->params[p].inmemory) { /* in Arg Reg */
259 s1 = rd->argfltregs[md->params[p].regoff];
260 M_DST(s1, REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
261 } else { /* on Stack */
262 /* this should not happen */
268 #if defined(__DARWIN__)
269 #warning "emit_verbosecall_enter not implemented"
272 /* Set integer and float argument registers for trace_args call */
273 /* offset to saved integer argument registers */
274 for (p = 0; (p < TRACE_ARGS_NUM) && (p < md->paramcount); p++) {
275 t = md->paramtypes[p].type;
276 if (IS_INT_LNG_TYPE(t)) {
277 M_LLD(rd->argintregs[p], REG_SP,LA_SIZE + PA_SIZE + 8 + p * 8);
278 } else { /* Float/Dbl */
279 if (!md->params[p].inmemory) { /* Param in Arg Reg */
280 /* use reserved Place on Stack (sp + 5 * 16) to copy */
281 /* float/double arg reg to int reg */
282 s1 = rd->argfltregs[md->params[p].regoff];
283 M_MOV(s1, rd->argintregs[p]);
291 /* put methodinfo pointer on Stackframe */
292 p = dseg_addaddress(cd, m);
293 M_ALD(REG_ITMP1, REG_PV, p);
294 #if defined(__DARWIN__)
295 M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8);
297 if (TRACE_ARGS_NUM == 8) {
298 /* need to pass via stack */
299 M_AST(REG_ITMP1, REG_SP, LA_SIZE + PA_SIZE);
301 /* pass via register, reg 3 is the first */
302 M_MOV(REG_ITMP1, 3 + TRACE_ARGS_NUM);
305 /* call via function descriptor */
306 /* XXX: what about TOC? */
307 p = dseg_addaddress(cd, builtin_trace_args);
308 M_ALD(REG_ITMP2, REG_PV, p);
309 M_ALD(REG_ITMP1, REG_ITMP2, 0);
313 #if defined(__DARWIN__)
314 #warning "emit_verbosecall_enter not implemented"
317 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
318 t = md->paramtypes[p].type;
319 if (IS_INT_LNG_TYPE(t)) {
320 if (!md->params[p].inmemory) { /* Param in Arg Reg */
321 /* restore integer argument registers */
322 M_LLD(rd->argintregs[p], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
324 assert(0); /* TODO: implement this */
326 } else { /* FLT/DBL */
327 if (!md->params[p].inmemory) { /* Param in Arg Reg */
328 M_DLD(rd->argfltregs[md->params[p].regoff], REG_SP, LA_SIZE + PA_SIZE + 8 + p * 8);
330 assert(0); /* this shoudl never happen */
336 M_ALD(REG_ZERO, REG_SP, stack_size + LA_LR_OFFSET);
338 M_LDA(REG_SP, REG_SP, stack_size);
340 /* mark trace code */
345 /* emit_verbosecall_exit ******************************************************
347 * Generates the code for the call trace.
349 ********************************************************************************/
351 void emit_verbosecall_exit(jitdata *jd)
353 codegendata *cd = jd->cd;
356 /* mark trace code */
360 M_LDA(REG_SP, REG_SP, -(LA_SIZE+PA_SIZE+10*8));
361 M_DST(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
362 M_LST(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
363 M_AST(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
365 #if defined(__DARWIN__)
366 M_MOV(REG_RESULT, jd->rd->argintregs[1]);
368 M_MOV(REG_RESULT, jd->rd->argintregs[1]);
371 disp = dseg_addaddress(cd, jd->m);
372 M_ALD(jd->rd->argintregs[0], REG_PV, disp);
374 M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[0]);
375 M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[1]);
376 disp = dseg_addaddress(cd, builtin_displaymethodstop);
377 /* call via function descriptor, XXX: what about TOC ? */
378 M_ALD(REG_ITMP2, REG_PV, disp);
379 M_ALD(REG_ITMP2, REG_ITMP2, 0);
383 M_DLD(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
384 M_LLD(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
385 M_ALD(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
386 M_LDA(REG_SP, REG_SP, LA_SIZE+PA_SIZE+10*8);
389 /* mark trace code */
396 * These are local overrides for various environment variables in Emacs.
397 * Please do not remove this and leave it at the end of the file, where
398 * Emacs will automagically detect them.
399 * ---------------------------------------------------------------------
402 * indent-tabs-mode: t
406 * vim:noexpandtab:sw=4:ts=4: