/* src/vm/jit/emit-common.hpp - common code emitter functions Copyright (C) 2006, 2007, 2008, 2009 CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO Copyright (C) 2009 Theobroma Systems Ltd. This file is part of CACAO. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _EMIT_COMMON_HPP #define _EMIT_COMMON_HPP #include "config.h" #include "vm/types.h" #include "arch.h" #include "codegen.h" #include "vm/jit/codegen-common.hpp" #include "vm/jit/jit.hpp" /* branch labels **************************************************************/ #define BRANCH_LABEL_1 1 #define BRANCH_LABEL_2 2 #define BRANCH_LABEL_3 3 #define BRANCH_LABEL_4 4 #define BRANCH_LABEL_5 5 #define BRANCH_LABEL_6 6 #define BRANCH_LABEL_7 7 #define BRANCH_LABEL_8 8 #define BRANCH_LABEL_9 9 #define BRANCH_LABEL_10 10 /* constant range macros ******************************************************/ #if SIZEOF_VOID_P == 8 # define IS_IMM8(c) \ (((s8) (c) >= -128) && ((s8) (c) <= 127)) # define IS_IMM32(c) \ (((s8) (c) >= (-2147483647-1)) && ((s8) (c) <= 2147483647)) #else # define IS_IMM8(c) \ (((s4) (c) >= -128) && ((s4) (c) <= 127)) # define IS_IMM16(c) \ (((s4) (c) >= -32768) && ((s4) (c) <= 32767)) #endif /* code generation functions **************************************************/ #ifdef __cplusplus extern "C" { #endif s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg); s4 emit_load_s1(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s2(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s3(jitdata *jd, instruction *iptr, s4 tempreg); #if SIZEOF_VOID_P == 4 s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg); s4 emit_load_s1_low(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s2_low(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s3_low(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg); s4 emit_load_s1_high(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s2_high(jitdata *jd, instruction *iptr, s4 tempreg); s4 emit_load_s3_high(jitdata *jd, instruction *iptr, s4 tempreg); #endif void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d); void emit_store_dst(jitdata *jd, instruction *iptr, s4 d); #if SIZEOF_VOID_P == 4 void emit_store_low(jitdata *jd, instruction *iptr, varinfo *dst, s4 d); void emit_store_high(jitdata *jd, instruction *iptr, varinfo *dst, s4 d); #endif void emit_copy(jitdata *jd, instruction *iptr); void emit_iconst(codegendata *cd, s4 d, s4 value); void emit_lconst(codegendata *cd, s4 d, s8 value); /* compare-emitting functions targeting an integer register */ #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER void emit_icmpeq_imm(codegendata* cd, int reg, int32_t value, int d); #endif /* compare-emitting functions targeting the condition register */ #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER void emit_icmp_imm(codegendata* cd, int reg, int32_t value); #endif /* branch-emitting functions */ void emit_bccz(codegendata *cd, basicblock *target, s4 condition, s4 reg, u4 options); void emit_bcc(codegendata *cd, basicblock *target, s4 condition, u4 options); /* wrapper for unconditional branches */ void emit_br(codegendata *cd, basicblock *target); /* wrappers for branches on one integer register */ #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER void emit_beqz(codegendata *cd, basicblock *target, s4 reg); void emit_bnez(codegendata *cd, basicblock *target, s4 reg); void emit_bltz(codegendata *cd, basicblock *target, s4 reg); void emit_bgez(codegendata *cd, basicblock *target, s4 reg); void emit_bgtz(codegendata *cd, basicblock *target, s4 reg); void emit_blez(codegendata *cd, basicblock *target, s4 reg); #endif /* wrappers for branches on two integer registers */ #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS void emit_beq(codegendata *cd, basicblock *target, s4 s1, s4 s2); void emit_bne(codegendata *cd, basicblock *target, s4 s1, s4 s2); #endif /* wrappers for branches on condition codes */ #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER void emit_beq(codegendata *cd, basicblock *target); void emit_bne(codegendata *cd, basicblock *target); void emit_blt(codegendata *cd, basicblock *target); void emit_bge(codegendata *cd, basicblock *target); void emit_bgt(codegendata *cd, basicblock *target); void emit_ble(codegendata *cd, basicblock *target); #endif #if SUPPORT_BRANCH_CONDITIONAL_UNSIGNED_CONDITIONS void emit_bult(codegendata *cd, basicblock *target); void emit_bule(codegendata *cd, basicblock *target); void emit_buge(codegendata *cd, basicblock *target); void emit_bugt(codegendata *cd, basicblock *target); #endif #if defined(__POWERPC__) || defined(__POWERPC64__) void emit_bnan(codegendata *cd, basicblock *target); #endif /* label-branches */ void emit_label_bccz(codegendata *cd, s4 label, s4 condition, s4 reg, u4 options); void emit_label(codegendata *cd, s4 label); void emit_label_bcc(codegendata *cd, s4 label, s4 condition, u4 options); void emit_label_br(codegendata *cd, s4 label); #if SUPPORT_BRANCH_CONDITIONAL_ONE_INTEGER_REGISTER void emit_label_beqz(codegendata* cd, int label, int reg); void emit_label_bnez(codegendata* cd, int label, int reg); void emit_label_bltz(codegendata* cd, int label, int reg); void emit_label_bgtz(codegendata* cd, int label, int reg); #endif #if SUPPORT_BRANCH_CONDITIONAL_TWO_INTEGER_REGISTERS void emit_label_beq(codegendata* cd, int label, int s1, int s2); void emit_label_bne(codegendata* cd, int label, int s1, int s2); #endif #if SUPPORT_BRANCH_CONDITIONAL_CONDITION_REGISTER void emit_label_beq(codegendata *cd, s4 label); void emit_label_bne(codegendata *cd, s4 label); void emit_label_blt(codegendata *cd, s4 label); void emit_label_bge(codegendata *cd, s4 label); void emit_label_bgt(codegendata *cd, s4 label); void emit_label_ble(codegendata *cd, s4 label); #endif /* machine dependent branch-emitting function */ void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options); void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg); void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2); void emit_arraystore_check(codegendata *cd, instruction *iptr); void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1); void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg); void emit_exception_check(codegendata *cd, instruction *iptr); void emit_trap_compiler(codegendata *cd); void emit_trap_countdown(codegendata *cd, s4 *counter); uint32_t emit_trap(codegendata *cd); void emit_patcher_traps(jitdata *jd); void emit_recompute_pv(codegendata* cd); /* machine dependent faspath-emitting functions */ void emit_fastpath_monitor_enter(jitdata* jd, instruction* iptr, int d); void emit_fastpath_monitor_exit(jitdata* jd, instruction* iptr, int d); #if defined(ENABLE_THREADS) void emit_monitor_enter(jitdata* jd, int32_t syncslot_offset); void emit_monitor_exit(jitdata* jd, int32_t syncslot_offset); #endif #if defined(ENABLE_PROFILING) void emit_profile_method(codegendata* cd, codeinfo* code); void emit_profile_basicblock(codegendata* cd, codeinfo* code, basicblock* bptr); void emit_profile_cycle_start(codegendata* cd, codeinfo* code); void emit_profile_cycle_stop(codegendata* cd, codeinfo* code); #endif void emit_verbosecall_enter(jitdata *jd); void emit_verbosecall_exit(jitdata *jd); #ifdef __cplusplus } #endif /* inline code generation functions *******************************************/ /** * Generates an integer-move from register s to d. If s and d are * the same registers, no code will be generated. */ static inline void emit_imove(codegendata* cd, int s, int d) { if (s != d) #if defined(__ARM__) // XXX Fix this!!! M_MOV(d, s); #else M_MOV(s, d); #endif } /** * Generates a long-move from register s to d. If s and d are * the same registers, no code will be generated. */ static inline void emit_lmove(codegendata* cd, int s, int d) { #if SIZEOF_VOID_P == 8 emit_imove(cd, s, d); #else if (GET_HIGH_REG(s) == GET_LOW_REG(d)) { assert((GET_LOW_REG(s) != GET_HIGH_REG(d))); emit_imove(cd, GET_HIGH_REG(s), GET_HIGH_REG(d)); emit_imove(cd, GET_LOW_REG(s), GET_LOW_REG(d)); } else { emit_imove(cd, GET_LOW_REG(s), GET_LOW_REG(d)); emit_imove(cd, GET_HIGH_REG(s), GET_HIGH_REG(d)); } #endif } /** * Generates a float-move from register s to d. If s and d are * the same registers, no code will be generated. */ static inline void emit_fmove(codegendata* cd, int s, int d) { if (s != d) M_FMOV(s, d); } /** * Generates an double-move from register s to d. If s and d are * the same registers, no code will be generated. */ static inline void emit_dmove(codegendata* cd, int s, int d) { if (s != d) M_DMOV(s, d); } /* preserve compatibility with legacy code ************************************/ #define M_INTMOVE(a, b) emit_imove(cd, a, b) #define M_LNGMOVE(a, b) emit_lmove(cd, a, b) #define M_FLTMOVE(a, b) emit_fmove(cd, a, b) #define M_DBLMOVE(a, b) emit_dmove(cd, a, b) #endif /* _EMIT_COMMON_HPP */ /* * These are local overrides for various environment variables in Emacs. * Please do not remove this and leave it at the end of the file, where * Emacs will automagically detect them. * --------------------------------------------------------------------- * Local variables: * mode: c * indent-tabs-mode: t * c-basic-offset: 4 * tab-width: 4 * End: * vim:noexpandtab:sw=4:ts=4: */