[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