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 $
44 #include "vm/jit/emit.h"
45 #include "vm/jit/jit.h"
46 #include "vm/jit/powerpc64/codegen.h"
47 #include "vm/builtin.h"
50 /* code generation functions **************************************************/
52 /* emit_load_s1 ****************************************************************
54 Emits a possible load of the first source operand.
56 *******************************************************************************/
58 s4 emit_load_s1(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
64 /* get required compiler data */
68 if (src->flags & INMEMORY) {
71 disp = src->regoff * 4;
73 if (IS_FLT_DBL_TYPE(src->type)) {
74 if (IS_2_WORD_TYPE(src->type))
75 M_DLD(tempreg, REG_SP, disp);
77 M_FLD(tempreg, REG_SP, disp);
80 if (IS_2_WORD_TYPE(src->type))
81 M_LLD(tempreg, REG_SP, disp);
83 M_ILD(tempreg, REG_SP, disp);
94 /* emit_load_s2 ****************************************************************
96 Emits a possible load of the second source operand.
98 *******************************************************************************/
100 s4 emit_load_s2(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
106 /* get required compiler data */
110 if (src->flags & INMEMORY) {
113 disp = src->regoff * 4;
115 if (IS_FLT_DBL_TYPE(src->type)) {
116 if (IS_2_WORD_TYPE(src->type))
117 M_DLD(tempreg, REG_SP, disp);
119 M_FLD(tempreg, REG_SP, disp);
122 if (IS_2_WORD_TYPE(src->type))
123 M_LLD(tempreg, REG_SP, disp);
125 M_ILD(tempreg, REG_SP, disp);
136 /* emit_load_s3 ****************************************************************
138 Emits a possible load of the third source operand.
140 *******************************************************************************/
142 s4 emit_load_s3(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
148 /* get required compiler data */
152 if (src->flags & INMEMORY) {
155 disp = src->regoff * 4;
157 if (IS_FLT_DBL_TYPE(src->type)) {
158 if (IS_2_WORD_TYPE(src->type))
159 M_DLD(tempreg, REG_SP, disp);
161 M_FLD(tempreg, REG_SP, disp);
164 if (IS_2_WORD_TYPE(src->type))
165 M_LLD(tempreg, REG_SP, disp);
167 M_ILD(tempreg, REG_SP, disp);
178 /* emit_load_s1_low ************************************************************
180 Emits a possible load of the low 32-bits of the first long source
183 *******************************************************************************/
185 s4 emit_load_s1_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
191 assert(src->type == TYPE_LNG);
193 /* get required compiler data */
197 if (src->flags & INMEMORY) {
200 disp = src->regoff * 4;
202 M_ILD(tempreg, REG_SP, disp + 4);
206 reg = GET_LOW_REG(src->regoff);
212 /* emit_load_s2_low ************************************************************
214 Emits a possible load of the low 32-bits of the second long source
217 *******************************************************************************/
219 s4 emit_load_s2_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
225 assert(src->type == TYPE_LNG);
227 /* get required compiler data */
231 if (src->flags & INMEMORY) {
234 disp = src->regoff * 4;
236 M_ILD(tempreg, REG_SP, disp + 4);
240 reg = GET_LOW_REG(src->regoff);
246 /* emit_load_s3_low ************************************************************
248 Emits a possible load of the low 32-bits of the third long source
251 *******************************************************************************/
253 s4 emit_load_s3_low(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
259 assert(src->type == TYPE_LNG);
261 /* get required compiler data */
265 if (src->flags & INMEMORY) {
268 disp = src->regoff * 4;
270 M_ILD(tempreg, REG_SP, disp + 4);
274 reg = GET_LOW_REG(src->regoff);
280 /* emit_load_s1_high ***********************************************************
282 Emits a possible load of the high 32-bits of the first long source
285 *******************************************************************************/
287 s4 emit_load_s1_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
293 assert(src->type == TYPE_LNG);
295 /* get required compiler data */
299 if (src->flags & INMEMORY) {
302 disp = src->regoff * 4;
304 M_ILD(tempreg, REG_SP, disp);
308 reg = GET_HIGH_REG(src->regoff);
314 /* emit_load_s2_high ***********************************************************
316 Emits a possible load of the high 32-bits of the second long source
319 *******************************************************************************/
321 s4 emit_load_s2_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
327 assert(src->type == TYPE_LNG);
329 /* get required compiler data */
333 if (src->flags & INMEMORY) {
336 disp = src->regoff * 4;
338 M_ILD(tempreg, REG_SP, disp);
342 reg = GET_HIGH_REG(src->regoff);
348 /* emit_load_s3_high ***********************************************************
350 Emits a possible load of the high 32-bits of the third long source
353 *******************************************************************************/
355 s4 emit_load_s3_high(jitdata *jd, instruction *iptr, stackptr src, s4 tempreg)
361 assert(src->type == TYPE_LNG);
363 /* get required compiler data */
367 if (src->flags & INMEMORY) {
370 disp = src->regoff * 4;
372 M_ILD(tempreg, REG_SP, disp);
376 reg = GET_HIGH_REG(src->regoff);
382 /* emit_store ******************************************************************
386 *******************************************************************************/
388 void emit_store(jitdata *jd, instruction *iptr, stackptr dst, s4 d)
392 /* get required compiler data */
396 if (dst->flags & INMEMORY) {
399 if (IS_FLT_DBL_TYPE(dst->type)) {
400 if (IS_2_WORD_TYPE(dst->type))
401 M_DST(d, REG_SP, dst->regoff * 4);
403 M_FST(d, REG_SP, dst->regoff * 4);
406 if (IS_2_WORD_TYPE(dst->type))
407 M_LST(d, REG_SP, dst->regoff * 4);
409 M_IST(d, REG_SP, dst->regoff * 4);
415 /* emit_copy *******************************************************************
419 *******************************************************************************/
421 void emit_copy(jitdata *jd, instruction *iptr, stackptr src, stackptr dst)
427 /* get required compiler data */
432 if (src->type == TYPE_LNG)
433 d = codegen_reg_of_var(rd, iptr->opc, dst, PACK_REGS(REG_ITMP2, REG_ITMP1));
435 d = codegen_reg_of_var(rd, iptr->opc, dst, REG_IFTMP);
437 if ((src->regoff != dst->regoff) ||
438 ((src->flags ^ dst->flags) & INMEMORY)) {
439 s1 = emit_load_s1(jd, iptr, src, d);
442 if (IS_FLT_DBL_TYPE(src->type))
445 if (IS_2_WORD_TYPE(src->type)) {
446 M_MOV(GET_LOW_REG(s1), GET_LOW_REG(d));
447 M_MOV(GET_HIGH_REG(s1), GET_HIGH_REG(d));
453 emit_store(jd, iptr, dst, d);
458 /* emit_iconst *****************************************************************
462 *******************************************************************************/
464 void emit_iconst(codegendata *cd, s4 d, s4 value)
468 if ((value >= -32768) && (value <= 32767))
469 M_LDA_INTERN(d, REG_ZERO, value);
471 disp = dseg_adds4(cd, value);
472 M_ILD(d, REG_PV, disp);
476 /* emit_verbosecall_enter ******************************************************
478 * Generates the code for the call trace.
480 ********************************************************************************/
481 void emit_verbosecall_enter (jitdata *jd)
491 /* get required compiler data */
499 /* Build up Stackframe for builtin_trace_args call (a multiple of 16) */
503 /* setup stack for TRACE_ARGS_NUM registers */
504 /* == LA_SIZE + PA_SIZE + 8 (methodinfo argument) + TRACE_ARGS_NUM*8 + 8 (itmp1) */
506 /* in nativestubs no Place to save the LR (Link Register) would be needed */
507 /* but since the stack frame has to be aligned the 4 Bytes would have to */
508 /* be padded again */
510 #if defined(__DARWIN__)
511 stack_size = LA_SIZE + (TRACE_ARGS_NUM + 1) * 8;
513 stack_size = LA_SIZE + PA_SIZE + 8 + TRACE_ARGS_NUM * 8 + 8;
516 /* mark trace code */
519 /* save up to TRACE_ARGS_NUM arguments into the reserved stack space */
521 #if defined(__DARWIN__)
522 /* Copy Params starting from first to Stack */
523 /* since TRACE_ARGS == INT_ARG_CNT all used integer argument regs */
527 /* Copy Params starting from fifth to Stack (INT_ARG_CNT/2) are in */
528 /* integer argument regs */
529 /* all integer argument registers have to be saved */
530 for (p = 0; p < 8; p++) {
531 d = rd->argintregs[p];
532 /* save integer argument registers */
533 M_LST(d, REG_SP, LA_SIZE + PA_SIZE + 4 * 8 + 8 + p * 8);
539 M_AST(REG_ZERO, REG_SP, LA_LR_OFFSET);
540 M_STDU(REG_SP, REG_SP, -stack_size);
541 stack_off = LA_SIZE + PA_SIZE;
542 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
543 t = md->paramtypes[p].type;
544 if (IS_INT_LNG_TYPE(t)) {
545 if (!md->params[p].inmemory) { /* Param in Arg Reg */
546 M_LST(rd->argintregs[md->params[p].regoff], REG_SP, stack_off);
547 } else { /* Param on Stack */
548 s1 = (md->params[p].regoff + cd->stackframesize) * 8 + stack_size;
549 M_LLD(REG_ITMP2, REG_SP, s1);
550 M_LST(REG_ITMP2, REG_SP, stack_off);
552 } else { /* IS_FLT_DBL_TYPE(t) */
553 if (!md->params[p].inmemory) { /* in Arg Reg */
554 s1 = rd->argfltregs[md->params[p].regoff];
555 M_DST(s1, REG_SP, stack_off);
556 } else { /* on Stack */
557 /* this should not happen */
563 /* load first 4 (==INT_ARG_CNT/2) arguments into integer registers */
564 #if defined(__DARWIN__)
565 for (p = 0; p < 8; p++) {
566 d = rd->argintregs[p];
567 M_ILD(d, REG_SP, LA_SIZE + p * 4);
571 /* Set integer and float argument registers for trace_args call */
572 /* offset to saved integer argument registers */
573 stack_off = LA_SIZE + PA_SIZE;
574 for (p = 0; (p < TRACE_ARGS_NUM) && (p < md->paramcount); p++, stack_off += 8) {
575 t = md->paramtypes[p].type;
576 if (IS_INT_LNG_TYPE(t)) {
577 M_LLD(rd->argintregs[p], REG_SP,stack_off);
578 } else { /* Float/Dbl */
579 if (!md->params[p].inmemory) { /* Param in Arg Reg */
580 /* use reserved Place on Stack (sp + 5 * 16) to copy */
581 /* float/double arg reg to int reg */
582 s1 = rd->argfltregs[md->params[p].regoff];
583 M_MOV(s1, rd->argintregs[p]);
591 /* put methodinfo pointer on Stackframe */
592 p = dseg_addaddress(cd, m);
593 M_ALD(REG_ITMP1, REG_PV, p);
594 #if defined(__DARWIN__)
595 M_AST(REG_ITMP1, REG_SP, LA_SIZE + TRACE_ARGS_NUM * 8);
597 if (TRACE_ARGS_NUM == 8) {
598 /* need to pass via stack */
599 M_AST(REG_ITMP1, REG_SP, LA_SIZE + PA_SIZE);
601 /* pass via register, reg 3 is the first */
602 M_MOV(REG_ITMP1, 3 + TRACE_ARGS_NUM);
605 /* call via function descriptor */
606 /* XXX: what about TOC? */
607 p = dseg_addaddress(cd, builtin_trace_args);
608 M_ALD(REG_ITMP2, REG_PV, p);
609 M_ALD(REG_ITMP1, REG_ITMP2, 0);
613 #if defined(__DARWIN__)
614 /* restore integer argument registers from the reserved stack space */
617 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++, stack_off += 8) {
618 t = md->paramtypes[p].type;
620 if (IS_INT_LNG_TYPE(t)) {
621 if (!md->params[p].inmemory) {
622 M_LLD(rd->argintregs[md->params[p].regoff], REG_SP, stack_off);
630 for (p = 0; p < md->paramcount && p < TRACE_ARGS_NUM; p++) {
631 d = rd->argintregs[p];
632 /* restore integer argument registers */
633 M_LLD(d, REG_SP, LA_SIZE + PA_SIZE + p * 8);
636 M_ALD(REG_ZERO, REG_SP, stack_size + LA_LR_OFFSET);
638 M_LDA(REG_SP, REG_SP, stack_size);
641 /* emit_verbosecall_exit ******************************************************
643 * Generates the code for the call trace.
645 ********************************************************************************/
646 void emit_verbosecall_exit(jitdata *jd)
648 codegendata *cd = jd->cd;
652 M_LDA(REG_SP, REG_SP, -(LA_SIZE+PA_SIZE+10*8));
653 M_DST(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
654 M_LST(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
655 M_AST(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
657 #if defined(__DARWIN__)
658 M_MOV(REG_RESULT, jd->rd->argintregs[1]);
660 M_MOV(REG_RESULT, jd->rd->argintregs[1]);
663 disp = dseg_addaddress(cd, jd->m);
664 M_ALD(jd->rd->argintregs[0], REG_PV, disp);
666 M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[0]);
667 M_FLTMOVE(REG_FRESULT, jd->rd->argfltregs[1]);
668 disp = dseg_addaddress(cd, builtin_displaymethodstop);
669 /* call via function descriptor, XXX: what about TOC ? */
670 M_ALD(REG_ITMP2, REG_PV, disp);
671 M_ALD(REG_ITMP2, REG_ITMP2, 0);
675 M_DLD(REG_FRESULT, REG_SP, LA_SIZE+PA_SIZE+0*8);
676 M_LLD(REG_RESULT, REG_SP, LA_SIZE+PA_SIZE+1*8);
677 M_ALD(REG_ZERO, REG_SP, LA_SIZE+PA_SIZE+2*8);
678 M_LDA(REG_SP, REG_SP, LA_SIZE+PA_SIZE+10*8);
685 * These are local overrides for various environment variables in Emacs.
686 * Please do not remove this and leave it at the end of the file, where
687 * Emacs will automagically detect them.
688 * ---------------------------------------------------------------------
691 * indent-tabs-mode: t
695 * vim:noexpandtab:sw=4:ts=4: