[kaffe] [PATCH] Add support for AMD64

Gwenole Beauchesne gbeauchesne at mandrakesoft.com
Fri May 16 05:33:01 PDT 2003


Hi,

The original patch was against Kaffe 1.0.7 and was created nearly one year 
ago but I have not sumitted them yet. So, here it is at last. ;-)

I planned to port JIT3 too by I hadn't got enough time recently to do so. 
A few months ago, I implemented a run-time assembler though. It can handle 
both IA-32 and AMD64 architectures with REX prefixes, SSE/SSE2 
instructions.

Bye,
Gwenole.
-------------- next part --------------
2002-08-18  Gwenole Beauchesne  <gbeauchesne at mandrakesoft.com>

	Add support for Linux/AMD64.
	* config/x86_64/common.h: New file.
	* config/x86_64/threads.h: New file.
	* config/x86_64/sysdepCallMethod.h: New file.
	* config/x86_64/linux/config.frag: New file.
	* config/x86_64/linux/md.c: New file.
	* config/x86_64/linux/md.h: New file.

	* config/Makefile.am: Update to add AMD64 files.
	* config/Makefile.in: Likewise.
	
--- kaffe-1.1/config/x86_64/linux/md.c.x86_64	2003-05-16 08:27:48.000000000 -0400
+++ kaffe-1.1/config/x86_64/linux/md.c	2002-08-15 12:43:38.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * x86_64/linux/md.c
+ * Linux X86-64 specific functions.
+ *
+ * Copyright (c) 2002
+ *	MandrakeSoft.  All rights reserved.
+ *
+ * Copyright (C) 2000
+ *  Silicon Graphics, Inc.  All Rights Reserved.
+ *  IA64_context_{save,restore} functions from State Threads Library
+ *
+ * Copyright (c) 2001
+ *	Transvirtual Technologies, Inc.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+#include "config.h"
+#include <stdlib.h>
+
+void
+init_md(void)
+{
+#if defined(M_MMAP_MAX) && defined(HAVE_MALLOPT)
+	mallopt(M_MMAP_MAX, 0);
+#endif
+}
--- kaffe-1.1/config/x86_64/linux/md.h.x86_64	2003-05-16 08:27:48.000000000 -0400
+++ kaffe-1.1/config/x86_64/linux/md.h	2002-08-15 15:18:22.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * x86_64/linux/md.h
+ * Linux X86-64 configuration information.
+ *
+ * Copyright (c) 2002
+ *	MandrakeSoft.  All rights reserved.
+ *
+ * Copyright (c) 2001
+ *	Transvirtual Technologies, Inc.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+#ifndef __x86_64_linux_md_h
+#define __x86_64_linux_md_h
+
+#include "x86_64/common.h"
+#include "x86_64/threads.h"
+
+#if defined(TRANSLATOR)
+#include "jit-md.h"
+#endif
+
+/* Linux requires a little initialisation */
+extern void init_md(void);
+#define	INIT_MD() init_md()
+
+#define SIGNAL_ARGS(sig, scp)           int sig, siginfo_t *sip, struct sigcontext *scp
+#define SIGNAL_CONTEXT_POINTER(scp)     struct sigcontext *scp
+#define GET_SIGNAL_CONTEXT_POINTER(sc)  (sc)
+#define SIGNAL_PC(scp)                  ((scp)->rip)
+
+#endif
--- kaffe-1.1/config/x86_64/linux/config.frag.x86_64	2003-05-16 08:27:48.000000000 -0400
+++ kaffe-1.1/config/x86_64/linux/config.frag	2002-08-16 08:34:04.000000000 -0400
@@ -0,0 +1,10 @@
+#
+# x86-64/Linux configuration
+#
+Khost_cpu=x86_64
+Khost_os=linux
+
+if test x"$with_threads" = x"linux-threads" ; then
+	CPPFLAGS="$CPPFLAGS -D_REENTRANT"
+	VM_LIBS="$VM_LIBS -lpthread"
+fi
--- kaffe-1.1/config/x86_64/common.h.x86_64	2003-05-16 08:27:48.000000000 -0400
+++ kaffe-1.1/config/x86_64/common.h	2002-08-18 04:24:40.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * x86_64/common.h
+ * Common X86-64 configuration information.
+ *
+ * Copyright (c) 2002
+ *	MandrakeSoft.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+#ifndef __x86_64_common_h
+#define __x86_64_common_h
+
+/* Stack must be aligned on 16-bytes boundary.  */
+#define NEED_STACK_ALIGN
+#define STACK_ALIGN(p)  ((((unsigned long)(p)) & 15) ^ (unsigned long)(p))
+
+#if NEED_sysdepCallMethod
+#include "sysdepCallMethod.h"
+#endif
+
+#if defined(__GNUC__)
+#define KAFFE_PROFILER 1
+#endif
+
+#if defined(KAFFE_PROFILER)
+
+/* Profiler clicks counter type.  */
+typedef uint64 profiler_click_t;
+
+/* ReaD the processor Time Stamp Counter.
+ * This is a macro to help GCC optimization.
+ * The rdtsc instruction load TSC to edx:eax aka A register.  */
+#define profiler_get_clicks(COUNTER) \
+        asm volatile ("rdtsc" : "=A" (COUNTER))
+
+#endif
+
+#if defined(__GNUC__)
+/*
+ * Do an atomic compare and exchange.  The address 'A' is checked against  
+ * value 'O' and if they match it's exchanged with value 'N'.
+ * We return '1' if the exchange is sucessful, otherwise 0.
+ */
+#define COMPARE_AND_EXCHANGE(A,O,N)                             \
+        ({ char ret;                                            \
+           asm volatile ("lock ; cmpxchgq %2,%1 ; sete %0"      \
+                         : "=q" (ret), "+m" (*(A))              \
+                         : "r" (N), "a" (O)                     \
+                         : "cc", "memory");                     \
+           (ret);                                               \
+        })
+#endif
+
+#endif
--- kaffe-1.1/config/x86_64/threads.h.x86_64	2003-05-16 08:27:48.000000000 -0400
+++ kaffe-1.1/config/x86_64/threads.h	2002-08-16 08:26:42.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * x86_64/threads.h
+ * X86-64 threading information.
+ *
+ * Copyright (c) 2002
+ *	MandrakeSoft.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+#ifndef __x86_64_threads_h
+#define __x86_64_threads_h
+
+/**/
+/* Thread handling */
+/**/
+#define	USE_INTERNAL_THREADS
+
+/*
+ * Set a default size for the stack.
+ */
+#if defined(INTERPRETER)
+#define THREADSTACKSIZE         (64 * 1024)
+#else
+#define THREADSTACKSIZE         (32 * 1024)
+#endif
+
+/*
+ * Stack offset.
+ * This is the offset into the setjmp buffer where the stack pointer is
+ * stored.  This may be different with different OSes.
+ */
+#define	SP_OFFSET	6
+#define FP_OFFSET	1
+
+#endif
--- kaffe-1.1/config/x86_64/sysdepCallMethod.h.x86_64	2003-05-16 08:27:48.000000000 -0400
+++ kaffe-1.1/config/x86_64/sysdepCallMethod.h	2002-08-15 14:51:17.000000000 -0400
@@ -0,0 +1,227 @@
+/*
+ * x86_64/sysdepCallMethod.h
+ * Dynamically build function calls using X86-64 SVR4 ABI.
+ *
+ * Copyright (c) 2002
+ *	MandrakeSoft.  All rights reserved.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file.
+ */
+
+/* This define will cause callMethodV and callMethodA to avoid
+   introducing unused slots after jlongs and jdoubles.  */
+#ifndef NO_HOLES
+# define NO_HOLES 1
+#endif
+
+/* This define will cause callMethodV and callMethodA to promote every
+   integer type to a 64bit word, and every float to double, so that
+   every value can be loaded as a single 64bit word.  It also causes
+   float arguments to be marked as 'D'.  */
+#ifndef PROMOTE_TO_64bits
+# define PROMOTE_TO_64bits 1
+#endif
+ 
+#ifndef PROMOTE_jfloat2jdouble
+# define PROMOTE_jfloat2jdouble 0
+#endif
+
+/* ARG_TYPE is the type of a register used for passing arguments.  */
+#define ARG_TYPE        long
+
+/* ARG_TYPES is a parameter list declaration for a function type
+   that takes all possible arguments in registers.  */
+#define ARG_TYPES       ARG_TYPE, ARG_TYPE, ARG_TYPE, ARG_TYPE, ARG_TYPE, ARG_TYPE
+
+/* ARG_LIST is the argument list for such a function.  */
+#define ARG_LIST        a0, a1, a2, a3, a4, a5
+
+/* GPR_ARGS is the number of GPR (integer) registers for passing
+   arguments.  */
+#define GPR_ARGS        6
+
+/* FPR_ARGS is the number of FPR (float) registers for passing
+   arguments.  */
+#define FPR_ARGS        8
+
+/* ARG_GPR a case label and a statement that arranges for one integer
+   argument to be passed. */
+#define ARG_GPR(N) \
+    case N+1: a##N = gpr[N];
+
+/* ARG_FPR a case label and a statement that arranges for one float
+   argument to be passed. */
+#define ARG_FPR(N) \
+    case N+1: d##N = fpr[N];
+
+
+/* Make a call to a native or Java (JIT) method.  This assembly code should
+   build a standard C call using the passed call information.  By its
+   nature this is highly processor specific.  This function is mandatory
+   for both JIT and Interpreter (since stubs have now been deprecated).  */
+static inline void sysdepCallMethod(callMethodInfo* call)
+{
+    void *func = call->function;
+    jvalue *callargs = call->args;
+    char *calltype = call->calltype;
+    jvalue *args = callargs;
+    jvalue *last = &callargs[call->nrargs];
+    int nr_gpr = 0;
+    int nr_fpr = 0;
+    int nr_stack = 0;
+
+    unsigned long *stack;
+    unsigned long gpr[GPR_ARGS];
+    double fpr[FPR_ARGS];
+
+    /* Compute gpr[], fpr[] and stack[] arrays' size */
+    while (args != last) {
+      switch (calltype[(args++) - callargs]) {
+      case 'F':
+      case 'D':
+        if (nr_fpr < FPR_ARGS)
+          nr_fpr++;
+        else
+          nr_stack++;
+        break;
+        
+      default:
+        if (nr_gpr < GPR_ARGS)
+          nr_gpr++;
+        else
+          nr_stack++;
+        break;
+      }
+    }
+
+    /* Allocate all arrays with one big alloca() */
+    {
+      int nr = nr_stack;
+      
+      /* stack, if used, must be 16 bytes aligned */
+      if (nr_stack)
+        nr = (nr + 1) & ~1;
+
+      /* stack[] is in called parameters area.  */
+      stack = __builtin_alloca (8 * nr);
+    }
+
+    /* build gpr[], fpr[] and stack[] arrays */
+    nr_gpr = 0;
+    nr_fpr = 0;
+    nr_stack = 0;
+    
+    args = callargs;
+    while (args != last) {
+      switch (calltype[args - callargs]) {
+      case 'F': {
+        if (nr_fpr < FPR_ARGS)
+          /* The value in %xmm register is already prepared to be
+             retrieved as a float. Therefore, we pass the float value
+             verbatim, as a double without any conversion.  */
+          fpr[nr_fpr++] = args->d;
+        else {
+          *(float *)stack = args->f;
+          stack++;
+        }
+        break;
+      }
+      
+      case 'D': {
+        if (nr_fpr < FPR_ARGS)
+          fpr[nr_fpr++] = args->d;
+        else {
+          *(double *)stack = args->d;
+          stack++;
+        }
+        break;
+      }
+      
+      default:
+        if (nr_gpr < GPR_ARGS)
+          gpr[nr_gpr++] = args->j;
+        else
+          *stack++ = args->j;
+      }
+      args++;
+    }
+
+    {
+      register ARG_TYPE a0 asm("rdi");
+      register ARG_TYPE a1 asm("rsi");
+      register ARG_TYPE a2 asm("rdx");
+      register ARG_TYPE a3 asm("rcx");
+      register ARG_TYPE a4 asm("r8");
+      register ARG_TYPE a5 asm("r9");
+      
+      register double d0 asm("xmm0");
+      register double d1 asm("xmm1");
+      register double d2 asm("xmm2");
+      register double d3 asm("xmm3");
+      register double d4 asm("xmm4");
+      register double d5 asm("xmm5");
+      register double d6 asm("xmm6");
+      register double d7 asm("xmm7");
+      
+      /* load FPR registers from fpr[] */
+      switch (nr_fpr) {
+        ARG_FPR(7);
+        ARG_FPR(6);
+        ARG_FPR(5);
+        ARG_FPR(4);
+        ARG_FPR(3);
+        ARG_FPR(2);
+        ARG_FPR(1);
+        ARG_FPR(0);
+      case 0:;
+      }
+
+      /* load GPR registers from gpr[] */
+      switch (nr_gpr) {
+        ARG_GPR(5);
+        ARG_GPR(4);
+        ARG_GPR(3);
+        ARG_GPR(2);
+        ARG_GPR(1);
+        ARG_GPR(0);
+      case 0:;
+      }
+      
+      /* Ensure that the assignments to SSE registers won't be optimized away. */
+      asm ("" ::
+           "x" (d0), "x" (d1), "x" (d2), "x" (d3),
+           "x" (d4), "x" (d5), "x" (d6), "x" (d7));
+
+      switch(call->retsize) {
+      case 0:
+        /* Must be void.  */
+        ((void (*)(ARG_TYPES))(func))(ARG_LIST);
+        break;
+        
+      case 1:
+        if (call->rettype == 'F')
+          call->ret->f = ((jfloat (*)(ARG_TYPES))(func))(ARG_LIST);
+        else /* Must be 32-bit or smaller int.  */
+          call->ret->i = ((jint (*)(ARG_TYPES))(func))(ARG_LIST);
+        break;
+
+      default:
+        /* It could've been `case 2;', but then we'd get an additional cmp
+         * that we don't really need.  */
+        if (call->rettype == 'D')
+          call->ret->d = ((jdouble (*)(ARG_TYPES))(func))(ARG_LIST);
+        else /* Must be jlong.  */
+          call->ret->j = ((jlong (*)(ARG_TYPES))(func))(ARG_LIST);
+        break;
+      }
+    }
+}
+
+#undef ARG_TYPE
+#undef ARG_TYPES
+#undef ARG_LIST
+#undef GPR_ARGS
+#undef FPR_ARGS
+#undef ARG_GPR
+#undef ARG_FPR
--- kaffe-1.1/config/Makefile.am.x86_64	2003-05-14 07:57:43.000000000 -0400
+++ kaffe-1.1/config/Makefile.am	2003-05-16 08:26:59.000000000 -0400
@@ -76,6 +76,12 @@ EXTRA_DIST = \
 	ia64/linux/md.h \
 	ia64/threads.h \
 	ia64/sysdepCallMethod.h \
+	x86_64/common.h \
+	x86_64/linux/config.frag \
+	x86_64/linux/md.c \
+	x86_64/linux/md.h \
+	x86_64/threads.h \
+	x86_64/sysdepCallMethod.h \
 	i386/beos/config.frag \
 	i386/beos/jit-md.h \
 	i386/beos/jit3-md.h \
--- kaffe-1.1/config/Makefile.in.x86_64	2003-05-15 17:15:51.000000000 -0400
+++ kaffe-1.1/config/Makefile.in	2003-05-16 08:26:59.000000000 -0400
@@ -298,6 +298,12 @@ EXTRA_DIST = \
 	ia64/linux/md.h \
 	ia64/threads.h \
 	ia64/sysdepCallMethod.h \
+	x86_64/common.h \
+	x86_64/linux/config.frag \
+	x86_64/linux/md.c \
+	x86_64/linux/md.h \
+	x86_64/threads.h \
+	x86_64/sysdepCallMethod.h \
 	i386/beos/config.frag \
 	i386/beos/jit-md.h \
 	i386/beos/jit3-md.h \


More information about the kaffe mailing list