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
38 #include "vm/jit/emit-common.h"
39 #include "vm/jit/jit.h"
40 #include "vm/jit/patcher-common.h"
42 #include "vmcore/options.h"
43 #include "vmcore/statistics.h"
46 /* emit_load_s1 ****************************************************************
48 Emits a possible load of the first source operand.
50 *******************************************************************************/
52 s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg)
57 src = VAROP(iptr->s1);
59 reg = emit_load(jd, iptr, src, tempreg);
65 /* emit_load_s2 ****************************************************************
67 Emits a possible load of the second source operand.
69 *******************************************************************************/
71 s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg)
76 src = VAROP(iptr->sx.s23.s2);
78 reg = emit_load(jd, iptr, src, tempreg);
84 /* emit_load_s3 ****************************************************************
86 Emits a possible load of the third source operand.
88 *******************************************************************************/
90 s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg)
95 src = VAROP(iptr->sx.s23.s3);
97 reg = emit_load(jd, iptr, src, tempreg);
103 /* emit_load_s1_low ************************************************************
105 Emits a possible load of the low 32-bits of the first long source
108 *******************************************************************************/
110 #if SIZEOF_VOID_P == 4
111 s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg)
116 src = VAROP(iptr->s1);
118 reg = emit_load_low(jd, iptr, src, tempreg);
125 /* emit_load_s2_low ************************************************************
127 Emits a possible load of the low 32-bits of the second long source
130 *******************************************************************************/
132 #if SIZEOF_VOID_P == 4
133 s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg)
138 src = VAROP(iptr->sx.s23.s2);
140 reg = emit_load_low(jd, iptr, src, tempreg);
147 /* emit_load_s3_low ************************************************************
149 Emits a possible load of the low 32-bits of the third long source
152 *******************************************************************************/
154 #if SIZEOF_VOID_P == 4
155 s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg)
160 src = VAROP(iptr->sx.s23.s3);
162 reg = emit_load_low(jd, iptr, src, tempreg);
169 /* emit_load_s1_high ***********************************************************
171 Emits a possible load of the high 32-bits of the first long source
174 *******************************************************************************/
176 #if SIZEOF_VOID_P == 4
177 s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg)
182 src = VAROP(iptr->s1);
184 reg = emit_load_high(jd, iptr, src, tempreg);
191 /* emit_load_s2_high ***********************************************************
193 Emits a possible load of the high 32-bits of the second long source
196 *******************************************************************************/
198 #if SIZEOF_VOID_P == 4
199 s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg)
204 src = VAROP(iptr->sx.s23.s2);
206 reg = emit_load_high(jd, iptr, src, tempreg);
213 /* emit_load_s3_high ***********************************************************
215 Emits a possible load of the high 32-bits of the third long source
218 *******************************************************************************/
220 #if SIZEOF_VOID_P == 4
221 s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg)
226 src = VAROP(iptr->sx.s23.s3);
228 reg = emit_load_high(jd, iptr, src, tempreg);
235 /* emit_store_dst **************************************************************
237 This function generates the code to store the result of an
238 operation back into a spilled pseudo-variable. If the
239 pseudo-variable has not been spilled in the first place, this
240 function will generate nothing.
242 *******************************************************************************/
244 void emit_store_dst(jitdata *jd, instruction *iptr, s4 d)
246 emit_store(jd, iptr, VAROP(iptr->dst), d);
250 /* emit_patcher_traps **********************************************************
252 Generates the code for the patcher traps.
254 *******************************************************************************/
256 void emit_patcher_traps(jitdata *jd)
265 /* get required compiler data */
270 /* generate patcher traps code */
272 for (pr = list_first_unsynced(code->patchers); pr != NULL; pr = list_next_unsynced(code->patchers, pr)) {
274 /* Calculate the patch position where the original machine
275 code is located and the trap should be placed. */
277 tmpmcodeptr = (u1 *) (cd->mcodebase + pr->mpc);
279 /* Patch in the trap to call the signal handler (done at
282 savedmcodeptr = cd->mcodeptr; /* save current mcodeptr */
283 cd->mcodeptr = tmpmcodeptr; /* set mcodeptr to patch position */
285 mcode = emit_trap(cd);
287 cd->mcodeptr = savedmcodeptr; /* restore the current mcodeptr */
289 /* Remember the original machine code which is patched
290 back in later (done at runtime). */
297 /* emit_bccz *******************************************************************
299 Emit conditional and unconditional branch instructions on integer
302 *******************************************************************************/
304 void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options)
309 /* Target basic block already has an PC, so we can generate the
310 branch immediately. */
312 if ((target->mpc >= 0)) {
313 STATISTICS(count_branches_resolved++);
315 /* calculate the mpc of the branch instruction */
317 branchmpc = cd->mcodeptr - cd->mcodebase;
318 disp = target->mpc - branchmpc;
320 #if defined(ENABLE_STATISTICS)
322 if ((int8_t)disp == disp) count_emit_branch_8bit++;
323 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
324 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
325 # if SIZEOF_VOID_P == 8
326 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
330 emit_branch(cd, disp, condition, reg, options);
333 /* current mcodeptr is the correct position,
334 afterwards emit the NOPs */
336 codegen_add_branch_ref(cd, target, condition, reg, options);
338 /* generate NOPs as placeholder for branch code */
345 /* emit_bcc ********************************************************************
347 Emit conditional and unconditional branch instructions on condition
350 *******************************************************************************/
352 void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options)
354 emit_bccz(cd, target, condition, -1, options);
358 /* emit_br *********************************************************************
360 Wrapper for unconditional branches.
362 *******************************************************************************/
364 void emit_br(codegendata *cd, basicblock *target)
366 emit_bcc(cd, target, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
370 /* emit_bxxz *******************************************************************
372 Wrappers for branches on one integer register.
374 *******************************************************************************/
376 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
378 void emit_beqz(codegendata *cd, basicblock *target, s4 reg)
380 emit_bccz(cd, target, BRANCH_EQ, reg, BRANCH_OPT_NONE);
383 void emit_bnez(codegendata *cd, basicblock *target, s4 reg)
385 emit_bccz(cd, target, BRANCH_NE, reg, BRANCH_OPT_NONE);
388 void emit_bltz(codegendata *cd, basicblock *target, s4 reg)
390 emit_bccz(cd, target, BRANCH_LT, reg, BRANCH_OPT_NONE);
393 void emit_bgez(codegendata *cd, basicblock *target, s4 reg)
395 emit_bccz(cd, target, BRANCH_GE, reg, BRANCH_OPT_NONE);
398 void emit_bgtz(codegendata *cd, basicblock *target, s4 reg)
400 emit_bccz(cd, target, BRANCH_GT, reg, BRANCH_OPT_NONE);
403 void emit_blez(codegendata *cd, basicblock *target, s4 reg)
405 emit_bccz(cd, target, BRANCH_LE, reg, BRANCH_OPT_NONE);
408 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
411 /* emit_bxx ********************************************************************
413 Wrappers for branches on two integer registers.
415 We use PACK_REGS here, so we don't have to change the branchref
416 data structure and the emit_bccz function.
418 *******************************************************************************/
420 #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS
422 void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2)
424 emit_bccz(cd, target, BRANCH_EQ, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
427 void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2)
429 emit_bccz(cd, target, BRANCH_NE, PACK_REGS(s1, s2), BRANCH_OPT_NONE);
432 #endif /* SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS */
435 /* emit_bxx ********************************************************************
437 Wrappers for branches on condition codes.
439 *******************************************************************************/
441 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
443 void emit_beq(codegendata *cd, basicblock *target)
445 emit_bcc(cd, target, BRANCH_EQ, BRANCH_OPT_NONE);
448 void emit_bne(codegendata *cd, basicblock *target)
450 emit_bcc(cd, target, BRANCH_NE, BRANCH_OPT_NONE);
453 void emit_blt(codegendata *cd, basicblock *target)
455 emit_bcc(cd, target, BRANCH_LT, BRANCH_OPT_NONE);
458 void emit_bge(codegendata *cd, basicblock *target)
460 emit_bcc(cd, target, BRANCH_GE, BRANCH_OPT_NONE);
463 void emit_bgt(codegendata *cd, basicblock *target)
465 emit_bcc(cd, target, BRANCH_GT, BRANCH_OPT_NONE);
468 void emit_ble(codegendata *cd, basicblock *target)
470 emit_bcc(cd, target, BRANCH_LE, BRANCH_OPT_NONE);
473 #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS
474 void emit_bult(codegendata *cd, basicblock *target)
476 emit_bcc(cd, target, BRANCH_ULT, BRANCH_OPT_NONE);
479 void emit_bule(codegendata *cd, basicblock *target)
481 emit_bcc(cd, target, BRANCH_ULE, BRANCH_OPT_NONE);
484 void emit_buge(codegendata *cd, basicblock *target)
486 emit_bcc(cd, target, BRANCH_UGE, BRANCH_OPT_NONE);
489 void emit_bugt(codegendata *cd, basicblock *target)
491 emit_bcc(cd, target, BRANCH_UGT, BRANCH_OPT_NONE);
495 #if defined(__POWERPC__) || defined(__POWERPC64__)
496 void emit_bnan(codegendata *cd, basicblock *target)
498 emit_bcc(cd, target, BRANCH_NAN, BRANCH_OPT_NONE);
502 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
505 /* emit_label_bccz *************************************************************
507 Emit a branch to a label. Possibly emit the branch, if it is a
510 *******************************************************************************/
512 void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options)
515 branch_label_ref_t *br;
519 /* get the label list */
521 list = cd->brancheslabel;
523 /* search if the label is already in the list */
525 for (br = list_first_unsynced(list); br != NULL;
526 br = list_next_unsynced(list, br)) {
527 /* is this entry the correct label? */
529 if (br->label == label)
533 /* a branch reference was found */
536 /* calculate the mpc of the branch instruction */
538 mpc = cd->mcodeptr - cd->mcodebase;
539 disp = br->mpc - mpc;
541 #if defined(ENABLE_STATISTICS)
543 if ((int8_t)disp == disp) count_emit_branch_8bit++;
544 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
545 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
546 # if SIZEOF_VOID_P == 8
547 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
551 emit_branch(cd, disp, condition, reg, options);
553 /* now remove the branch reference */
555 list_remove_unsynced(list, br);
558 /* current mcodeptr is the correct position,
559 afterwards emit the NOPs */
561 codegen_branch_label_add(cd, label, condition, reg, options);
563 /* generate NOPs as placeholder for branch code */
570 /* emit_label ******************************************************************
572 Emit a label for a branch. Possibly emit the branch, if it is a
575 *******************************************************************************/
577 void emit_label(codegendata *cd, s4 label)
580 branch_label_ref_t *br;
585 /* get the label list */
587 list = cd->brancheslabel;
589 /* search if the label is already in the list */
591 for (br = list_first_unsynced(list); br != NULL;
592 br = list_next_unsynced(list, br)) {
593 /* is this entry the correct label? */
595 if (br->label == label)
599 /* a branch reference was found */
602 /* calculate the mpc of the branch instruction */
604 mpc = cd->mcodeptr - cd->mcodebase;
605 disp = mpc - br->mpc;
607 /* temporary set the mcodeptr */
609 mcodeptr = cd->mcodeptr;
610 cd->mcodeptr = cd->mcodebase + br->mpc;
612 #if defined(ENABLE_STATISTICS)
614 if ((int8_t)disp == disp) count_emit_branch_8bit++;
615 else if ((int16_t)disp == disp) count_emit_branch_16bit++;
616 else if ((int32_t)disp == disp) count_emit_branch_32bit++;
617 # if SIZEOF_VOID_P == 8
618 else if ((int64_t)disp == disp) count_emit_branch_64bit++;
622 emit_branch(cd, disp, br->condition, br->reg, br->options);
624 /* restore mcodeptr */
626 cd->mcodeptr = mcodeptr;
628 /* now remove the branch reference */
630 list_remove_unsynced(list, br);
633 /* add the label to the list (use invalid values for condition
636 codegen_branch_label_add(cd, label, -1, -1, BRANCH_OPT_NONE );
641 /* emit_label_bcc **************************************************************
643 Emit conditional and unconditional label-branch instructions on
646 *******************************************************************************/
648 void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options)
650 emit_label_bccz(cd, label, condition, -1, options);
654 /* emit_label_br ***************************************************************
656 Wrapper for unconditional label-branches.
658 *******************************************************************************/
660 void emit_label_br(codegendata *cd, s4 label)
662 emit_label_bcc(cd, label, BRANCH_UNCONDITIONAL, BRANCH_OPT_NONE);
666 /* emit_label_bxxz *************************************************************
668 Wrappers for label-branches on one integer register.
670 *******************************************************************************/
672 #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER
674 void emit_label_beqz(codegendata *cd, s4 label, s4 reg)
676 emit_label_bccz(cd, label, BRANCH_EQ, reg, BRANCH_OPT_NONE);
679 #endif /* SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER */
682 /* emit_label_bxx **************************************************************
684 Wrappers for label-branches on condition codes.
686 *******************************************************************************/
688 #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER
690 void emit_label_beq(codegendata *cd, s4 label)
692 emit_label_bcc(cd, label, BRANCH_EQ, BRANCH_OPT_NONE);
695 void emit_label_bne(codegendata *cd, s4 label)
697 emit_label_bcc(cd, label, BRANCH_NE, BRANCH_OPT_NONE);
700 void emit_label_blt(codegendata *cd, s4 label)
702 emit_label_bcc(cd, label, BRANCH_LT, BRANCH_OPT_NONE);
705 void emit_label_bge(codegendata *cd, s4 label)
707 emit_label_bcc(cd, label, BRANCH_GE, BRANCH_OPT_NONE);
710 void emit_label_bgt(codegendata *cd, s4 label)
712 emit_label_bcc(cd, label, BRANCH_GT, BRANCH_OPT_NONE);
715 void emit_label_ble(codegendata *cd, s4 label)
717 emit_label_bcc(cd, label, BRANCH_LE, BRANCH_OPT_NONE);
720 #endif /* SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER */
724 * These are local overrides for various environment variables in Emacs.
725 * Please do not remove this and leave it at the end of the file, where
726 * Emacs will automagically detect them.
727 * ---------------------------------------------------------------------
730 * indent-tabs-mode: t
734 * vim:noexpandtab:sw=4:ts=4: