add process=interpret support for Linux/ARM64

This makes all the tests pass for the platform=linux arch=arm64
process=interpret build.  Next step: process=compile support.
This commit is contained in:
Joel Dice 2014-11-25 18:36:34 -07:00
parent 66f1b7cf8f
commit d52d0f6d96
11 changed files with 239 additions and 52 deletions

View File

@ -118,6 +118,7 @@ class PlatformInfo {
x86 = AVIAN_ARCH_X86,
x86_64 = AVIAN_ARCH_X86_64,
Arm = AVIAN_ARCH_ARM,
Arm64 = AVIAN_ARCH_ARM64,
UnknownArch = AVIAN_ARCH_UNKNOWN
};

View File

@ -7,12 +7,13 @@ build-arch := $(shell uname -m \
| sed 's/^i.86$$/i386/' \
| sed 's/^x86pc$$/i386/' \
| sed 's/amd64/x86_64/' \
| sed 's/^arm.*$$/arm/')
| sed 's/^arm.*$$/arm/' \
| sed 's/aarch64/arm64/')
build-platform := \
$(shell uname -s | tr [:upper:] [:lower:] \
| sed \
-e 's/^mingw32.*$$/mingw32/' \
-e 's/^mingw32.*$$/mingw32/' \
-e 's/^cygwin.*$$/cygwin/' \
-e 's/^darwin.*$$/macosx/')
@ -62,8 +63,8 @@ ifeq ($(filter compile interpret,$(process)),)
x := $(error "'$(process)' is not a valid process (choose one of: compile interpret)")
endif
ifeq ($(filter x86_64 i386 arm,$(arch)),)
x := $(error "'$(arch)' is not a supported architecture (choose one of: x86_64 i386 arm)")
ifeq ($(filter x86_64 i386 arm arm64,$(arch)),)
x := $(error "'$(arch)' is not a supported architecture (choose one of: x86_64 i386 arm arm64)")
endif
ifeq ($(platform),darwin)
@ -79,8 +80,8 @@ ifeq ($(filter linux windows macosx ios freebsd,$(platform)),)
endif
ifeq ($(platform),macosx)
ifeq ($(arch),arm)
x := $(error "please use 'arch=arm' 'platform=ios' to build for ios-arm")
ifneq ($(filter arm arm64,$(arch),)
x := $(error "please use 'arch=arm' or 'arch=arm64' 'platform=ios' to build for ios-arm")
endif
endif
@ -454,15 +455,15 @@ cflags = $(build-cflags)
common-lflags = -lm -lz
ifeq ($(use-clang),true)
ifeq ($(build-kernel),darwin)
common-lflags += -Wl,-export_dynamic
else
ifneq ($(platform),windows)
common-lflags += -Wl,-E
else
common-lflags += -Wl,--export-all-symbols
endif
endif
ifeq ($(build-kernel),darwin)
common-lflags += -Wl,-export_dynamic
else
ifneq ($(platform),windows)
common-lflags += -Wl,-E
else
common-lflags += -Wl,--export-all-symbols
endif
endif
endif
build-lflags = -lz -lpthread -ldl
@ -520,30 +521,39 @@ codeimage-symbols = _binary_codeimage_bin_start:_binary_codeimage_bin_end
developer-dir := $(shell if test -d /Developer/Platforms/$(target).platform/Developer/SDKs; then echo /Developer; \
else echo /Applications/Xcode.app/Contents/Developer; fi)
ifeq ($(arch),i386)
ifneq (,$(filter i386 arm,$(arch)))
pointer-size = 4
endif
ifeq ($(arch),arm)
ifneq (,$(filter arm arm64,$(arch)))
asm = arm
pointer-size = 4
ifneq ($(platform),ios)
no-psabi = -Wno-psabi
cflags += -marm $(no-psabi)
ifneq ($(arch),arm64)
no-psabi = -Wno-psabi
cflags += -marm $(no-psabi)
# By default, assume we can't use armv7-specific instructions on
# non-iOS platforms. Ideally, we'd detect this at runtime.
armv6=true
# By default, assume we can't use armv7-specific instructions on
# non-iOS platforms. Ideally, we'd detect this at runtime.
armv6=true
endif
endif
ifneq ($(arch),$(build-arch))
ifneq ($(kernel),darwin)
cxx = arm-linux-gnueabi-g++
cc = arm-linux-gnueabi-gcc
ar = arm-linux-gnueabi-ar
ranlib = arm-linux-gnueabi-ranlib
strip = arm-linux-gnueabi-strip
ifeq ($(arch),arm64)
cxx = aarch64-linux-gnu-g++
cc = aarch64-linux-gnu-gcc
ar = aarch64-linux-gnu-ar
ranlib = aarch64-linux-gnu-ranlib
strip = aarch64-linux-gnu-strip
else
cxx = arm-linux-gnueabi-g++
cc = arm-linux-gnueabi-gcc
ar = arm-linux-gnueabi-ar
ranlib = arm-linux-gnueabi-ranlib
strip = arm-linux-gnueabi-strip
endif
endif
endif
endif
@ -682,7 +692,7 @@ ifeq ($(kernel),darwin)
sdk-dir = $(platform-dir)/Developer/SDKs
mac-version := $(shell \
if test -d $(sdk-dir)/MacOSX10.9.sdk; then echo 10.9; \
if test -d $(sdk-dir)/MacOSX10.9.sdk; then echo 10.9; \
elif test -d $(sdk-dir)/MacOSX10.8.sdk; then echo 10.8; \
elif test -d $(sdk-dir)/MacOSX10.7.sdk; then echo 10.7; \
elif test -d $(sdk-dir)/MacOSX10.6.sdk; then echo 10.6; \
@ -721,7 +731,11 @@ ifeq ($(kernel),darwin)
else
target = iPhoneOS
sdk = iphoneos$(ios-version)
arch-flag = -arch armv7
ifeq ($(arch),arm)
arch-flag = -arch armv7
else
arch-flag = -arch arm64
endif
release = Release-iphoneos
endif
@ -729,7 +743,7 @@ ifeq ($(kernel),darwin)
sdk-dir = $(platform-dir)/Developer/SDKs
ios-version := $(shell \
if test -d $(sdk-dir)/$(target)8.0.sdk; then echo 8.0; \
if test -d $(sdk-dir)/$(target)8.0.sdk; then echo 8.0; \
elif test -d $(sdk-dir)/$(target)7.1.sdk; then echo 7.1; \
elif test -d $(sdk-dir)/$(target)7.0.sdk; then echo 7.0; \
elif test -d $(sdk-dir)/$(target)6.1.sdk; then echo 6.1; \
@ -822,7 +836,7 @@ ifeq ($(platform),windows)
&& echo i686-w64-mingw32- || echo x86_64-w64-mingw32-)
cxx = $(prefix)g++ -m32
cc = $(prefix)gcc -m32
dlltool = $(prefix)dlltool -mi386 --as-flags=--32
dlltool = $(prefix)dlltool -mi386 --as-flags=--32
ar = $(prefix)ar
ranlib = $(prefix)ranlib
strip = $(prefix)strip --strip-all
@ -1234,7 +1248,7 @@ ifeq ($(process),compile)
vm-sources += $(native-assembler-sources)
endif
ifeq ($(codegen-targets),all)
ifeq ($(arch),arm)
ifneq (,$(filter arm arm64,$(arch)))
# The x86 jit has a dependency on the x86 assembly code,
# and thus can't be successfully built on non-x86 platforms.
vm-sources += $(native-assembler-sources)
@ -1255,7 +1269,7 @@ all-codegen-target-objects = $(call cpp-objects,$(all-codegen-target-sources),$(
vm-asm-objects = $(call asm-objects,$(vm-asm-sources),$(src),$(build))
vm-objects = $(vm-cpp-objects) $(vm-asm-objects)
heapwalk-sources = $(src)/heapwalk.cpp
heapwalk-sources = $(src)/heapwalk.cpp
heapwalk-objects = \
$(call cpp-objects,$(heapwalk-sources),$(src),$(build))
@ -1511,6 +1525,10 @@ ifeq ($(target-arch),arm)
cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM
endif
ifeq ($(target-arch),arm64)
cflags += -DAVIAN_TARGET_ARCH=AVIAN_ARCH_ARM64
endif
ifeq ($(target-format),elf)
cflags += -DAVIAN_TARGET_FORMAT=AVIAN_FORMAT_ELF
endif
@ -1639,7 +1657,7 @@ $(classpath-dep): $(classpath-sources) $(classpath-jar-dep)
classes="$(shell $(MAKE) -s --no-print-directory build=$(build) \
$(classpath-classes))"; if [ -n "$${classes}" ]; then \
$(javac) -source 1.6 -target 1.6 \
-d $(classpath-build) -bootclasspath $(boot-classpath) \
-d $(classpath-build) -bootclasspath $(boot-classpath) \
$${classes}; fi
@touch $(@)
@ -1703,7 +1721,7 @@ $(build)/android.dep: $(luni-javas) $(dalvik-javas) $(libart-javas) \
$(build)/android/java/security/security.properties
chmod +w $(build)/android/java/security/security.properties
cp -r $(build)/android/* $(classpath-build)
@touch $(@)
@touch $(@)
$(test-build)/%.class: $(test)/%.java
@echo $(<)
@ -1714,7 +1732,7 @@ $(test-dep): $(test-sources) $(test-library)
files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-classes))"; \
if test -n "$${files}"; then \
$(javac) -source 1.6 -target 1.6 \
-classpath $(test-build) -d $(test-build) -bootclasspath $(boot-classpath) $${files}; \
-classpath $(test-build) -d $(test-build) -bootclasspath $(boot-classpath) $${files}; \
fi
$(javac) -source 1.2 -target 1.1 -XDjsrlimit=0 -d $(test-build) \
-bootclasspath $(boot-classpath) test/Subroutine.java
@ -1726,7 +1744,7 @@ $(test-extra-dep): $(test-extra-sources)
files="$(shell $(MAKE) -s --no-print-directory build=$(build) $(test-extra-classes))"; \
if test -n "$${files}"; then \
$(javac) -source 1.6 -target 1.6 \
-d $(test-build) -bootclasspath $(boot-classpath) $${files}; \
-d $(test-build) -bootclasspath $(boot-classpath) $${files}; \
fi
@touch $(@)
@ -1808,7 +1826,7 @@ ifdef mt
endif
else
$(dlltool) -z $(addsuffix .def,$(basename $(@))) $(^)
$(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@)))
$(dlltool) -d $(addsuffix .def,$(basename $(@))) -e $(addsuffix .exp,$(basename $(@)))
$(ld) $(addsuffix .exp,$(basename $(@))) $(^) \
$(lflags) $(bootimage-lflags) -o $(@)
endif

140
src/arm.S
View File

@ -10,7 +10,7 @@
details. */
#include "avian/types.h"
.text
#define LOCAL(x) .L##x
@ -18,9 +18,137 @@
#ifdef __APPLE__
# define GLOBAL(x) _##x
#else
# define GLOBAL(x) x
# define GLOBAL(x) x
#endif
#ifdef __aarch64__
.globl GLOBAL(vmNativeCall)
.align 2
GLOBAL(vmNativeCall):
// arguments:
// x0 -> x19 : function
// w1 -> w20 : stackTotal
// x2 : memoryTable
// w3 : memoryCount
// x4 -> x21 : gprTable
// x5 -> x22 : vfpTable
// w6 -> w23 : returnType
// allocate frame
stp x29, x30, [sp,#-64]!
// save callee-saved register values so we can clobber them
stp x19, x20, [sp,#16]
stp x21, x22, [sp,#32]
str x23, [sp,#48]
// move arguments into callee-saved registers
mov x19, x0
mov w20, w1
mov x21, x4
mov x22, x5
mov w23, w6
// setup stack arguments if necessary
sub sp, sp, w20 // allocate stack
mov x9, sp
LOCAL(loop):
cmp w3, wzr
b.eq LOCAL(populateGPRs)
ldr x0, [x2], #8
str x0, [x9], #8
sub w3, w3, #8
b LOCAL(loop)
LOCAL(populateGPRs):
cmp x21, xzr
b.eq LOCAL(populateVFPs)
ldp x0, x1, [x21]
ldp x2, x3, [x21,#16]
ldp x4, x5, [x21,#32]
ldp x6, x7, [x21,#48]
LOCAL(populateVFPs):
cmp x22, xzr
b.eq LOCAL(doCall)
ldp d0, d1, [x22]
ldp d2, d3, [x22,#16]
ldp d4, d5, [x22,#32]
ldp d6, d7, [x22,#48]
LOCAL(doCall):
blr x19 // call function
add sp, sp, w20 // deallocate stack
cmp w23,#FLOAT_TYPE
bne LOCAL(double)
fmov w0,s0
b LOCAL(exit)
LOCAL(double):
cmp w23,#DOUBLE_TYPE
bne LOCAL(exit)
fmov x0,d0
LOCAL(exit):
ldp x19, x20, [sp,#16]
ldp x21, x22, [sp,#32]
ldr x23, [sp,#48]
ldp x29, x30, [sp],#64
ret
.globl GLOBAL(vmJump)
.align 2
GLOBAL(vmJump):
mov x30, x0
mov x0, x4
mov x1, x5
mov sp, x2
mov x19, x3
br x30
#define CHECKPOINT_THREAD 8
#define CHECKPOINT_STACK 48
.globl GLOBAL(vmRun)
.align 2
GLOBAL(vmRun):
// x0: function
// x1: arguments
// x2: checkpoint
// allocate frame
stp x29, x30, [sp,#-96]!
// save callee-saved register values
stp x19, x20, [sp,#16]
stp x21, x22, [sp,#32]
stp x23, x24, [sp,#48]
stp x25, x26, [sp,#64]
stp x27, x28, [sp,#80]
mov x19, sp
str x19, [x2, #CHECKPOINT_STACK]
mov x19, x0
ldr x0, [x2, #CHECKPOINT_THREAD]
blr x19
.globl GLOBAL(vmRun_returnAddress)
.align 2
GLOBAL(vmRun_returnAddress):
ldp x19, x20, [sp,#16]
ldp x21, x22, [sp,#32]
ldp x23, x24, [sp,#48]
ldp x25, x26, [sp,#64]
ldp x27, x28, [sp,#80]
ldp x29, x30, [sp],#96
br x30
#elif defined __arm__
.globl GLOBAL(vmNativeCall)
.align 2
GLOBAL(vmNativeCall):
@ -83,9 +211,9 @@ LOCAL(loop):
LOCAL(double):
cmp r8,#DOUBLE_TYPE
bne LOCAL(exit)
fmrrd r0,r1,d0
fmrrd r0,r1,d0
#endif
LOCAL(exit):
ldmfd sp!, {r4-r8, pc} // restore non-volatile regs and return
@ -111,7 +239,7 @@ GLOBAL(vmRun):
stmfd sp!, {r4-r11, lr}
// align stack
sub sp, sp, #12
str sp, [r2, #CHECKPOINT_STACK]
mov r12, r0
@ -130,3 +258,5 @@ GLOBAL(vmRun_returnAddress):
add sp, sp, #12
ldmfd sp!, {r4-r11, lr}
bx lr
#endif // __arm__

View File

@ -43,7 +43,7 @@ inline void compileTimeMemoryBarrier()
#if (defined ARCH_x86_32) || (defined ARCH_x86_64)
#include "x86.h"
#elif defined ARCH_arm
#elif (defined ARCH_arm) || (defined ARCH_arm64)
#include "arm.h"
#else
#error unsupported architecture

View File

@ -53,10 +53,17 @@
#define THREAD_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_IP])
#define LINK_REGISTER(context) (context->uc_mcontext.cpu.gpr[ARM_REG_LR])
#else
#ifdef ARCH_arm
#define IP_REGISTER(context) (context->uc_mcontext.arm_pc)
#define STACK_REGISTER(context) (context->uc_mcontext.arm_sp)
#define THREAD_REGISTER(context) (context->uc_mcontext.arm_ip)
#define LINK_REGISTER(context) (context->uc_mcontext.arm_lr)
#else
#define IP_REGISTER(context) (context->uc_mcontext.pc)
#define STACK_REGISTER(context) (context->uc_mcontext.sp)
#define THREAD_REGISTER(context) (context->uc_mcontext.regs[19])
#define LINK_REGISTER(context) (context->uc_mcontext.regs[30])
#endif
#endif
#define VA_LIST(x) (&(x))
@ -76,7 +83,7 @@ inline void trap()
#ifdef _MSC_VER
__debugbreak();
#else
asm("bkpt");
asm("brk 0");
#endif
}
@ -162,6 +169,8 @@ inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
old, new_, reinterpret_cast<int32_t*>(p));
#elif(defined __QNX__)
return old == _smp_cmpxchg(p, old, new_);
#elif (defined ARCH_arm64)
return __sync_bool_compare_and_swap(p, old, new_);
#else
int r = __kernel_cmpxchg(
static_cast<int>(old), static_cast<int>(new_), reinterpret_cast<int*>(p));
@ -169,10 +178,22 @@ inline bool atomicCompareAndSwap32(uint32_t* p, uint32_t old, uint32_t new_)
#endif
}
#ifdef ARCH_arm64
inline bool atomicCompareAndSwap64(uint64_t* p, uint64_t old, uint64_t new_)
{
return __sync_bool_compare_and_swap(p, old, new_);
}
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{
return atomicCompareAndSwap64(reinterpret_cast<uint64_t*>(p), old, new_);
}
#else
inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_)
{
return atomicCompareAndSwap32(reinterpret_cast<uint32_t*>(p), old, new_);
}
#endif
inline uint64_t dynamicCall(void* function,
uintptr_t* arguments,
@ -181,17 +202,17 @@ inline uint64_t dynamicCall(void* function,
unsigned argumentsSize UNUSED,
unsigned returnType)
{
#ifdef __APPLE__
#if (defined __APPLE__) || (defined ARCH_arm64)
const unsigned Alignment = 1;
#else
const unsigned Alignment = 2;
#endif
const unsigned GprCount = 4;
const unsigned GprCount = BytesPerWord;
uintptr_t gprTable[GprCount];
unsigned gprIndex = 0;
const unsigned VfpCount = 16;
const unsigned VfpCount = BytesPerWord == 8 ? 8 : 16;
uintptr_t vfpTable[VfpCount];
unsigned vfpIndex = 0;
unsigned vfpBackfillIndex UNUSED = 0;
@ -206,7 +227,7 @@ inline uint64_t dynamicCall(void* function,
for (unsigned ati = 0; ati < argumentCount; ++ati) {
switch (argumentTypes[ati]) {
case DOUBLE_TYPE:
#if defined(__ARM_PCS_VFP)
#if (defined __ARM_PCS_VFP) || (defined ARCH_arm64)
{
if (vfpIndex + Alignment <= VfpCount) {
if (vfpIndex % Alignment) {

View File

@ -116,6 +116,8 @@ typedef intptr_t intptr_alias_t;
#define ARCH_x86_64
#elif defined __arm__
#define ARCH_arm
#elif defined __aarch64__
#define ARCH_arm64
#else
#error "unsupported architecture"
#endif
@ -184,7 +186,7 @@ typedef intptr_t __attribute__((__may_alias__)) intptr_alias_t;
#error "Unsupported architecture"
#endif
#endif
#ifdef PLATFORM_WINDOWS
#define SO_PREFIX ""
#else

View File

@ -28,5 +28,6 @@
#define AVIAN_ARCH_X86 (1 << 8)
#define AVIAN_ARCH_X86_64 (2 << 8)
#define AVIAN_ARCH_ARM (3 << 8)
#define AVIAN_ARCH_ARM64 (4 << 8)
#endif

View File

@ -52,10 +52,17 @@ inline int fpr32(lir::Register* reg)
return fpr64(reg) << 1;
}
#ifdef ARCH_arm64
const int ThreadRegister = 19;
const int StackRegister = 31;
const int LinkRegister = 30;
const int ProgramCounter = 0xFF; // i.e. unaddressable
#else
const int ThreadRegister = 8;
const int StackRegister = 13;
const int LinkRegister = 14;
const int ProgramCounter = 15;
#endif
} // namespace arm
} // namespace codegen

View File

@ -30,7 +30,8 @@ Architecture* makeArchitectureNative(vm::System* system,
#elif(AVIAN_TARGET_ARCH == AVIAN_ARCH_X86) \
|| (AVIAN_TARGET_ARCH == AVIAN_ARCH_X86_64)
return makeArchitectureX86(system, useNativeFeatures);
#elif AVIAN_TARGET_ARCH == AVIAN_ARCH_ARM
#elif (AVIAN_TARGET_ARCH == AVIAN_ARCH_ARM) \
|| (AVIAN_TARGET_ARCH == AVIAN_ARCH_ARM64)
return makeArchitectureArm(system, useNativeFeatures);
#else
#error "Unsupported codegen target"

View File

@ -49,6 +49,7 @@
#define EM_386 3
#define EM_X86_64 62
#define EM_ARM 40
#define EM_AARCH64 183
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
@ -129,6 +130,8 @@ unsigned getElfPlatform(PlatformInfo::Architecture arch)
return EM_386;
case PlatformInfo::Arm:
return EM_ARM;
case PlatformInfo::Arm64:
return EM_AARCH64;
default:
return ~0;
}
@ -398,6 +401,7 @@ class ElfPlatform : public Platform {
ElfPlatform<uint32_t> elfX86Platform(PlatformInfo::x86);
ElfPlatform<uint32_t> elfArmPlatform(PlatformInfo::Arm);
ElfPlatform<uint64_t> elfArm64Platform(PlatformInfo::Arm64);
ElfPlatform<uint64_t> elfX86_64Platform(PlatformInfo::x86_64);
} // namespace

View File

@ -115,6 +115,8 @@ PlatformInfo::Architecture PlatformInfo::archFromString(const char* arch)
return Architecture::x86_64;
} else if (strcmp(arch, "arm") == 0) {
return Architecture::Arm;
} else if (strcmp(arch, "arm64") == 0) {
return Architecture::Arm64;
} else {
return Architecture::UnknownArch;
}