Authors: Andreas Krall
Reinhard Grafl
-
- Changes: Joseph Wenninger
+ Joseph Wenninger
Christian Thalinger
+ Edwin Steiner
- $Id: md.c 4357 2006-01-22 23:33:38Z twisti $
+ $Id: md.c 5948 2006-11-11 16:56:48Z twisti $
*/
#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 *********************************************************************
void md_init(void)
{
- /* XXX TWISTI: do we really need this? fptest's seem to work fine */
+ /* 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
}
+/* md_codegen_patch_branch *****************************************************
+
+ Back-patches a branch instruction.
+
+*******************************************************************************/
+
+void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
+{
+ 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
}
-/* md_codegen_findmethod *******************************************************
+/* 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;
+
+ /* get first instruction word on current PC */
+
+ mcode = *((u4 *) ra);
+
+ /* check if we have 2 instructions (lui) */
+
+ 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 {
+ /* get first instruction (ldq) */
+
+ mcode = *((u4 *) ra);
+
+ /* get the offset from the instruction */
+
+ offset = (s2) (mcode & 0x0000ffff);
+
+ /* check for call with REG_METHODPTR: ldq pv,0(at) */
+
+ if ((mcode >> 16) == 0xa77c) {
+ /* in this case we use the passed method pointer */
+
+ 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;
+}
+
+
+/* md_codegen_get_pv_from_pc ***************************************************
Machine code:
*******************************************************************************/
-u1 *md_codegen_findmethod(u1 *ra)
+u1 *md_codegen_get_pv_from_pc(u1 *ra)
{
u1 *pv;
u4 mcode;
mcode = *((u4 *) (ra + 1 * 4));
- if ((mcode >> 16) != 0x237b) {
- log_text("No `lda pv,x(pv)' instruction found on return address!");
- assert(0);
- }
+ assert((mcode >> 16) == 0x237b);
offset = (s2) (mcode & 0x0000ffff);
pv += offset;
-
- } else {
+ }
+ else {
/* get displacement of first instruction (lda) */
- if ((mcode >> 16) != 0x237a) {
- log_text("No `lda pv,x(ra)' instruction found on return address!");
- assert(0);
- }
+ assert((mcode >> 16) == 0x237a);
offset = (s2) (mcode & 0x0000ffff);
pv += offset;
}
+/* md_cacheflush ***************************************************************
+
+ Calls the system's function to flush the instruction and data
+ cache.
+
+*******************************************************************************/
+
+void md_cacheflush(u1 *addr, s4 nbytes)
+{
+ asm_cacheflush(addr, nbytes);
+}
+
+
+/* md_icacheflush **************************************************************
+
+ Calls the system's function to flush the instruction cache.
+
+*******************************************************************************/
+
+void md_icacheflush(u1 *addr, s4 nbytes)
+{
+ asm_cacheflush(addr, nbytes);
+}
+
+
+/* md_patch_replacement_point **************************************************
+
+ Patch the given replacement point.
+
+*******************************************************************************/
+
+void md_patch_replacement_point(rplpoint *rp)
+{
+ u8 mcode;
+
+ /* save the current machine code */
+ mcode = *(u4*)rp->pc;
+
+ /* write the new machine code */
+ *(u4*)(rp->pc) = (u4) rp->mcode;
+
+ /* store saved mcode */
+ rp->mcode = mcode;
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+ {
+ u1* u1ptr = rp->pc;
+ DISASSINSTR(u1ptr);
+ fflush(stdout);
+ }
+#endif
+
+ /* flush instruction cache */
+ md_icacheflush(rp->pc,4);
+}
+
/*
* 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
* c-basic-offset: 4
* tab-width: 4
* End:
+ * vim:noexpandtab:sw=4:ts=4:
*/