* Removed all Id tags.
[cacao.git] / src / vm / jit / i386 / md.c
index 07328061a21feded02a0c1d7927ffed401e76587..4b98f219198c95ab0f9647b9b07be1985c66f44a 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/i386/md.c - machine dependent i386 functions
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 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
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Christian Thalinger
-
-   Changes: Edwin Steiner
-
-   $Id: md.c 4613 2006-03-15 12:04:05Z edwin $
-
 */
 
 
 #include "config.h"
-#include "vm/types.h"
 
 #include <assert.h>
 
+#include "vm/types.h"
+
 #include "vm/global.h"
+
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
-#include "vm/options.h" /* XXX debug */
+#include "vm/jit/md.h"
+
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
+#include "vmcore/options.h" /* XXX debug */
 #include "vm/jit/disass.h" /* XXX debug */
+#endif
 
 
 /* md_init *********************************************************************
@@ -76,59 +74,194 @@ u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
 }
 
 
-/* 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).
 
-   On this architecture just a wrapper function to codegen_findmethod.
+   INVOKESTATIC/SPECIAL:
+
+   b9 30 00 49 b7             mov    $0xb7490030,%ecx
+   ff d1                      call   *%ecx
+
+   INVOKEVIRTUAL:
+
+   8b 08                      mov    (%eax),%ecx
+   8b 91 00 00 00 00          mov    0x0(%ecx),%edx
+   ff d2                      call   *%edx
+
+   INVOKEINTERFACE:
+
+   8b 08                      mov    (%eax),%ecx
+   8b 89 00 00 00 00          mov    0x0(%ecx),%ecx
+   8b 91 00 00 00 00          mov    0x0(%ecx),%edx
+   ff d2                      call   *%edx
 
 *******************************************************************************/
 
-u1 *md_codegen_findmethod(u1 *ra)
+u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
+{
+       u1  mcode;
+       s4  offset;
+       u1 *pa;                             /* patch address                      */
+
+       /* go back to the actual call instruction (2-bytes) */
+
+       ra = ra - 2;
+
+       /* get the last byte of the call */
+
+       mcode = ra[1];
+
+       /* check for the different calls */
+
+       if (mcode == 0xd1) {
+               /* INVOKESTATIC/SPECIAL */
+
+               /* patch address is 4-bytes before the call instruction */
+
+               pa = ra - 4;
+       }
+       else if (mcode == 0xd2) {
+               /* INVOKEVIRTUAL/INTERFACE */
+
+               /* return NULL if no mptr was specified (used for replacement) */
+
+               if (mptr == NULL)
+                       return NULL;
+
+               /* Get the offset from the instruction (the offset address is
+                  4-bytes before the call instruction). */
+
+               offset = *((s4 *) (ra - 4));
+
+               /* add the offset to the method pointer */
+
+               pa = mptr + offset;
+       }
+       else {
+               /* catch any problems */
+
+               pa = NULL; /* avoid warnings */
+
+               vm_abort("couldn't find a proper call instruction sequence");
+       }
+
+       return pa;
+}
+
+
+/* md_codegen_get_pv_from_pc ***************************************************
+
+   On this architecture just a wrapper function to
+   codegen_get_pv_from_pc.
+
+*******************************************************************************/
+
+u1 *md_codegen_get_pv_from_pc(u1 *ra)
 {
        u1 *pv;
 
-       /* the the start address of the function which contains this
-       address from the method table */
+       /* Get the start address of the function which contains this
+       address from the method table. */
 
-       pv = codegen_findmethod(ra);
+       pv = codegen_get_pv_from_pc(ra);
 
        return pv;
 }
 
+
+/* md_cacheflush ***************************************************************
+
+   Calls the system's function to flush the instruction and data
+   cache.
+
+*******************************************************************************/
+
+void md_cacheflush(u1 *addr, s4 nbytes)
+{
+       /* do nothing */
+}
+
+
+/* md_icacheflush **************************************************************
+
+   Calls the system's function to flush the instruction cache.
+
+*******************************************************************************/
+
+void md_icacheflush(u1 *addr, s4 nbytes)
+{
+       /* do nothing */
+}
+
+
+/* md_dcacheflush **************************************************************
+
+   Calls the system's function to flush the data cache.
+
+*******************************************************************************/
+
+void md_dcacheflush(u1 *addr, s4 nbytes)
+{
+       /* do nothing */
+}
+
+
 /* md_patch_replacement_point **************************************************
 
    Patch the given replacement point.
 
 *******************************************************************************/
 
-void md_patch_replacement_point(rplpoint *rp)
+#if defined(ENABLE_REPLACEMENT)
+void md_patch_replacement_point(codeinfo *code, s4 index, rplpoint *rp, u1 *savedmcode)
 {
-    u8 mcode;
+       u8 mcode;
 
        /* XXX this is probably unsafe! */
 
-       /* save the current machine code */
-       mcode = *(u8*)rp->pc;
+       if (index < 0) {
+               /* write spinning instruction */
+               *(u2*)(rp->pc) = 0xebfe;
 
-       /* write spinning instruction */
-       *(u2*)(rp->pc) = 0xebfe;
+               /* write 5th byte */
+               rp->pc[4] = savedmcode[4];
 
-       /* write 5th byte */
-       rp->pc[4] = (rp->mcode >> 32);
+               /* write first word */
+               *(u4*)(rp->pc) = *(u4*)(savedmcode);
+       }
+       else {
+               /* save the current machine code */
+               *(u4*)(savedmcode) = *(u4*)(rp->pc);
+               savedmcode[4] = rp->pc[4];
 
-       /* write first word */
-    *(u4*)(rp->pc) = (u4) rp->mcode;
+               /* build the machine code for the patch */
+               assert(0); /* XXX build trap instruction below */
+               mcode = 0;
+
+               /* write spinning instruction */
+               *(u2*)(rp->pc) = 0xebfe;
+
+               /* write 5th byte */
+               rp->pc[4] = (mcode >> 32);
+
+               /* write first word */
+               *(u4*)(rp->pc) = (u4) mcode;
+       }
 
-       /* store saved mcode */
-       rp->mcode = mcode;
-       
+#if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER) && 0
        {
                u1* u1ptr = rp->pc;
                DISASSINSTR(u1ptr);
                fflush(stdout);
        }
+#endif
                        
     /* XXX if required asm_cacheflush(rp->pc,8); */
 }
+#endif /* defined(ENABLE_REPLACEMENT) */
 
 /*
  * These are local overrides for various environment variables in Emacs.