From d52d0f6d96c27e89d80d69069dad2990fc0d732e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Tue, 25 Nov 2014 18:36:34 -0700 Subject: [PATCH] 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. --- include/avian/tools/object-writer/tools.h | 1 + makefile | 96 +++++++++------ src/arm.S | 140 +++++++++++++++++++++- src/avian/arch.h | 2 +- src/avian/arm.h | 31 ++++- src/avian/common.h | 4 +- src/avian/environment.h | 1 + src/codegen/target/arm/registers.h | 7 ++ src/codegen/targets.cpp | 3 +- src/tools/object-writer/elf.cpp | 4 + src/tools/object-writer/tools.cpp | 2 + 11 files changed, 239 insertions(+), 52 deletions(-) diff --git a/include/avian/tools/object-writer/tools.h b/include/avian/tools/object-writer/tools.h index ea7651de5c..d6fb2c1a96 100644 --- a/include/avian/tools/object-writer/tools.h +++ b/include/avian/tools/object-writer/tools.h @@ -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 }; diff --git a/makefile b/makefile index 39056e5b3e..11f1aa74c4 100755 --- a/makefile +++ b/makefile @@ -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 diff --git a/src/arm.S b/src/arm.S index 551fd85bf7..5d33b2cb58 100644 --- a/src/arm.S +++ b/src/arm.S @@ -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__ diff --git a/src/avian/arch.h b/src/avian/arch.h index cf717b0369..b799ca50cb 100644 --- a/src/avian/arch.h +++ b/src/avian/arch.h @@ -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 diff --git a/src/avian/arm.h b/src/avian/arm.h index e44848c924..9fbc83c474 100644 --- a/src/avian/arm.h +++ b/src/avian/arm.h @@ -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(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(old), static_cast(new_), reinterpret_cast(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(p), old, new_); +} +#else inline bool atomicCompareAndSwap(uintptr_t* p, uintptr_t old, uintptr_t new_) { return atomicCompareAndSwap32(reinterpret_cast(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) { diff --git a/src/avian/common.h b/src/avian/common.h index ac05cef999..96f4498f54 100644 --- a/src/avian/common.h +++ b/src/avian/common.h @@ -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 diff --git a/src/avian/environment.h b/src/avian/environment.h index 8df211b559..d95b40617c 100644 --- a/src/avian/environment.h +++ b/src/avian/environment.h @@ -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 diff --git a/src/codegen/target/arm/registers.h b/src/codegen/target/arm/registers.h index f6d0a9d7fa..ed639acac6 100644 --- a/src/codegen/target/arm/registers.h +++ b/src/codegen/target/arm/registers.h @@ -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 diff --git a/src/codegen/targets.cpp b/src/codegen/targets.cpp index e981e8a497..fff55d3b35 100644 --- a/src/codegen/targets.cpp +++ b/src/codegen/targets.cpp @@ -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" diff --git a/src/tools/object-writer/elf.cpp b/src/tools/object-writer/elf.cpp index 2733ee0225..46c4e62936 100644 --- a/src/tools/object-writer/elf.cpp +++ b/src/tools/object-writer/elf.cpp @@ -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 elfX86Platform(PlatformInfo::x86); ElfPlatform elfArmPlatform(PlatformInfo::Arm); +ElfPlatform elfArm64Platform(PlatformInfo::Arm64); ElfPlatform elfX86_64Platform(PlatformInfo::x86_64); } // namespace diff --git a/src/tools/object-writer/tools.cpp b/src/tools/object-writer/tools.cpp index ad736efd24..869cc6c249 100644 --- a/src/tools/object-writer/tools.cpp +++ b/src/tools/object-writer/tools.cpp @@ -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; }