1 /* src/vm/jit/emit-common.c - common code emitter functions
3 Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4 R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5 C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6 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 $Id: emit-common.c 8265 2007-08-06 16:10:42Z twisti $
40 #include "vm/jit/emit-common.h"
41 #include "vm/jit/jit.h"
42 #include "vm/jit/patcher-common.h"
44 #include "vmcore/options.h"
45 #include "vmcore/statistics.h"
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)
267 /* get required compiler data */
272 /* generate patcher traps code */
274 for (pr = list_first_unsynced(code->patchers); pr != NULL; pr = list_next_unsynced(code->patchers, pr)) {
276 /* Calculate the patch position where the original machine
277 code is located and the trap should be placed. */
279 tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
281 /* Patch in the trap to call the signal handler (done at
284 savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
285 cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
287 mcode = emit_trap(cd);
289 cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
291 /* Remember the original machine code which is patched
292 back in later (done at runtime). */
299 /* emit_bccz *******************************************************************
301 Emit conditional and unconditional branch instructions on integer
304 *******************************************************************************/
306 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
311 /* Target basic block already has an PC, so we can generate the
312 branch immediately. */
314 if ((target->mpc >= 0)) {
315 STATISTICS(count_branches_resolved++);
317 /* calculate the mpc of the branch instruction */
319 branchmpc = cd->mcodeptr - cd->mcodebase;
320 disp = target->mpc - branchmpc;
322 #if defined(ENABLE_STATISTICS)
324 if ((int8_t)disp == disp) count_emit_branch_8bit++;
325 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
326 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
327 # if SIZEOF_VOID_P == 8
328 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
332 emit_branch(cd, disp, condition, reg, options);
335 /* current mcodeptr is the correct position,
336 afterwards emit the NOPs */
338 codegen_add_branch_ref(cd, target, condition, reg, options);
340 /* generate NOPs as placeholder for branch code */
347 /* emit_bcc ********************************************************************
349 Emit conditional and unconditional branch instructions on condition
352 *******************************************************************************/
354 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
356 emit_bccz(cd, target, condition, -1, options);
360 /* emit_br *********************************************************************
362 Wrapper for unconditional branches.
364 *******************************************************************************/
366 void emit_br(codegendata *cd, basicblock *target)
368 emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
372 /* emit_bxxz *******************************************************************
374 Wrappers for branches on one integer register.
376 *******************************************************************************/
378 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
380 void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
382 emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
385 void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
387 emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
390 void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
392 emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
395 void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
397 emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
400 void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
402 emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
405 void emit_blez(codegendata *cd, basicblock *target, s4 reg)
407 emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
410 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
413 /* emit_bxx ********************************************************************
415 Wrappers for branches on two integer registers.
417 We use PACK_REGS here, so we don't have to change the branchref
418 data structure and the emit_bccz function.
420 *******************************************************************************/
422 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
424 void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
426 emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
429 void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
431 emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
434 #endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
437 /* emit_bxx ********************************************************************
439 Wrappers for branches on condition codes.
441 *******************************************************************************/
443 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
445 void emit_beq(codegendata *cd, basicblock *target)
447 emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
450 void emit_bne(codegendata *cd, basicblock *target)
452 emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
455 void emit_blt(codegendata *cd, basicblock *target)
457 emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
460 void emit_bge(codegendata *cd, basicblock *target)
462 emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
465 void emit_bgt(codegendata *cd, basicblock *target)
467 emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
470 void emit_ble(codegendata *cd, basicblock *target)
472 emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
475 #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
476 void emit_bult(codegendata *cd, basicblock *target)
478 emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
481 void emit_bule(codegendata *cd, basicblock *target)
483 emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
486 void emit_buge(codegendata *cd, basicblock *target)
488 emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
491 void emit_bugt(codegendata *cd, basicblock *target)
493 emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
497 #if defined(__POWERPC__) || defined(__POWERPC64__)
498 void emit_bnan(codegendata *cd, basicblock *target)
500 emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
504 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
507 /* emit_label_bccz *************************************************************
509 Emit a branch to a label. Possibly emit the branch, if it is a
512 *******************************************************************************/
514 void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
517 branch_label_ref_t *br;
521 /* get the label list */
523 list = cd->brancheslabel;
525 /* search if the label is already in the list */
527 for (br = list_first_unsynced(list); br != NULL;
528 br = list_next_unsynced(list, br)) {
529 /* is this entry the correct label? */
531 if (br->label == label)
535 /* a branch reference was found */
538 /* calculate the mpc of the branch instruction */
540 mpc = cd->mcodeptr - cd->mcodebase;
541 disp = br->mpc - mpc;
543 #if defined(ENABLE_STATISTICS)
545 if ((int8_t)disp == disp) count_emit_branch_8bit++;
546 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
547 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
548 # if SIZEOF_VOID_P == 8
549 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
553 emit_branch(cd, disp, condition, reg, options);
555 /* now remove the branch reference */
557 list_remove_unsynced(list, br);
560 /* current mcodeptr is the correct position,
561 afterwards emit the NOPs */
563 codegen_branch_label_add(cd, label, condition, reg, options);
565 /* generate NOPs as placeholder for branch code */
572 /* emit_label ******************************************************************
574 Emit a label for a branch. Possibly emit the branch, if it is a
577 *******************************************************************************/
579 void emit_label(codegendata *cd, s4 label)
582 branch_label_ref_t *br;
587 /* get the label list */
589 list = cd->brancheslabel;
591 /* search if the label is already in the list */
593 for (br = list_first_unsynced(list); br != NULL;
594 br = list_next_unsynced(list, br)) {
595 /* is this entry the correct label? */
597 if (br->label == label)
601 /* a branch reference was found */
604 /* calculate the mpc of the branch instruction */
606 mpc = cd->mcodeptr - cd->mcodebase;
607 disp = mpc - br->mpc;
609 /* temporary set the mcodeptr */
611 mcodeptr = cd->mcodeptr;
612 cd->mcodeptr = cd->mcodebase + br->mpc;
614 #if defined(ENABLE_STATISTICS)
616 if ((int8_t)disp == disp) count_emit_branch_8bit++;
617 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
618 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
619 # if SIZEOF_VOID_P == 8
620 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
624 emit_branch(cd, disp, br->condition, br->reg, br->options);
626 /* restore mcodeptr */
628 cd->mcodeptr = mcodeptr;
630 /* now remove the branch reference */
632 list_remove_unsynced(list, br);
635 /* add the label to the list (use invalid values for condition
638 codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
643 /* emit_label_bcc **************************************************************
645 Emit conditional and unconditional label-branch instructions on
648 *******************************************************************************/
650 void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
652 emit_label_bccz(cd, label, condition, -1, options);
656 /* emit_label_br ***************************************************************
658 Wrapper for unconditional label-branches.
660 *******************************************************************************/
662 void emit_label_br(codegendata *cd, s4 label)
664 emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
668 /* emit_label_bxxz *************************************************************
670 Wrappers for label-branches on one integer register.
672 *******************************************************************************/
674 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
676 void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
678 emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
681 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
684 /* emit_label_bxx **************************************************************
686 Wrappers for label-branches on condition codes.
688 *******************************************************************************/
690 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
692 void emit_label_beq(codegendata *cd, s4 label)
694 emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
697 void emit_label_bne(codegendata *cd, s4 label)
699 emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
702 void emit_label_blt(codegendata *cd, s4 label)
704 emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
707 void emit_label_bge(codegendata *cd, s4 label)
709 emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
712 void emit_label_bgt(codegendata *cd, s4 label)
714 emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
717 void emit_label_ble(codegendata *cd, s4 label)
719 emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
722 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
726 * These are local overrides for various environment variables in Emacs.
727 * Please do not remove this and leave it at the end of the file, where
728 * Emacs will automagically detect them.
729 * ---------------------------------------------------------------------
732 * indent-tabs-mode: t
736 * vim:noexpandtab:sw=4:ts=4: