X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=src%2Fvm%2Fjit%2Falpha%2Fmd.c;h=c3b6457fc132603f555b0da74aab0e2b2ba8045c;hb=1deac13e9bc6f4db546f48a5c9e0b2c4d6857740;hp=e883f4757c8518c3280f2def37f33d7ae304bbca;hpb=943d084d7aabf457aefff2a693dcaf65c029cea9;p=cacao.git diff --git a/src/vm/jit/alpha/md.c b/src/vm/jit/alpha/md.c index e883f4757..c3b6457fc 100644 --- a/src/vm/jit/alpha/md.c +++ b/src/vm/jit/alpha/md.c @@ -1,9 +1,9 @@ /* src/vm/jit/alpha/md.c - machine dependent Alpha functions - Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates, - R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner, - C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger, - Institut f. Computersprachen - TU Wien + Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel, + C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring, + E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, + J. Wenninger, Institut f. Computersprachen - TU Wien This file is part of CACAO. @@ -19,112 +19,354 @@ 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., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. - Contact: cacao@complang.tuwien.ac.at + Contact: cacao@cacaojvm.org Authors: Andreas Krall Reinhard Grafl - - Changes: Joseph Wenninger + Joseph Wenninger Christian Thalinger + Edwin Steiner - $Id: md.c 2804 2005-06-23 13:40:41Z twisti $ + $Id: md.c 6265 2007-01-02 20:40:57Z edwin $ */ +#include "config.h" + +#include #include -#include "config.h" +#if defined(__LINUX__) +# include + +extern unsigned long ieee_get_fp_control(); +extern void ieee_set_fp_control(unsigned long fp_control); +#endif + +#include "vm/types.h" + #include "vm/jit/alpha/md-abi.h" -#include "vm/jit/alpha/types.h" #include "vm/exceptions.h" #include "vm/stringlocal.h" #include "vm/jit/asmpart.h" +#include "vm/jit/stacktrace.h" + +#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) +#include "vm/options.h" /* XXX debug */ +#include "vm/jit/disass.h" /* XXX debug */ +#endif + + +/* global variables ***********************************************************/ + +bool has_ext_instr_set = false; /* has instruction set extensions */ + + +/* md_init ********************************************************************* + + Do some machine dependent initialization. + +*******************************************************************************/ + +void md_init(void) +{ + /* check for extended instruction set */ + + has_ext_instr_set = !asm_md_init(); + +#if defined(__LINUX__) + /* Linux on Digital Alpha needs an initialisation of the ieee + floating point control for IEEE compliant arithmetic (option + -mieee of GCC). Under Digital Unix this is done + automatically. */ + + /* initialize floating point control */ + + ieee_set_fp_control(ieee_get_fp_control() + & ~IEEE_TRAP_ENABLE_INV + & ~IEEE_TRAP_ENABLE_DZE +/* & ~IEEE_TRAP_ENABLE_UNF we dont want underflow */ + & ~IEEE_TRAP_ENABLE_OVF); +#endif +} -/* signal_handler_sigsegv ****************************************************** +/* md_codegen_patch_branch ***************************************************** - NullPointerException signal handler for hardware null pointer check. + Back-patches a branch instruction. *******************************************************************************/ -void signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p) +void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc) { - ucontext_t *_uc; - mcontext_t *_mc; - u4 instr; - ptrint addr; + s4 *mcodeptr; + s4 mcode; + s4 disp; /* branch displacement */ + + /* calculate the patch position */ + + mcodeptr = (s4 *) (cd->mcodebase + branchmpc); + + /* get the instruction before the exception point */ + + mcode = mcodeptr[-1]; + + /* Calculate the branch displacement. For branches we need a + displacement relative and shifted to the branch PC. */ + + disp = (targetmpc - branchmpc) >> 2; + + /* check branch displacement */ + + if ((disp < (s4) 0xffe00000) || (disp > (s4) 0x001fffff)) + vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x001fffff); + + /* patch the branch instruction before the mcodeptr */ + + mcodeptr[-1] |= (disp & 0x001fffff); +} + + +/* md_stacktrace_get_returnaddress ********************************************* + + Returns the return address of the current stackframe, specified by + the passed stack pointer and the stack frame size. + +*******************************************************************************/ + +u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize) +{ + u1 *ra; + + /* on Alpha the return address is located on the top of the stackframe */ + + ra = *((u1 **) (sp + framesize - SIZEOF_VOID_P)); + + return ra; +} + + +/* md_get_method_patch_address ************************************************* + + Gets the patch address of the currently compiled method. The offset + is extracted from the load instruction(s) before the jump and added + to the right base address (PV or REG_METHODPTR). + + INVOKESTATIC/SPECIAL: + + a77bffb8 ldq pv,-72(pv) + 6b5b4000 jsr (pv) + + INVOKEVIRTUAL: + + a7900000 ldq at,0(a0) + a77c0000 ldq pv,0(at) + 6b5b4000 jsr (pv) + + INVOKEINTERFACE: + + a7900000 ldq at,0(a0) + a79cff98 ldq at,-104(at) + a77c0018 ldq pv,24(at) + 6b5b4000 jsr (pv) + +*******************************************************************************/ + +u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr) +{ + u4 mcode; + s4 offset; + u1 *pa; /* patch address */ + + /* go back to the actual load instruction (2 instructions on Alpha) */ + + ra = ra - 2 * 4; - _uc = (ucontext_t *) _p; - _mc = &_uc->uc_mcontext; + /* get first instruction word on current PC */ - instr = *((s4 *) (_mc->sc_pc)); - addr = _mc->sc_regs[(instr >> 16) & 0x1f]; + mcode = *((u4 *) ra); - if (addr == 0) { - _mc->sc_regs[REG_ITMP1_XPTR] = - (ptrint) string_java_lang_NullPointerException; + /* check if we have 2 instructions (lui) */ - _mc->sc_regs[REG_ITMP2_XPC] = _mc->sc_pc; - _mc->sc_pc = (ptrint) asm_throw_and_handle_exception; + if ((mcode >> 16) == 0x3c19) { + /* XXX write a regression for this */ + assert(0); + + /* get displacement of first instruction (lui) */ + + offset = (s4) (mcode << 16); + + /* get displacement of second instruction (daddiu) */ + + mcode = *((u4 *) (ra + 1 * 4)); + + assert((mcode >> 16) == 0x6739); + + offset += (s2) (mcode & 0x0000ffff); } else { - addr += (long) ((instr << 16) >> 16); + /* get first instruction (ldq) */ + + mcode = *((u4 *) ra); + + /* get the offset from the instruction */ + + offset = (s2) (mcode & 0x0000ffff); - throw_cacao_exception_exit(string_java_lang_InternalError, - "faulting address: 0x%016lx\n", addr); + /* check for call with REG_METHODPTR: ldq pv,0(at) */ + + if ((mcode >> 16) == 0xa77c) { + /* in this case we use the passed method pointer */ + + /* return NULL if no mptr was specified (used for replacement) */ + + if (mptr == NULL) + return NULL; + + pa = mptr + offset; + + } else { + /* in the normal case we check for a `ldq pv,-72(pv)' instruction */ + + assert((mcode >> 16) == 0xa77b); + + /* and get the final data segment address */ + + pa = sfi->pv + offset; + } } + + return pa; } -#if 0 -#if defined(__OSF__) -void init_exceptions(void) +/* md_codegen_get_pv_from_pc *************************************************** + + Machine code: + + 6b5b4000 jsr (pv) + 277afffe ldah pv,-2(ra) + 237ba61c lda pv,-23012(pv) + +*******************************************************************************/ + +u1 *md_codegen_get_pv_from_pc(u1 *ra) { + u1 *pv; + u4 mcode; + s4 offset; -#else /* Linux */ + pv = ra; -/* Linux on Digital Alpha needs an initialisation of the ieee floating point - control for IEEE compliant arithmetic (option -mieee of GCC). Under - Digital Unix this is done automatically. -*/ + /* get first instruction word after jump */ -#include + mcode = *((u4 *) ra); -extern unsigned long ieee_get_fp_control(); -extern void ieee_set_fp_control(unsigned long fp_control); + /* check if we have 2 instructions (ldah, lda) */ -void init_exceptions(void) -{ - /* initialize floating point control */ + if ((mcode >> 16) == 0x277a) { + /* get displacement of first instruction (ldah) */ - ieee_set_fp_control(ieee_get_fp_control() - & ~IEEE_TRAP_ENABLE_INV - & ~IEEE_TRAP_ENABLE_DZE -/* & ~IEEE_TRAP_ENABLE_UNF we dont want underflow */ - & ~IEEE_TRAP_ENABLE_OVF); -#endif + offset = (s4) (mcode << 16); + pv += offset; + + /* get displacement of second instruction (lda) */ + + mcode = *((u4 *) (ra + 1 * 4)); + + assert((mcode >> 16) == 0x237b); + + offset = (s2) (mcode & 0x0000ffff); + pv += offset; + } + else { + /* get displacement of first instruction (lda) */ + + assert((mcode >> 16) == 0x237a); + + offset = (s2) (mcode & 0x0000ffff); + pv += offset; + } + + return pv; } -#endif -#if defined(USE_THREADS) && defined(NATIVE_THREADS) -void thread_restartcriticalsection(ucontext_t *uc) +/* md_cacheflush *************************************************************** + + Calls the system's function to flush the instruction and data + cache. + +*******************************************************************************/ + +void md_cacheflush(u1 *addr, s4 nbytes) { - void *critical; + asm_cacheflush(addr, nbytes); +} - critical = thread_checkcritical((void *) uc->uc_mcontext.sc_pc); - if (critical) - uc->uc_mcontext.sc_pc = (ptrint) critical; +/* md_icacheflush ************************************************************** + + Calls the system's function to flush the instruction cache. + +*******************************************************************************/ + +void md_icacheflush(u1 *addr, s4 nbytes) +{ + asm_cacheflush(addr, nbytes); } -#endif +/* md_patch_replacement_point ************************************************** + + Patch the given replacement point. + +*******************************************************************************/ + +#if defined(ENABLE_REPLACEMENT) +void md_patch_replacement_point(codeinfo *code, s4 index, rplpoint *rp, u1 *savedmcode) +{ + s4 disp; + u4 mcode; + + if (index < 0) { + /* restore the patched-over instruction */ + *(u4*)(rp->pc) = *(u4*)(savedmcode); + } + else { + /* save the current machine code */ + *(u4*)(savedmcode) = *(u4*)(rp->pc); + + /* build the machine code for the patch */ + disp = ((u4*)code->replacementstubs - (u4*)rp->pc) + + index * REPLACEMENT_STUB_SIZE + - 1; + + /* BR */ + mcode = (((s4) (0x30)) << 26) | ((REG_ZERO) << 21) | ((disp) & 0x1fffff); + + /* write the new machine code */ + *(u4*)(rp->pc) = mcode; + } + +#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) && 0 + { + u1* u1ptr = rp->pc; + DISASSINSTR(u1ptr); + fflush(stdout); + } +#endif + + /* flush instruction cache */ + md_icacheflush(rp->pc,4); +} +#endif /* defined(ENABLE_REPLACEMENT) */ + /* * 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 @@ -136,4 +378,5 @@ void thread_restartcriticalsection(ucontext_t *uc) * c-basic-offset: 4 * tab-width: 4 * End: + * vim:noexpandtab:sw=4:ts=4: */