1 /* src/vm/jit/emit-common.cpp - common code emitter functions
3 Copyright (C) 2006, 2007, 2008
4 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
6 This file is part of CACAO.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2, or (at
11 your option) any later version.
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
38 #include "toolbox/list.hpp"
40 #include "vm/options.h"
41 #include "vm/statistics.h"
43 #include "vm/jit/emit-common.hpp"
44 #include "vm/jit/jit.hpp"
45 #include "vm/jit/patcher-common.hpp"
48 /* emit_load_s1 ****************************************************************
50 Emits a possible load of the first source operand.
52 *******************************************************************************/
54 s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
59 src = VAROP(iptr->s1);
61 reg = emit_load(jd, iptr, src, tempreg);
67 /* emit_load_s2 ****************************************************************
69 Emits a possible load of the second source operand.
71 *******************************************************************************/
73 s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
78 src = VAROP(iptr->sx.s23.s2);
80 reg = emit_load(jd, iptr, src, tempreg);
86 /* emit_load_s3 ****************************************************************
88 Emits a possible load of the third source operand.
90 *******************************************************************************/
92 s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
97 src = VAROP(iptr->sx.s23.s3);
99 reg = emit_load(jd, iptr, src, tempreg);
105 /* emit_load_s1_low ************************************************************
107 Emits a possible load of the low 32-bits of the first long source
110 *******************************************************************************/
112 #if SIZEOF_VOID_P == 4
113 s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
118 src = VAROP(iptr->s1);
120 reg = emit_load_low(jd, iptr, src, tempreg);
127 /* emit_load_s2_low ************************************************************
129 Emits a possible load of the low 32-bits of the second long source
132 *******************************************************************************/
134 #if SIZEOF_VOID_P == 4
135 s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
140 src = VAROP(iptr->sx.s23.s2);
142 reg = emit_load_low(jd, iptr, src, tempreg);
149 /* emit_load_s3_low ************************************************************
151 Emits a possible load of the low 32-bits of the third long source
154 *******************************************************************************/
156 #if SIZEOF_VOID_P == 4
157 s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
162 src = VAROP(iptr->sx.s23.s3);
164 reg = emit_load_low(jd, iptr, src, tempreg);
171 /* emit_load_s1_high ***********************************************************
173 Emits a possible load of the high 32-bits of the first long source
176 *******************************************************************************/
178 #if SIZEOF_VOID_P == 4
179 s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
184 src = VAROP(iptr->s1);
186 reg = emit_load_high(jd, iptr, src, tempreg);
193 /* emit_load_s2_high ***********************************************************
195 Emits a possible load of the high 32-bits of the second long source
198 *******************************************************************************/
200 #if SIZEOF_VOID_P == 4
201 s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
206 src = VAROP(iptr->sx.s23.s2);
208 reg = emit_load_high(jd, iptr, src, tempreg);
215 /* emit_load_s3_high ***********************************************************
217 Emits a possible load of the high 32-bits of the third long source
220 *******************************************************************************/
222 #if SIZEOF_VOID_P == 4
223 s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
228 src = VAROP(iptr->sx.s23.s3);
230 reg = emit_load_high(jd, iptr, src, tempreg);
237 /* emit_store_dst **************************************************************
239 This function generates the code to store the result of an
240 operation back into a spilled pseudo-variable. If the
241 pseudo-variable has not been spilled in the first place, this
242 function will generate nothing.
244 *******************************************************************************/
246 void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
248 emit_store(jd, iptr, VAROP(iptr->dst), d);
252 /* emit_patcher_traps **********************************************************
254 Generates the code for the patcher traps.
256 *******************************************************************************/
258 void emit_patcher_traps(jitdata *jd)
266 /* get required compiler data */
271 // Generate patcher traps code.
272 for (List<patchref_t>::iterator it = code->patchers->begin(); it != code->patchers->end(); it++) {
273 patchref_t& pr = *it;
275 /* Calculate the patch position where the original machine
276 code is located and the trap should be placed. */
278 tmpmcodeptr = (u1 *) (cd->mcodebase + pr.mpc);
280 /* Patch in the trap to call the signal handler (done at
283 savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
284 cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
286 mcode = emit_trap(cd);
288 cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
290 /* Remember the original machine code which is patched
291 back in later (done at runtime). */
298 /* emit_bccz *******************************************************************
300 Emit conditional and unconditional branch instructions on integer
303 *******************************************************************************/
305 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
310 /* Target basic block already has an PC, so we can generate the
311 branch immediately. */
313 if ((target->mpc >= 0)) {
314 STATISTICS(count_branches_resolved++);
316 /* calculate the mpc of the branch instruction */
318 branchmpc = cd->mcodeptr - cd->mcodebase;
319 disp = target->mpc - branchmpc;
321 #if defined(ENABLE_STATISTICS)
323 if ((int8_t)disp == disp) count_emit_branch_8bit++;
324 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
325 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
326 # if SIZEOF_VOID_P == 8
327 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
331 emit_branch(cd, disp, condition, reg, options);
334 /* current mcodeptr is the correct position,
335 afterwards emit the NOPs */
337 codegen_add_branch_ref(cd, target, condition, reg, options);
339 /* generate NOPs as placeholder for branch code */
346 /* emit_bcc ********************************************************************
348 Emit conditional and unconditional branch instructions on condition
351 *******************************************************************************/
353 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
355 emit_bccz(cd, target, condition, -1, options);
359 /* emit_br *********************************************************************
361 Wrapper for unconditional branches.
363 *******************************************************************************/
365 void emit_br(codegendata *cd, basicblock *target)
367 emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
371 /* emit_bxxz *******************************************************************
373 Wrappers for branches on one integer register.
375 *******************************************************************************/
377 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
379 void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
381 emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
384 void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
386 emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
389 void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
391 emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
394 void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
396 emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
399 void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
401 emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
404 void emit_blez(codegendata *cd, basicblock *target, s4 reg)
406 emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
409 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
412 /* emit_bxx ********************************************************************
414 Wrappers for branches on two integer registers.
416 We use PACK_REGS here, so we don't have to change the branchref
417 data structure and the emit_bccz function.
419 *******************************************************************************/
421 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
423 void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
425 emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
428 void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
430 emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
433 #endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
436 /* emit_bxx ********************************************************************
438 Wrappers for branches on condition codes.
440 *******************************************************************************/
442 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
444 void emit_beq(codegendata *cd, basicblock *target)
446 emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
449 void emit_bne(codegendata *cd, basicblock *target)
451 emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
454 void emit_blt(codegendata *cd, basicblock *target)
456 emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
459 void emit_bge(codegendata *cd, basicblock *target)
461 emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
464 void emit_bgt(codegendata *cd, basicblock *target)
466 emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
469 void emit_ble(codegendata *cd, basicblock *target)
471 emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
474 #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
475 void emit_bult(codegendata *cd, basicblock *target)
477 emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
480 void emit_bule(codegendata *cd, basicblock *target)
482 emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
485 void emit_buge(codegendata *cd, basicblock *target)
487 emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
490 void emit_bugt(codegendata *cd, basicblock *target)
492 emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
496 #if defined(__POWERPC__) || defined(__POWERPC64__)
497 void emit_bnan(codegendata *cd, basicblock *target)
499 emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
503 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
506 /* emit_label_bccz *************************************************************
508 Emit a branch to a label. Possibly emit the branch, if it is a
511 *******************************************************************************/
513 void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
515 // Search if the label is already in the list.
516 DumpList<branch_label_ref_t*>::iterator it;
517 for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
518 branch_label_ref_t* br = *it;
520 /* is this entry the correct label? */
522 if (br->label == label)
526 if (it == cd->brancheslabel->end()) {
527 /* current mcodeptr is the correct position,
528 afterwards emit the NOPs */
530 codegen_branch_label_add(cd, label, condition, reg, options);
532 /* generate NOPs as placeholder for branch code */
538 // Branch reference was found.
539 branch_label_ref_t* br = *it;
541 /* calculate the mpc of the branch instruction */
543 int32_t mpc = cd->mcodeptr - cd->mcodebase;
544 int32_t disp = br->mpc - mpc;
546 #if defined(ENABLE_STATISTICS)
548 if ((int8_t)disp == disp) count_emit_branch_8bit++;
549 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
550 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
551 # if SIZEOF_VOID_P == 8
552 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
556 emit_branch(cd, disp, condition, reg, options);
558 // Now remove the branch reference.
559 cd->brancheslabel->remove(br);
563 /* emit_label ******************************************************************
565 Emit a label for a branch. Possibly emit the branch, if it is a
568 *******************************************************************************/
570 void emit_label(codegendata *cd, s4 label)
574 // Search if the label is already in the list.
575 DumpList<branch_label_ref_t*>::iterator it;
576 for (it = cd->brancheslabel->begin(); it != cd->brancheslabel->end(); it++) {
577 branch_label_ref_t* br = *it;
579 /* is this entry the correct label? */
581 if (br->label == label)
585 if (it == cd->brancheslabel->end()) {
586 /* No branch reference found, add the label to the list (use
587 invalid values for condition and register). */
589 codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
593 // Branch reference was found.
594 branch_label_ref_t* br = *it;
596 // Calculate the mpc of the branch instruction.
597 int32_t mpc = cd->mcodeptr - cd->mcodebase;
598 int32_t disp = mpc - br->mpc;
600 /* temporary set the mcodeptr */
602 mcodeptr = cd->mcodeptr;
603 cd->mcodeptr = cd->mcodebase + br->mpc;
605 #if defined(ENABLE_STATISTICS)
607 if ((int8_t)disp == disp) count_emit_branch_8bit++;
608 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
609 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
610 # if SIZEOF_VOID_P == 8
611 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
615 emit_branch(cd, disp, br->condition, br->reg, br->options);
617 /* restore mcodeptr */
619 cd->mcodeptr = mcodeptr;
621 // Now remove the branch reference.
622 cd->brancheslabel->remove(br);
626 /* emit_label_bcc **************************************************************
628 Emit conditional and unconditional label-branch instructions on
631 *******************************************************************************/
633 void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
635 emit_label_bccz(cd, label, condition, -1, options);
639 /* emit_label_br ***************************************************************
641 Wrapper for unconditional label-branches.
643 *******************************************************************************/
645 void emit_label_br(codegendata *cd, s4 label)
647 emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
651 /* emit_label_bxxz *************************************************************
653 Wrappers for label-branches on one integer register.
655 *******************************************************************************/
657 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
659 void emit_label_beqz(codegendata* cd, int label, int reg)
661 emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
664 void emit_label_bnez(codegendata* cd, int label, int reg)
666 emit_label_bccz(cd, label, BRANCH_NE, reg, BRANCH_OPT_NONE);
669 void emit_label_bltz(codegendata* cd, int label, int reg)
671 emit_label_bccz(cd, label, BRANCH_LT, reg, BRANCH_OPT_NONE);
674 void emit_label_bgtz(codegendata* cd, int label, int reg)
676 emit_label_bccz(cd, label, BRANCH_GT, reg, BRANCH_OPT_NONE);
679 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
682 /* emit_label_bxx **************************************************************
684 Wrappers for label-branches on two integer registers.
686 We use PACK_REGS here, so we don't have to change the branchref
687 data structure and the emit_bccz function.
689 *******************************************************************************/
691 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
693 void emit_label_beq(codegendata* cd, int label, int s1, int s2)
695 emit_label_bccz(cd, label, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
698 void emit_label_bne(codegendata* cd, int label, int s1, int s2)
700 emit_label_bccz(cd, label, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
703 #endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
706 /* emit_label_bxx **************************************************************
708 Wrappers for label-branches on condition codes.
710 *******************************************************************************/
712 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
714 void emit_label_beq(codegendata *cd, s4 label)
716 emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
719 void emit_label_bne(codegendata *cd, s4 label)
721 emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
724 void emit_label_blt(codegendata *cd, s4 label)
726 emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
729 void emit_label_bge(codegendata *cd, s4 label)
731 emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
734 void emit_label_bgt(codegendata *cd, s4 label)
736 emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
739 void emit_label_ble(codegendata *cd, s4 label)
741 emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
744 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
748 * These are local overrides for various environment variables in Emacs.
749 * Please do not remove this and leave it at the end of the file, where
750 * Emacs will automagically detect them.
751 * ---------------------------------------------------------------------
754 * indent-tabs-mode: t
758 * vim:noexpandtab:sw=4:ts=4: