Reland "Add Windows ARM64 ABI support to V8"

This is a reland of fcbb023b0e

Original change's description:
> Add Windows ARM64 ABI support to V8
>
> This change added Windows ARM64 ABI support, major things are:
> 1. Excluding x18 register from any usage because it is reserved as
>    platform register. Preserve alignment after the change.
> 2. Fix the assumption of LP64 in arm64 backend. Windows ARM64 is
>    still LLP64.
> 3. Stack guard page probe for large allocation on stack.
>
> Reference:
> Windows ARM64 ABI:
> https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=vs-2017
>
> Bug: chromium:893460
> Change-Id: I325884ac8dab719154a0047141e18a9fcb8dff7e
> Reviewed-on: https://chromium-review.googlesource.com/c/1285129
> Commit-Queue: Michael Achenbach <machenbach@chromium.org>
> Reviewed-by: Andreas Haas <ahaas@chromium.org>
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#56881}

CQ_INCLUDE_TRYBOTS=luci.chromium.try:android_arm64_dbg_recipe
TBR=mlippautz@chromium.org

Bug: chromium:893460
Change-Id: Icc45fd091c33f7df805842a70236b79b14756f52
Reviewed-on: https://chromium-review.googlesource.com/c/1297300
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#56965}
This commit is contained in:
Tom Tan 2018-10-23 16:30:20 -07:00 committed by Commit Bot
parent 76968a2ff3
commit a6423cca4a
30 changed files with 431 additions and 167 deletions

View File

@ -156,6 +156,7 @@ Teddy Katz <teddy.katz@gmail.com>
Tiancheng "Timothy" Gu <timothygu99@gmail.com> Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Tobias Burnus <burnus@net-b.de> Tobias Burnus <burnus@net-b.de>
Tobias Nießen <tniessen@tnie.de> Tobias Nießen <tniessen@tnie.de>
Tom Tan <Tom.Tan@microsoft.com>
Ujjwal Sharma <usharma1998@gmail.com> Ujjwal Sharma <usharma1998@gmail.com>
Victor Costan <costan@gmail.com> Victor Costan <costan@gmail.com>
Vlad Burlik <vladbph@gmail.com> Vlad Burlik <vladbph@gmail.com>

View File

@ -83,7 +83,13 @@ if (v8_snapshot_toolchain == "") {
if (v8_current_cpu == "x64" || v8_current_cpu == "x86") { if (v8_current_cpu == "x64" || v8_current_cpu == "x86") {
_cpus = v8_current_cpu _cpus = v8_current_cpu
} else if (v8_current_cpu == "arm64" || v8_current_cpu == "mips64el") { } else if (v8_current_cpu == "arm64" || v8_current_cpu == "mips64el") {
_cpus = "x64_v8_${v8_current_cpu}" if (is_win && v8_current_cpu == "arm64") {
# set _cpus to blank for Windows ARM64 so host_toolchain could be
# selected as snapshot toolchain later.
_cpus = ""
} else {
_cpus = "x64_v8_${v8_current_cpu}"
}
} else if (v8_current_cpu == "arm" || v8_current_cpu == "mipsel") { } else if (v8_current_cpu == "arm" || v8_current_cpu == "mipsel") {
_cpus = "x86_v8_${v8_current_cpu}" _cpus = "x86_v8_${v8_current_cpu}"
} else { } else {
@ -94,6 +100,9 @@ if (v8_snapshot_toolchain == "") {
if (_cpus != "") { if (_cpus != "") {
v8_snapshot_toolchain = "//build/toolchain/${host_os}:${_clang}${_cpus}" v8_snapshot_toolchain = "//build/toolchain/${host_os}:${_clang}${_cpus}"
} else if (is_win && v8_current_cpu == "arm64") {
# cross compile Windows arm64 with Windows x64 toolchain.
v8_snapshot_toolchain = host_toolchain
} }
} }
} }

View File

@ -89,14 +89,14 @@ inline void CPURegList::Remove(const CPURegister& other1,
inline void CPURegList::Combine(int code) { inline void CPURegList::Combine(int code) {
DCHECK(IsValid()); DCHECK(IsValid());
DCHECK(CPURegister::Create(code, size_, type_).IsValid()); DCHECK(CPURegister::Create(code, size_, type_).IsValid());
list_ |= (1UL << code); list_ |= (1ULL << code);
} }
inline void CPURegList::Remove(int code) { inline void CPURegList::Remove(int code) {
DCHECK(IsValid()); DCHECK(IsValid());
DCHECK(CPURegister::Create(code, size_, type_).IsValid()); DCHECK(CPURegister::Create(code, size_, type_).IsValid());
list_ &= ~(1UL << code); list_ &= ~(1ULL << code);
} }
@ -679,7 +679,7 @@ Address RelocInfo::target_address_address() {
return constant_pool_entry_address(); return constant_pool_entry_address();
} else { } else {
DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch()); DCHECK(instr->IsBranchAndLink() || instr->IsUnconditionalBranch());
return reinterpret_cast<Address>(pc_); return pc_;
} }
} }

View File

@ -68,7 +68,7 @@ CPURegister CPURegList::PopLowestIndex() {
return NoCPUReg; return NoCPUReg;
} }
int index = CountTrailingZeros(list_, kRegListSizeInBits); int index = CountTrailingZeros(list_, kRegListSizeInBits);
DCHECK((1 << index) & list_); DCHECK((1LL << index) & list_);
Remove(index); Remove(index);
return CPURegister::Create(index, size_, type_); return CPURegister::Create(index, size_, type_);
} }
@ -81,7 +81,7 @@ CPURegister CPURegList::PopHighestIndex() {
} }
int index = CountLeadingZeros(list_, kRegListSizeInBits); int index = CountLeadingZeros(list_, kRegListSizeInBits);
index = kRegListSizeInBits - 1 - index; index = kRegListSizeInBits - 1 - index;
DCHECK((1 << index) & list_); DCHECK((1LL << index) & list_);
Remove(index); Remove(index);
return CPURegister::Create(index, size_, type_); return CPURegister::Create(index, size_, type_);
} }
@ -110,8 +110,14 @@ CPURegList CPURegList::GetCalleeSavedV(int size) {
CPURegList CPURegList::GetCallerSaved(int size) { CPURegList CPURegList::GetCallerSaved(int size) {
#if defined(V8_OS_WIN)
// x18 is reserved as platform register on Windows arm64.
// Registers x0-x17 and lr (x30) are caller-saved.
CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 17);
#else
// Registers x0-x18 and lr (x30) are caller-saved. // Registers x0-x18 and lr (x30) are caller-saved.
CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18); CPURegList list = CPURegList(CPURegister::kRegister, size, 0, 18);
#endif
list.Combine(lr); list.Combine(lr);
return list; return list;
} }
@ -144,9 +150,13 @@ CPURegList CPURegList::GetSafepointSavedRegisters() {
list.Remove(16); list.Remove(16);
list.Remove(17); list.Remove(17);
// Don't add x18 to safepoint list on Windows arm64 because it is reserved
// as platform register.
#if !defined(V8_OS_WIN)
// Add x18 to the safepoint list, as although it's not in kJSCallerSaved, it // Add x18 to the safepoint list, as although it's not in kJSCallerSaved, it
// is a caller-saved register according to the procedure call standard. // is a caller-saved register according to the procedure call standard.
list.Combine(18); list.Combine(18);
#endif
// Add the link register (x30) to the safepoint list. // Add the link register (x30) to the safepoint list.
list.Combine(30); list.Combine(30);
@ -506,11 +516,11 @@ MemOperand::PairResult MemOperand::AreConsistentForPair(
} }
// Step two: check that the offsets are contiguous and that the range // Step two: check that the offsets are contiguous and that the range
// is OK for ldp/stp. // is OK for ldp/stp.
if ((operandB.offset() == operandA.offset() + (1 << access_size_log2)) && if ((operandB.offset() == operandA.offset() + (1LL << access_size_log2)) &&
is_int7(operandA.offset() >> access_size_log2)) { is_int7(operandA.offset() >> access_size_log2)) {
return kPairAB; return kPairAB;
} }
if ((operandA.offset() == operandB.offset() + (1 << access_size_log2)) && if ((operandA.offset() == operandB.offset() + (1LL << access_size_log2)) &&
is_int7(operandB.offset() >> access_size_log2)) { is_int7(operandB.offset() >> access_size_log2)) {
return kPairBA; return kPairBA;
} }
@ -4002,16 +4012,16 @@ void Assembler::MoveWide(const Register& rd, uint64_t imm, int shift,
// Calculate a new immediate and shift combination to encode the immediate // Calculate a new immediate and shift combination to encode the immediate
// argument. // argument.
shift = 0; shift = 0;
if ((imm & ~0xFFFFUL) == 0) { if ((imm & ~0xFFFFULL) == 0) {
// Nothing to do. // Nothing to do.
} else if ((imm & ~(0xFFFFUL << 16)) == 0) { } else if ((imm & ~(0xFFFFULL << 16)) == 0) {
imm >>= 16; imm >>= 16;
shift = 1; shift = 1;
} else if ((imm & ~(0xFFFFUL << 32)) == 0) { } else if ((imm & ~(0xFFFFULL << 32)) == 0) {
DCHECK(rd.Is64Bits()); DCHECK(rd.Is64Bits());
imm >>= 32; imm >>= 32;
shift = 2; shift = 2;
} else if ((imm & ~(0xFFFFUL << 48)) == 0) { } else if ((imm & ~(0xFFFFULL << 48)) == 0) {
DCHECK(rd.Is64Bits()); DCHECK(rd.Is64Bits());
imm >>= 48; imm >>= 48;
shift = 3; shift = 3;

View File

@ -18,6 +18,12 @@
#include "src/globals.h" #include "src/globals.h"
#include "src/utils.h" #include "src/utils.h"
// Windows arm64 SDK defines mvn to NEON intrinsic neon_not which will not
// be used here.
#if defined(V8_OS_WIN) && defined(mvn)
#undef mvn
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -36,11 +42,20 @@ namespace internal {
R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \ R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \
R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31) R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31)
#if defined(V8_OS_WIN)
// x18 is reserved as platform register on Windows ARM64.
#define ALLOCATABLE_GENERAL_REGISTERS(R) \
R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \
R(x27) R(x28)
#else
#define ALLOCATABLE_GENERAL_REGISTERS(R) \ #define ALLOCATABLE_GENERAL_REGISTERS(R) \
R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \ R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \ R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \ R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x25) \
R(x27) R(x28) R(x27) R(x28)
#endif
#define FLOAT_REGISTERS(V) \ #define FLOAT_REGISTERS(V) \
V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \ V(s0) V(s1) V(s2) V(s3) V(s4) V(s5) V(s6) V(s7) \
@ -207,7 +222,12 @@ class CPURegister : public RegisterBase<CPURegister, kRegAfterLast> {
int reg_size_; int reg_size_;
RegisterType reg_type_; RegisterType reg_type_;
#if defined(V8_OS_WIN) && !defined(__clang__)
// MSVC has problem to parse template base class as friend class.
friend RegisterBase;
#else
friend class RegisterBase; friend class RegisterBase;
#endif
constexpr CPURegister(int code, int size, RegisterType type) constexpr CPURegister(int code, int size, RegisterType type)
: RegisterBase(code), reg_size_(size), reg_type_(type) {} : RegisterBase(code), reg_size_(size), reg_type_(type) {}
@ -533,8 +553,8 @@ class CPURegList {
((type == CPURegister::kVRegister) && ((type == CPURegister::kVRegister) &&
(last_reg < kNumberOfVRegisters))); (last_reg < kNumberOfVRegisters)));
DCHECK(last_reg >= first_reg); DCHECK(last_reg >= first_reg);
list_ = (1UL << (last_reg + 1)) - 1; list_ = (1ULL << (last_reg + 1)) - 1;
list_ &= ~((1UL << first_reg) - 1); list_ &= ~((1ULL << first_reg) - 1);
DCHECK(IsValid()); DCHECK(IsValid());
} }
@ -693,7 +713,7 @@ class Immediate {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Operands. // Operands.
constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize; constexpr int kSmiShift = kSmiTagSize + kSmiShiftSize;
constexpr uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1; constexpr uint64_t kSmiShiftMask = (1ULL << kSmiShift) - 1;
// Represents an operand in a machine instruction. // Represents an operand in a machine instruction.
class Operand { class Operand {

View File

@ -8,12 +8,16 @@
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/globals.h" #include "src/globals.h"
// Assert that this is an LP64 system. // Assert that this is an LP64 system, or LLP64 on Windows.
STATIC_ASSERT(sizeof(int) == sizeof(int32_t)); STATIC_ASSERT(sizeof(int) == sizeof(int32_t));
#if defined(V8_OS_WIN)
STATIC_ASSERT(sizeof(1L) == sizeof(int32_t));
#else
STATIC_ASSERT(sizeof(long) == sizeof(int64_t)); // NOLINT(runtime/int) STATIC_ASSERT(sizeof(long) == sizeof(int64_t)); // NOLINT(runtime/int)
STATIC_ASSERT(sizeof(1L) == sizeof(int64_t));
#endif
STATIC_ASSERT(sizeof(void *) == sizeof(int64_t)); STATIC_ASSERT(sizeof(void *) == sizeof(int64_t));
STATIC_ASSERT(sizeof(1) == sizeof(int32_t)); STATIC_ASSERT(sizeof(1) == sizeof(int32_t));
STATIC_ASSERT(sizeof(1L) == sizeof(int64_t));
// Get the standard printf format macros for C99 stdint types. // Get the standard printf format macros for C99 stdint types.
@ -77,17 +81,17 @@ const int64_t kDRegMask = 0xffffffffffffffffL;
// TODO(all) check if the expression below works on all compilers or if it // TODO(all) check if the expression below works on all compilers or if it
// triggers an overflow error. // triggers an overflow error.
const int64_t kDSignBit = 63; const int64_t kDSignBit = 63;
const int64_t kDSignMask = 0x1L << kDSignBit; const int64_t kDSignMask = 0x1LL << kDSignBit;
const int64_t kSSignBit = 31; const int64_t kSSignBit = 31;
const int64_t kSSignMask = 0x1L << kSSignBit; const int64_t kSSignMask = 0x1LL << kSSignBit;
const int64_t kXSignBit = 63; const int64_t kXSignBit = 63;
const int64_t kXSignMask = 0x1L << kXSignBit; const int64_t kXSignMask = 0x1LL << kXSignBit;
const int64_t kWSignBit = 31; const int64_t kWSignBit = 31;
const int64_t kWSignMask = 0x1L << kWSignBit; const int64_t kWSignMask = 0x1LL << kWSignBit;
const int64_t kDQuietNanBit = 51; const int64_t kDQuietNanBit = 51;
const int64_t kDQuietNanMask = 0x1L << kDQuietNanBit; const int64_t kDQuietNanMask = 0x1LL << kDQuietNanBit;
const int64_t kSQuietNanBit = 22; const int64_t kSQuietNanBit = 22;
const int64_t kSQuietNanMask = 0x1L << kSQuietNanBit; const int64_t kSQuietNanMask = 0x1LL << kSQuietNanBit;
const int64_t kByteMask = 0xffL; const int64_t kByteMask = 0xffL;
const int64_t kHalfWordMask = 0xffffL; const int64_t kHalfWordMask = 0xffffL;
const int64_t kWordMask = 0xffffffffL; const int64_t kWordMask = 0xffffffffL;
@ -273,7 +277,7 @@ V_(Flags, 31, 28, Bits, uint32_t) \
V_(N, 31, 31, Bits, bool) \ V_(N, 31, 31, Bits, bool) \
V_(Z, 30, 30, Bits, bool) \ V_(Z, 30, 30, Bits, bool) \
V_(C, 29, 29, Bits, bool) \ V_(C, 29, 29, Bits, bool) \
V_(V, 28, 28, Bits, uint32_t) \ V_(V, 28, 28, Bits, bool) \
M_(NZCV, Flags_mask) \ M_(NZCV, Flags_mask) \
\ \
/* FPCR */ \ /* FPCR */ \
@ -445,14 +449,14 @@ enum SystemRegister {
const uint32_t kUnallocatedInstruction = 0xffffffff; const uint32_t kUnallocatedInstruction = 0xffffffff;
// Generic fields. // Generic fields.
enum GenericInstrField { enum GenericInstrField : uint32_t {
SixtyFourBits = 0x80000000, SixtyFourBits = 0x80000000,
ThirtyTwoBits = 0x00000000, ThirtyTwoBits = 0x00000000,
FP32 = 0x00000000, FP32 = 0x00000000,
FP64 = 0x00400000 FP64 = 0x00400000
}; };
enum NEONFormatField { enum NEONFormatField : uint32_t {
NEONFormatFieldMask = 0x40C00000, NEONFormatFieldMask = 0x40C00000,
NEON_Q = 0x40000000, NEON_Q = 0x40000000,
NEON_8B = 0x00000000, NEON_8B = 0x00000000,
@ -465,14 +469,14 @@ enum NEONFormatField {
NEON_2D = 0x00C00000 | NEON_Q NEON_2D = 0x00C00000 | NEON_Q
}; };
enum NEONFPFormatField { enum NEONFPFormatField : uint32_t {
NEONFPFormatFieldMask = 0x40400000, NEONFPFormatFieldMask = 0x40400000,
NEON_FP_2S = FP32, NEON_FP_2S = FP32,
NEON_FP_4S = FP32 | NEON_Q, NEON_FP_4S = FP32 | NEON_Q,
NEON_FP_2D = FP64 | NEON_Q NEON_FP_2D = FP64 | NEON_Q
}; };
enum NEONLSFormatField { enum NEONLSFormatField : uint32_t {
NEONLSFormatFieldMask = 0x40000C00, NEONLSFormatFieldMask = 0x40000C00,
LS_NEON_8B = 0x00000000, LS_NEON_8B = 0x00000000,
LS_NEON_16B = LS_NEON_8B | NEON_Q, LS_NEON_16B = LS_NEON_8B | NEON_Q,
@ -484,7 +488,7 @@ enum NEONLSFormatField {
LS_NEON_2D = LS_NEON_1D | NEON_Q LS_NEON_2D = LS_NEON_1D | NEON_Q
}; };
enum NEONScalarFormatField { enum NEONScalarFormatField : uint32_t {
NEONScalarFormatFieldMask = 0x00C00000, NEONScalarFormatFieldMask = 0x00C00000,
NEONScalar = 0x10000000, NEONScalar = 0x10000000,
NEON_B = 0x00000000, NEON_B = 0x00000000,
@ -494,7 +498,7 @@ enum NEONScalarFormatField {
}; };
// PC relative addressing. // PC relative addressing.
enum PCRelAddressingOp { enum PCRelAddressingOp : uint32_t {
PCRelAddressingFixed = 0x10000000, PCRelAddressingFixed = 0x10000000,
PCRelAddressingFMask = 0x1F000000, PCRelAddressingFMask = 0x1F000000,
PCRelAddressingMask = 0x9F000000, PCRelAddressingMask = 0x9F000000,
@ -504,7 +508,7 @@ enum PCRelAddressingOp {
// Add/sub (immediate, shifted and extended.) // Add/sub (immediate, shifted and extended.)
const int kSFOffset = 31; const int kSFOffset = 31;
enum AddSubOp { enum AddSubOp : uint32_t {
AddSubOpMask = 0x60000000, AddSubOpMask = 0x60000000,
AddSubSetFlagsBit = 0x20000000, AddSubSetFlagsBit = 0x20000000,
ADD = 0x00000000, ADD = 0x00000000,
@ -519,7 +523,7 @@ enum AddSubOp {
V(SUB), \ V(SUB), \
V(SUBS) V(SUBS)
enum AddSubImmediateOp { enum AddSubImmediateOp : uint32_t {
AddSubImmediateFixed = 0x11000000, AddSubImmediateFixed = 0x11000000,
AddSubImmediateFMask = 0x1F000000, AddSubImmediateFMask = 0x1F000000,
AddSubImmediateMask = 0xFF000000, AddSubImmediateMask = 0xFF000000,
@ -530,7 +534,7 @@ enum AddSubImmediateOp {
#undef ADD_SUB_IMMEDIATE #undef ADD_SUB_IMMEDIATE
}; };
enum AddSubShiftedOp { enum AddSubShiftedOp : uint32_t {
AddSubShiftedFixed = 0x0B000000, AddSubShiftedFixed = 0x0B000000,
AddSubShiftedFMask = 0x1F200000, AddSubShiftedFMask = 0x1F200000,
AddSubShiftedMask = 0xFF200000, AddSubShiftedMask = 0xFF200000,
@ -541,7 +545,7 @@ enum AddSubShiftedOp {
#undef ADD_SUB_SHIFTED #undef ADD_SUB_SHIFTED
}; };
enum AddSubExtendedOp { enum AddSubExtendedOp : uint32_t {
AddSubExtendedFixed = 0x0B200000, AddSubExtendedFixed = 0x0B200000,
AddSubExtendedFMask = 0x1F200000, AddSubExtendedFMask = 0x1F200000,
AddSubExtendedMask = 0xFFE00000, AddSubExtendedMask = 0xFFE00000,
@ -553,7 +557,7 @@ enum AddSubExtendedOp {
}; };
// Add/sub with carry. // Add/sub with carry.
enum AddSubWithCarryOp { enum AddSubWithCarryOp : uint32_t {
AddSubWithCarryFixed = 0x1A000000, AddSubWithCarryFixed = 0x1A000000,
AddSubWithCarryFMask = 0x1FE00000, AddSubWithCarryFMask = 0x1FE00000,
AddSubWithCarryMask = 0xFFE0FC00, AddSubWithCarryMask = 0xFFE0FC00,
@ -571,7 +575,7 @@ enum AddSubWithCarryOp {
// Logical (immediate and shifted register). // Logical (immediate and shifted register).
enum LogicalOp { enum LogicalOp : uint32_t {
LogicalOpMask = 0x60200000, LogicalOpMask = 0x60200000,
NOT = 0x00200000, NOT = 0x00200000,
AND = 0x00000000, AND = 0x00000000,
@ -585,7 +589,7 @@ enum LogicalOp {
}; };
// Logical immediate. // Logical immediate.
enum LogicalImmediateOp { enum LogicalImmediateOp : uint32_t {
LogicalImmediateFixed = 0x12000000, LogicalImmediateFixed = 0x12000000,
LogicalImmediateFMask = 0x1F800000, LogicalImmediateFMask = 0x1F800000,
LogicalImmediateMask = 0xFF800000, LogicalImmediateMask = 0xFF800000,
@ -600,7 +604,7 @@ enum LogicalImmediateOp {
}; };
// Logical shifted register. // Logical shifted register.
enum LogicalShiftedOp { enum LogicalShiftedOp : uint32_t {
LogicalShiftedFixed = 0x0A000000, LogicalShiftedFixed = 0x0A000000,
LogicalShiftedFMask = 0x1F000000, LogicalShiftedFMask = 0x1F000000,
LogicalShiftedMask = 0xFF200000, LogicalShiftedMask = 0xFF200000,
@ -631,7 +635,7 @@ enum LogicalShiftedOp {
}; };
// Move wide immediate. // Move wide immediate.
enum MoveWideImmediateOp { enum MoveWideImmediateOp : uint32_t {
MoveWideImmediateFixed = 0x12800000, MoveWideImmediateFixed = 0x12800000,
MoveWideImmediateFMask = 0x1F800000, MoveWideImmediateFMask = 0x1F800000,
MoveWideImmediateMask = 0xFF800000, MoveWideImmediateMask = 0xFF800000,
@ -648,7 +652,7 @@ enum MoveWideImmediateOp {
// Bitfield. // Bitfield.
const int kBitfieldNOffset = 22; const int kBitfieldNOffset = 22;
enum BitfieldOp { enum BitfieldOp : uint32_t {
BitfieldFixed = 0x13000000, BitfieldFixed = 0x13000000,
BitfieldFMask = 0x1F800000, BitfieldFMask = 0x1F800000,
BitfieldMask = 0xFF800000, BitfieldMask = 0xFF800000,
@ -665,7 +669,7 @@ enum BitfieldOp {
}; };
// Extract. // Extract.
enum ExtractOp { enum ExtractOp : uint32_t {
ExtractFixed = 0x13800000, ExtractFixed = 0x13800000,
ExtractFMask = 0x1F800000, ExtractFMask = 0x1F800000,
ExtractMask = 0xFFA00000, ExtractMask = 0xFFA00000,
@ -675,7 +679,7 @@ enum ExtractOp {
}; };
// Unconditional branch. // Unconditional branch.
enum UnconditionalBranchOp { enum UnconditionalBranchOp : uint32_t {
UnconditionalBranchFixed = 0x14000000, UnconditionalBranchFixed = 0x14000000,
UnconditionalBranchFMask = 0x7C000000, UnconditionalBranchFMask = 0x7C000000,
UnconditionalBranchMask = 0xFC000000, UnconditionalBranchMask = 0xFC000000,
@ -684,7 +688,7 @@ enum UnconditionalBranchOp {
}; };
// Unconditional branch to register. // Unconditional branch to register.
enum UnconditionalBranchToRegisterOp { enum UnconditionalBranchToRegisterOp : uint32_t {
UnconditionalBranchToRegisterFixed = 0xD6000000, UnconditionalBranchToRegisterFixed = 0xD6000000,
UnconditionalBranchToRegisterFMask = 0xFE000000, UnconditionalBranchToRegisterFMask = 0xFE000000,
UnconditionalBranchToRegisterMask = 0xFFFFFC1F, UnconditionalBranchToRegisterMask = 0xFFFFFC1F,
@ -694,7 +698,7 @@ enum UnconditionalBranchToRegisterOp {
}; };
// Compare and branch. // Compare and branch.
enum CompareBranchOp { enum CompareBranchOp : uint32_t {
CompareBranchFixed = 0x34000000, CompareBranchFixed = 0x34000000,
CompareBranchFMask = 0x7E000000, CompareBranchFMask = 0x7E000000,
CompareBranchMask = 0xFF000000, CompareBranchMask = 0xFF000000,
@ -707,7 +711,7 @@ enum CompareBranchOp {
}; };
// Test and branch. // Test and branch.
enum TestBranchOp { enum TestBranchOp : uint32_t {
TestBranchFixed = 0x36000000, TestBranchFixed = 0x36000000,
TestBranchFMask = 0x7E000000, TestBranchFMask = 0x7E000000,
TestBranchMask = 0x7F000000, TestBranchMask = 0x7F000000,
@ -716,7 +720,7 @@ enum TestBranchOp {
}; };
// Conditional branch. // Conditional branch.
enum ConditionalBranchOp { enum ConditionalBranchOp : uint32_t {
ConditionalBranchFixed = 0x54000000, ConditionalBranchFixed = 0x54000000,
ConditionalBranchFMask = 0xFE000000, ConditionalBranchFMask = 0xFE000000,
ConditionalBranchMask = 0xFF000010, ConditionalBranchMask = 0xFF000010,
@ -728,12 +732,12 @@ enum ConditionalBranchOp {
// and CR fields to encode parameters. To handle this cleanly, the system // and CR fields to encode parameters. To handle this cleanly, the system
// instructions are split into more than one enum. // instructions are split into more than one enum.
enum SystemOp { enum SystemOp : uint32_t {
SystemFixed = 0xD5000000, SystemFixed = 0xD5000000,
SystemFMask = 0xFFC00000 SystemFMask = 0xFFC00000
}; };
enum SystemSysRegOp { enum SystemSysRegOp : uint32_t {
SystemSysRegFixed = 0xD5100000, SystemSysRegFixed = 0xD5100000,
SystemSysRegFMask = 0xFFD00000, SystemSysRegFMask = 0xFFD00000,
SystemSysRegMask = 0xFFF00000, SystemSysRegMask = 0xFFF00000,
@ -741,7 +745,7 @@ enum SystemSysRegOp {
MSR = SystemSysRegFixed | 0x00000000 MSR = SystemSysRegFixed | 0x00000000
}; };
enum SystemHintOp { enum SystemHintOp : uint32_t {
SystemHintFixed = 0xD503201F, SystemHintFixed = 0xD503201F,
SystemHintFMask = 0xFFFFF01F, SystemHintFMask = 0xFFFFF01F,
SystemHintMask = 0xFFFFF01F, SystemHintMask = 0xFFFFF01F,
@ -749,7 +753,7 @@ enum SystemHintOp {
}; };
// Exception. // Exception.
enum ExceptionOp { enum ExceptionOp : uint32_t {
ExceptionFixed = 0xD4000000, ExceptionFixed = 0xD4000000,
ExceptionFMask = 0xFF000000, ExceptionFMask = 0xFF000000,
ExceptionMask = 0xFFE0001F, ExceptionMask = 0xFFE0001F,
@ -765,7 +769,7 @@ enum ExceptionOp {
// Code used to spot hlt instructions that should not be hit. // Code used to spot hlt instructions that should not be hit.
const int kHltBadCode = 0xbad; const int kHltBadCode = 0xbad;
enum MemBarrierOp { enum MemBarrierOp : uint32_t {
MemBarrierFixed = 0xD503309F, MemBarrierFixed = 0xD503309F,
MemBarrierFMask = 0xFFFFF09F, MemBarrierFMask = 0xFFFFF09F,
MemBarrierMask = 0xFFFFF0FF, MemBarrierMask = 0xFFFFF0FF,
@ -775,13 +779,13 @@ enum MemBarrierOp {
}; };
// Any load or store (including pair). // Any load or store (including pair).
enum LoadStoreAnyOp { enum LoadStoreAnyOp : uint32_t {
LoadStoreAnyFMask = 0x0a000000, LoadStoreAnyFMask = 0x0a000000,
LoadStoreAnyFixed = 0x08000000 LoadStoreAnyFixed = 0x08000000
}; };
// Any load pair or store pair. // Any load pair or store pair.
enum LoadStorePairAnyOp { enum LoadStorePairAnyOp : uint32_t {
LoadStorePairAnyFMask = 0x3a000000, LoadStorePairAnyFMask = 0x3a000000,
LoadStorePairAnyFixed = 0x28000000 LoadStorePairAnyFixed = 0x28000000
}; };
@ -794,7 +798,7 @@ enum LoadStorePairAnyOp {
V(LDP, q, 0x84400000) V(LDP, q, 0x84400000)
// Load/store pair (post, pre and offset.) // Load/store pair (post, pre and offset.)
enum LoadStorePairOp { enum LoadStorePairOp : uint32_t {
LoadStorePairMask = 0xC4400000, LoadStorePairMask = 0xC4400000,
LoadStorePairLBit = 1 << 22, LoadStorePairLBit = 1 << 22,
#define LOAD_STORE_PAIR(A, B, C) \ #define LOAD_STORE_PAIR(A, B, C) \
@ -803,7 +807,7 @@ enum LoadStorePairOp {
#undef LOAD_STORE_PAIR #undef LOAD_STORE_PAIR
}; };
enum LoadStorePairPostIndexOp { enum LoadStorePairPostIndexOp : uint32_t {
LoadStorePairPostIndexFixed = 0x28800000, LoadStorePairPostIndexFixed = 0x28800000,
LoadStorePairPostIndexFMask = 0x3B800000, LoadStorePairPostIndexFMask = 0x3B800000,
LoadStorePairPostIndexMask = 0xFFC00000, LoadStorePairPostIndexMask = 0xFFC00000,
@ -813,7 +817,7 @@ enum LoadStorePairPostIndexOp {
#undef LOAD_STORE_PAIR_POST_INDEX #undef LOAD_STORE_PAIR_POST_INDEX
}; };
enum LoadStorePairPreIndexOp { enum LoadStorePairPreIndexOp : uint32_t {
LoadStorePairPreIndexFixed = 0x29800000, LoadStorePairPreIndexFixed = 0x29800000,
LoadStorePairPreIndexFMask = 0x3B800000, LoadStorePairPreIndexFMask = 0x3B800000,
LoadStorePairPreIndexMask = 0xFFC00000, LoadStorePairPreIndexMask = 0xFFC00000,
@ -823,7 +827,7 @@ enum LoadStorePairPreIndexOp {
#undef LOAD_STORE_PAIR_PRE_INDEX #undef LOAD_STORE_PAIR_PRE_INDEX
}; };
enum LoadStorePairOffsetOp { enum LoadStorePairOffsetOp : uint32_t {
LoadStorePairOffsetFixed = 0x29000000, LoadStorePairOffsetFixed = 0x29000000,
LoadStorePairOffsetFMask = 0x3B800000, LoadStorePairOffsetFMask = 0x3B800000,
LoadStorePairOffsetMask = 0xFFC00000, LoadStorePairOffsetMask = 0xFFC00000,
@ -834,7 +838,7 @@ enum LoadStorePairOffsetOp {
}; };
// Load literal. // Load literal.
enum LoadLiteralOp { enum LoadLiteralOp : uint32_t {
LoadLiteralFixed = 0x18000000, LoadLiteralFixed = 0x18000000,
LoadLiteralFMask = 0x3B000000, LoadLiteralFMask = 0x3B000000,
LoadLiteralMask = 0xFF000000, LoadLiteralMask = 0xFF000000,
@ -876,7 +880,7 @@ enum LoadLiteralOp {
// clang-format on // clang-format on
// Load/store unscaled offset. // Load/store unscaled offset.
enum LoadStoreUnscaledOffsetOp { enum LoadStoreUnscaledOffsetOp : uint32_t {
LoadStoreUnscaledOffsetFixed = 0x38000000, LoadStoreUnscaledOffsetFixed = 0x38000000,
LoadStoreUnscaledOffsetFMask = 0x3B200C00, LoadStoreUnscaledOffsetFMask = 0x3B200C00,
LoadStoreUnscaledOffsetMask = 0xFFE00C00, LoadStoreUnscaledOffsetMask = 0xFFE00C00,
@ -887,7 +891,7 @@ enum LoadStoreUnscaledOffsetOp {
}; };
// Load/store (post, pre, offset and unsigned.) // Load/store (post, pre, offset and unsigned.)
enum LoadStoreOp { enum LoadStoreOp : uint32_t {
LoadStoreMask = 0xC4C00000, LoadStoreMask = 0xC4C00000,
#define LOAD_STORE(A, B, C, D) A##B##_##C = D #define LOAD_STORE(A, B, C, D) A##B##_##C = D
LOAD_STORE_OP_LIST(LOAD_STORE), LOAD_STORE_OP_LIST(LOAD_STORE),
@ -896,7 +900,7 @@ enum LoadStoreOp {
}; };
// Load/store post index. // Load/store post index.
enum LoadStorePostIndex { enum LoadStorePostIndex : uint32_t {
LoadStorePostIndexFixed = 0x38000400, LoadStorePostIndexFixed = 0x38000400,
LoadStorePostIndexFMask = 0x3B200C00, LoadStorePostIndexFMask = 0x3B200C00,
LoadStorePostIndexMask = 0xFFE00C00, LoadStorePostIndexMask = 0xFFE00C00,
@ -907,7 +911,7 @@ enum LoadStorePostIndex {
}; };
// Load/store pre index. // Load/store pre index.
enum LoadStorePreIndex { enum LoadStorePreIndex : uint32_t {
LoadStorePreIndexFixed = 0x38000C00, LoadStorePreIndexFixed = 0x38000C00,
LoadStorePreIndexFMask = 0x3B200C00, LoadStorePreIndexFMask = 0x3B200C00,
LoadStorePreIndexMask = 0xFFE00C00, LoadStorePreIndexMask = 0xFFE00C00,
@ -918,7 +922,7 @@ enum LoadStorePreIndex {
}; };
// Load/store unsigned offset. // Load/store unsigned offset.
enum LoadStoreUnsignedOffset { enum LoadStoreUnsignedOffset : uint32_t {
LoadStoreUnsignedOffsetFixed = 0x39000000, LoadStoreUnsignedOffsetFixed = 0x39000000,
LoadStoreUnsignedOffsetFMask = 0x3B000000, LoadStoreUnsignedOffsetFMask = 0x3B000000,
LoadStoreUnsignedOffsetMask = 0xFFC00000, LoadStoreUnsignedOffsetMask = 0xFFC00000,
@ -930,7 +934,7 @@ enum LoadStoreUnsignedOffset {
}; };
// Load/store register offset. // Load/store register offset.
enum LoadStoreRegisterOffset { enum LoadStoreRegisterOffset : uint32_t {
LoadStoreRegisterOffsetFixed = 0x38200800, LoadStoreRegisterOffsetFixed = 0x38200800,
LoadStoreRegisterOffsetFMask = 0x3B200C00, LoadStoreRegisterOffsetFMask = 0x3B200C00,
LoadStoreRegisterOffsetMask = 0xFFE00C00, LoadStoreRegisterOffsetMask = 0xFFE00C00,
@ -942,7 +946,7 @@ enum LoadStoreRegisterOffset {
}; };
// Load/store acquire/release. // Load/store acquire/release.
enum LoadStoreAcquireReleaseOp { enum LoadStoreAcquireReleaseOp : uint32_t {
LoadStoreAcquireReleaseFixed = 0x08000000, LoadStoreAcquireReleaseFixed = 0x08000000,
LoadStoreAcquireReleaseFMask = 0x3F000000, LoadStoreAcquireReleaseFMask = 0x3F000000,
LoadStoreAcquireReleaseMask = 0xCFC08000, LoadStoreAcquireReleaseMask = 0xCFC08000,
@ -965,14 +969,14 @@ enum LoadStoreAcquireReleaseOp {
}; };
// Conditional compare. // Conditional compare.
enum ConditionalCompareOp { enum ConditionalCompareOp : uint32_t {
ConditionalCompareMask = 0x60000000, ConditionalCompareMask = 0x60000000,
CCMN = 0x20000000, CCMN = 0x20000000,
CCMP = 0x60000000 CCMP = 0x60000000
}; };
// Conditional compare register. // Conditional compare register.
enum ConditionalCompareRegisterOp { enum ConditionalCompareRegisterOp : uint32_t {
ConditionalCompareRegisterFixed = 0x1A400000, ConditionalCompareRegisterFixed = 0x1A400000,
ConditionalCompareRegisterFMask = 0x1FE00800, ConditionalCompareRegisterFMask = 0x1FE00800,
ConditionalCompareRegisterMask = 0xFFE00C10, ConditionalCompareRegisterMask = 0xFFE00C10,
@ -983,7 +987,7 @@ enum ConditionalCompareRegisterOp {
}; };
// Conditional compare immediate. // Conditional compare immediate.
enum ConditionalCompareImmediateOp { enum ConditionalCompareImmediateOp : uint32_t {
ConditionalCompareImmediateFixed = 0x1A400800, ConditionalCompareImmediateFixed = 0x1A400800,
ConditionalCompareImmediateFMask = 0x1FE00800, ConditionalCompareImmediateFMask = 0x1FE00800,
ConditionalCompareImmediateMask = 0xFFE00C10, ConditionalCompareImmediateMask = 0xFFE00C10,
@ -994,7 +998,7 @@ enum ConditionalCompareImmediateOp {
}; };
// Conditional select. // Conditional select.
enum ConditionalSelectOp { enum ConditionalSelectOp : uint32_t {
ConditionalSelectFixed = 0x1A800000, ConditionalSelectFixed = 0x1A800000,
ConditionalSelectFMask = 0x1FE00000, ConditionalSelectFMask = 0x1FE00000,
ConditionalSelectMask = 0xFFE00C00, ConditionalSelectMask = 0xFFE00C00,
@ -1013,7 +1017,7 @@ enum ConditionalSelectOp {
}; };
// Data processing 1 source. // Data processing 1 source.
enum DataProcessing1SourceOp { enum DataProcessing1SourceOp : uint32_t {
DataProcessing1SourceFixed = 0x5AC00000, DataProcessing1SourceFixed = 0x5AC00000,
DataProcessing1SourceFMask = 0x5FE00000, DataProcessing1SourceFMask = 0x5FE00000,
DataProcessing1SourceMask = 0xFFFFFC00, DataProcessing1SourceMask = 0xFFFFFC00,
@ -1036,7 +1040,7 @@ enum DataProcessing1SourceOp {
}; };
// Data processing 2 source. // Data processing 2 source.
enum DataProcessing2SourceOp { enum DataProcessing2SourceOp : uint32_t {
DataProcessing2SourceFixed = 0x1AC00000, DataProcessing2SourceFixed = 0x1AC00000,
DataProcessing2SourceFMask = 0x5FE00000, DataProcessing2SourceFMask = 0x5FE00000,
DataProcessing2SourceMask = 0xFFE0FC00, DataProcessing2SourceMask = 0xFFE0FC00,
@ -1069,7 +1073,7 @@ enum DataProcessing2SourceOp {
}; };
// Data processing 3 source. // Data processing 3 source.
enum DataProcessing3SourceOp { enum DataProcessing3SourceOp : uint32_t {
DataProcessing3SourceFixed = 0x1B000000, DataProcessing3SourceFixed = 0x1B000000,
DataProcessing3SourceFMask = 0x1F000000, DataProcessing3SourceFMask = 0x1F000000,
DataProcessing3SourceMask = 0xFFE08000, DataProcessing3SourceMask = 0xFFE08000,
@ -1088,7 +1092,7 @@ enum DataProcessing3SourceOp {
}; };
// Floating point compare. // Floating point compare.
enum FPCompareOp { enum FPCompareOp : uint32_t {
FPCompareFixed = 0x1E202000, FPCompareFixed = 0x1E202000,
FPCompareFMask = 0x5F203C00, FPCompareFMask = 0x5F203C00,
FPCompareMask = 0xFFE0FC1F, FPCompareMask = 0xFFE0FC1F,
@ -1105,7 +1109,7 @@ enum FPCompareOp {
}; };
// Floating point conditional compare. // Floating point conditional compare.
enum FPConditionalCompareOp { enum FPConditionalCompareOp : uint32_t {
FPConditionalCompareFixed = 0x1E200400, FPConditionalCompareFixed = 0x1E200400,
FPConditionalCompareFMask = 0x5F200C00, FPConditionalCompareFMask = 0x5F200C00,
FPConditionalCompareMask = 0xFFE00C10, FPConditionalCompareMask = 0xFFE00C10,
@ -1118,7 +1122,7 @@ enum FPConditionalCompareOp {
}; };
// Floating point conditional select. // Floating point conditional select.
enum FPConditionalSelectOp { enum FPConditionalSelectOp : uint32_t {
FPConditionalSelectFixed = 0x1E200C00, FPConditionalSelectFixed = 0x1E200C00,
FPConditionalSelectFMask = 0x5F200C00, FPConditionalSelectFMask = 0x5F200C00,
FPConditionalSelectMask = 0xFFE00C00, FPConditionalSelectMask = 0xFFE00C00,
@ -1128,7 +1132,7 @@ enum FPConditionalSelectOp {
}; };
// Floating point immediate. // Floating point immediate.
enum FPImmediateOp { enum FPImmediateOp : uint32_t {
FPImmediateFixed = 0x1E201000, FPImmediateFixed = 0x1E201000,
FPImmediateFMask = 0x5F201C00, FPImmediateFMask = 0x5F201C00,
FPImmediateMask = 0xFFE01C00, FPImmediateMask = 0xFFE01C00,
@ -1137,7 +1141,7 @@ enum FPImmediateOp {
}; };
// Floating point data processing 1 source. // Floating point data processing 1 source.
enum FPDataProcessing1SourceOp { enum FPDataProcessing1SourceOp : uint32_t {
FPDataProcessing1SourceFixed = 0x1E204000, FPDataProcessing1SourceFixed = 0x1E204000,
FPDataProcessing1SourceFMask = 0x5F207C00, FPDataProcessing1SourceFMask = 0x5F207C00,
FPDataProcessing1SourceMask = 0xFFFFFC00, FPDataProcessing1SourceMask = 0xFFFFFC00,
@ -1183,7 +1187,7 @@ enum FPDataProcessing1SourceOp {
}; };
// Floating point data processing 2 source. // Floating point data processing 2 source.
enum FPDataProcessing2SourceOp { enum FPDataProcessing2SourceOp : uint32_t {
FPDataProcessing2SourceFixed = 0x1E200800, FPDataProcessing2SourceFixed = 0x1E200800,
FPDataProcessing2SourceFMask = 0x5F200C00, FPDataProcessing2SourceFMask = 0x5F200C00,
FPDataProcessing2SourceMask = 0xFFE0FC00, FPDataProcessing2SourceMask = 0xFFE0FC00,
@ -1217,7 +1221,7 @@ enum FPDataProcessing2SourceOp {
}; };
// Floating point data processing 3 source. // Floating point data processing 3 source.
enum FPDataProcessing3SourceOp { enum FPDataProcessing3SourceOp : uint32_t {
FPDataProcessing3SourceFixed = 0x1F000000, FPDataProcessing3SourceFixed = 0x1F000000,
FPDataProcessing3SourceFMask = 0x5F000000, FPDataProcessing3SourceFMask = 0x5F000000,
FPDataProcessing3SourceMask = 0xFFE08000, FPDataProcessing3SourceMask = 0xFFE08000,
@ -1232,7 +1236,7 @@ enum FPDataProcessing3SourceOp {
}; };
// Conversion between floating point and integer. // Conversion between floating point and integer.
enum FPIntegerConvertOp { enum FPIntegerConvertOp : uint32_t {
FPIntegerConvertFixed = 0x1E200000, FPIntegerConvertFixed = 0x1E200000,
FPIntegerConvertFMask = 0x5F20FC00, FPIntegerConvertFMask = 0x5F20FC00,
FPIntegerConvertMask = 0xFFFFFC00, FPIntegerConvertMask = 0xFFFFFC00,
@ -1305,7 +1309,7 @@ enum FPIntegerConvertOp {
}; };
// Conversion between fixed point and floating point. // Conversion between fixed point and floating point.
enum FPFixedPointConvertOp { enum FPFixedPointConvertOp : uint32_t {
FPFixedPointConvertFixed = 0x1E000000, FPFixedPointConvertFixed = 0x1E000000,
FPFixedPointConvertFMask = 0x5F200000, FPFixedPointConvertFMask = 0x5F200000,
FPFixedPointConvertMask = 0xFFFF0000, FPFixedPointConvertMask = 0xFFFF0000,
@ -1332,7 +1336,7 @@ enum FPFixedPointConvertOp {
}; };
// NEON instructions with two register operands. // NEON instructions with two register operands.
enum NEON2RegMiscOp { enum NEON2RegMiscOp : uint32_t {
NEON2RegMiscFixed = 0x0E200800, NEON2RegMiscFixed = 0x0E200800,
NEON2RegMiscFMask = 0x9F3E0C00, NEON2RegMiscFMask = 0x9F3E0C00,
NEON2RegMiscMask = 0xBF3FFC00, NEON2RegMiscMask = 0xBF3FFC00,
@ -1414,7 +1418,7 @@ enum NEON2RegMiscOp {
}; };
// NEON instructions with three same-type operands. // NEON instructions with three same-type operands.
enum NEON3SameOp { enum NEON3SameOp : uint32_t {
NEON3SameFixed = 0x0E200400, NEON3SameFixed = 0x0E200400,
NEON3SameFMask = 0x9F200400, NEON3SameFMask = 0x9F200400,
NEON3SameMask = 0xBF20FC00, NEON3SameMask = 0xBF20FC00,
@ -1510,7 +1514,7 @@ enum NEON3SameOp {
}; };
// NEON instructions with three different-type operands. // NEON instructions with three different-type operands.
enum NEON3DifferentOp { enum NEON3DifferentOp : uint32_t {
NEON3DifferentFixed = 0x0E200000, NEON3DifferentFixed = 0x0E200000,
NEON3DifferentFMask = 0x9F200C00, NEON3DifferentFMask = 0x9F200C00,
NEON3DifferentMask = 0xFF20FC00, NEON3DifferentMask = 0xFF20FC00,
@ -1569,7 +1573,7 @@ enum NEON3DifferentOp {
}; };
// NEON instructions operating across vectors. // NEON instructions operating across vectors.
enum NEONAcrossLanesOp { enum NEONAcrossLanesOp : uint32_t {
NEONAcrossLanesFixed = 0x0E300800, NEONAcrossLanesFixed = 0x0E300800,
NEONAcrossLanesFMask = 0x9F3E0C00, NEONAcrossLanesFMask = 0x9F3E0C00,
NEONAcrossLanesMask = 0xBF3FFC00, NEONAcrossLanesMask = 0xBF3FFC00,
@ -1593,7 +1597,7 @@ enum NEONAcrossLanesOp {
}; };
// NEON instructions with indexed element operand. // NEON instructions with indexed element operand.
enum NEONByIndexedElementOp { enum NEONByIndexedElementOp : uint32_t {
NEONByIndexedElementFixed = 0x0F000000, NEONByIndexedElementFixed = 0x0F000000,
NEONByIndexedElementFMask = 0x9F000400, NEONByIndexedElementFMask = 0x9F000400,
NEONByIndexedElementMask = 0xBF00F400, NEONByIndexedElementMask = 0xBF00F400,
@ -1622,7 +1626,7 @@ enum NEONByIndexedElementOp {
}; };
// NEON modified immediate. // NEON modified immediate.
enum NEONModifiedImmediateOp { enum NEONModifiedImmediateOp : uint32_t {
NEONModifiedImmediateFixed = 0x0F000400, NEONModifiedImmediateFixed = 0x0F000400,
NEONModifiedImmediateFMask = 0x9FF80400, NEONModifiedImmediateFMask = 0x9FF80400,
NEONModifiedImmediateOpBit = 0x20000000, NEONModifiedImmediateOpBit = 0x20000000,
@ -1633,14 +1637,14 @@ enum NEONModifiedImmediateOp {
}; };
// NEON extract. // NEON extract.
enum NEONExtractOp { enum NEONExtractOp : uint32_t {
NEONExtractFixed = 0x2E000000, NEONExtractFixed = 0x2E000000,
NEONExtractFMask = 0xBF208400, NEONExtractFMask = 0xBF208400,
NEONExtractMask = 0xBFE08400, NEONExtractMask = 0xBFE08400,
NEON_EXT = NEONExtractFixed | 0x00000000 NEON_EXT = NEONExtractFixed | 0x00000000
}; };
enum NEONLoadStoreMultiOp { enum NEONLoadStoreMultiOp : uint32_t {
NEONLoadStoreMultiL = 0x00400000, NEONLoadStoreMultiL = 0x00400000,
NEONLoadStoreMulti1_1v = 0x00007000, NEONLoadStoreMulti1_1v = 0x00007000,
NEONLoadStoreMulti1_2v = 0x0000A000, NEONLoadStoreMulti1_2v = 0x0000A000,
@ -1652,7 +1656,7 @@ enum NEONLoadStoreMultiOp {
}; };
// NEON load/store multiple structures. // NEON load/store multiple structures.
enum NEONLoadStoreMultiStructOp { enum NEONLoadStoreMultiStructOp : uint32_t {
NEONLoadStoreMultiStructFixed = 0x0C000000, NEONLoadStoreMultiStructFixed = 0x0C000000,
NEONLoadStoreMultiStructFMask = 0xBFBF0000, NEONLoadStoreMultiStructFMask = 0xBFBF0000,
NEONLoadStoreMultiStructMask = 0xBFFFF000, NEONLoadStoreMultiStructMask = 0xBFFFF000,
@ -1676,7 +1680,7 @@ enum NEONLoadStoreMultiStructOp {
}; };
// NEON load/store multiple structures with post-index addressing. // NEON load/store multiple structures with post-index addressing.
enum NEONLoadStoreMultiStructPostIndexOp { enum NEONLoadStoreMultiStructPostIndexOp : uint32_t {
NEONLoadStoreMultiStructPostIndexFixed = 0x0C800000, NEONLoadStoreMultiStructPostIndexFixed = 0x0C800000,
NEONLoadStoreMultiStructPostIndexFMask = 0xBFA00000, NEONLoadStoreMultiStructPostIndexFMask = 0xBFA00000,
NEONLoadStoreMultiStructPostIndexMask = 0xBFE0F000, NEONLoadStoreMultiStructPostIndexMask = 0xBFE0F000,
@ -1697,7 +1701,7 @@ enum NEONLoadStoreMultiStructPostIndexOp {
NEON_ST4_post = NEON_ST4 | NEONLoadStoreMultiStructPostIndex NEON_ST4_post = NEON_ST4 | NEONLoadStoreMultiStructPostIndex
}; };
enum NEONLoadStoreSingleOp { enum NEONLoadStoreSingleOp : uint32_t {
NEONLoadStoreSingle1 = 0x00000000, NEONLoadStoreSingle1 = 0x00000000,
NEONLoadStoreSingle2 = 0x00200000, NEONLoadStoreSingle2 = 0x00200000,
NEONLoadStoreSingle3 = 0x00002000, NEONLoadStoreSingle3 = 0x00002000,
@ -1712,7 +1716,7 @@ enum NEONLoadStoreSingleOp {
}; };
// NEON load/store single structure. // NEON load/store single structure.
enum NEONLoadStoreSingleStructOp { enum NEONLoadStoreSingleStructOp : uint32_t {
NEONLoadStoreSingleStructFixed = 0x0D000000, NEONLoadStoreSingleStructFixed = 0x0D000000,
NEONLoadStoreSingleStructFMask = 0xBF9F0000, NEONLoadStoreSingleStructFMask = 0xBF9F0000,
NEONLoadStoreSingleStructMask = 0xBFFFE000, NEONLoadStoreSingleStructMask = 0xBFFFE000,
@ -1777,7 +1781,7 @@ enum NEONLoadStoreSingleStructOp {
}; };
// NEON load/store single structure with post-index addressing. // NEON load/store single structure with post-index addressing.
enum NEONLoadStoreSingleStructPostIndexOp { enum NEONLoadStoreSingleStructPostIndexOp : uint32_t {
NEONLoadStoreSingleStructPostIndexFixed = 0x0D800000, NEONLoadStoreSingleStructPostIndexFixed = 0x0D800000,
NEONLoadStoreSingleStructPostIndexFMask = 0xBF800000, NEONLoadStoreSingleStructPostIndexFMask = 0xBF800000,
NEONLoadStoreSingleStructPostIndexMask = 0xBFE0E000, NEONLoadStoreSingleStructPostIndexMask = 0xBFE0E000,
@ -1824,7 +1828,7 @@ enum NEONLoadStoreSingleStructPostIndexOp {
}; };
// NEON register copy. // NEON register copy.
enum NEONCopyOp { enum NEONCopyOp : uint32_t {
NEONCopyFixed = 0x0E000400, NEONCopyFixed = 0x0E000400,
NEONCopyFMask = 0x9FE08400, NEONCopyFMask = 0x9FE08400,
NEONCopyMask = 0x3FE08400, NEONCopyMask = 0x3FE08400,
@ -1843,7 +1847,7 @@ enum NEONCopyOp {
}; };
// NEON scalar instructions with indexed element operand. // NEON scalar instructions with indexed element operand.
enum NEONScalarByIndexedElementOp { enum NEONScalarByIndexedElementOp : uint32_t {
NEONScalarByIndexedElementFixed = 0x5F000000, NEONScalarByIndexedElementFixed = 0x5F000000,
NEONScalarByIndexedElementFMask = 0xDF000400, NEONScalarByIndexedElementFMask = 0xDF000400,
NEONScalarByIndexedElementMask = 0xFF00F400, NEONScalarByIndexedElementMask = 0xFF00F400,
@ -1866,7 +1870,7 @@ enum NEONScalarByIndexedElementOp {
}; };
// NEON shift immediate. // NEON shift immediate.
enum NEONShiftImmediateOp { enum NEONShiftImmediateOp : uint32_t {
NEONShiftImmediateFixed = 0x0F000400, NEONShiftImmediateFixed = 0x0F000400,
NEONShiftImmediateFMask = 0x9F800400, NEONShiftImmediateFMask = 0x9F800400,
NEONShiftImmediateMask = 0xBF80FC00, NEONShiftImmediateMask = 0xBF80FC00,
@ -1902,7 +1906,7 @@ enum NEONShiftImmediateOp {
}; };
// NEON scalar register copy. // NEON scalar register copy.
enum NEONScalarCopyOp { enum NEONScalarCopyOp : uint32_t {
NEONScalarCopyFixed = 0x5E000400, NEONScalarCopyFixed = 0x5E000400,
NEONScalarCopyFMask = 0xDFE08400, NEONScalarCopyFMask = 0xDFE08400,
NEONScalarCopyMask = 0xFFE0FC00, NEONScalarCopyMask = 0xFFE0FC00,
@ -1910,7 +1914,7 @@ enum NEONScalarCopyOp {
}; };
// NEON scalar pairwise instructions. // NEON scalar pairwise instructions.
enum NEONScalarPairwiseOp { enum NEONScalarPairwiseOp : uint32_t {
NEONScalarPairwiseFixed = 0x5E300800, NEONScalarPairwiseFixed = 0x5E300800,
NEONScalarPairwiseFMask = 0xDF3E0C00, NEONScalarPairwiseFMask = 0xDF3E0C00,
NEONScalarPairwiseMask = 0xFFB1F800, NEONScalarPairwiseMask = 0xFFB1F800,
@ -1923,7 +1927,7 @@ enum NEONScalarPairwiseOp {
}; };
// NEON scalar shift immediate. // NEON scalar shift immediate.
enum NEONScalarShiftImmediateOp { enum NEONScalarShiftImmediateOp : uint32_t {
NEONScalarShiftImmediateFixed = 0x5F000400, NEONScalarShiftImmediateFixed = 0x5F000400,
NEONScalarShiftImmediateFMask = 0xDF800400, NEONScalarShiftImmediateFMask = 0xDF800400,
NEONScalarShiftImmediateMask = 0xFF80FC00, NEONScalarShiftImmediateMask = 0xFF80FC00,
@ -1954,7 +1958,7 @@ enum NEONScalarShiftImmediateOp {
}; };
// NEON table. // NEON table.
enum NEONTableOp { enum NEONTableOp : uint32_t {
NEONTableFixed = 0x0E000000, NEONTableFixed = 0x0E000000,
NEONTableFMask = 0xBF208C00, NEONTableFMask = 0xBF208C00,
NEONTableExt = 0x00001000, NEONTableExt = 0x00001000,
@ -1970,7 +1974,7 @@ enum NEONTableOp {
}; };
// NEON perm. // NEON perm.
enum NEONPermOp { enum NEONPermOp : uint32_t {
NEONPermFixed = 0x0E000800, NEONPermFixed = 0x0E000800,
NEONPermFMask = 0xBF208C00, NEONPermFMask = 0xBF208C00,
NEONPermMask = 0x3F20FC00, NEONPermMask = 0x3F20FC00,
@ -1983,7 +1987,7 @@ enum NEONPermOp {
}; };
// NEON scalar instructions with two register operands. // NEON scalar instructions with two register operands.
enum NEONScalar2RegMiscOp { enum NEONScalar2RegMiscOp : uint32_t {
NEONScalar2RegMiscFixed = 0x5E200800, NEONScalar2RegMiscFixed = 0x5E200800,
NEONScalar2RegMiscFMask = 0xDF3E0C00, NEONScalar2RegMiscFMask = 0xDF3E0C00,
NEONScalar2RegMiscMask = NEON_Q | NEONScalar | NEON2RegMiscMask, NEONScalar2RegMiscMask = NEON_Q | NEONScalar | NEON2RegMiscMask,
@ -2030,7 +2034,7 @@ enum NEONScalar2RegMiscOp {
}; };
// NEON scalar instructions with three same-type operands. // NEON scalar instructions with three same-type operands.
enum NEONScalar3SameOp { enum NEONScalar3SameOp : uint32_t {
NEONScalar3SameFixed = 0x5E200400, NEONScalar3SameFixed = 0x5E200400,
NEONScalar3SameFMask = 0xDF200400, NEONScalar3SameFMask = 0xDF200400,
NEONScalar3SameMask = 0xFF20FC00, NEONScalar3SameMask = 0xFF20FC00,
@ -2073,7 +2077,7 @@ enum NEONScalar3SameOp {
}; };
// NEON scalar instructions with three different-type operands. // NEON scalar instructions with three different-type operands.
enum NEONScalar3DiffOp { enum NEONScalar3DiffOp : uint32_t {
NEONScalar3DiffFixed = 0x5E200000, NEONScalar3DiffFixed = 0x5E200000,
NEONScalar3DiffFMask = 0xDF200C00, NEONScalar3DiffFMask = 0xDF200C00,
NEONScalar3DiffMask = NEON_Q | NEONScalar | NEON3DifferentMask, NEONScalar3DiffMask = NEON_Q | NEONScalar | NEON3DifferentMask,
@ -2084,12 +2088,12 @@ enum NEONScalar3DiffOp {
// Unimplemented and unallocated instructions. These are defined to make fixed // Unimplemented and unallocated instructions. These are defined to make fixed
// bit assertion easier. // bit assertion easier.
enum UnimplementedOp { enum UnimplementedOp : uint32_t {
UnimplementedFixed = 0x00000000, UnimplementedFixed = 0x00000000,
UnimplementedFMask = 0x00000000 UnimplementedFMask = 0x00000000
}; };
enum UnallocatedOp { enum UnallocatedOp : uint32_t {
UnallocatedFixed = 0x00000000, UnallocatedFixed = 0x00000000,
UnallocatedFMask = 0x00000000 UnallocatedFMask = 0x00000000
}; };

View File

@ -15,7 +15,7 @@ namespace internal {
class CacheLineSizes { class CacheLineSizes {
public: public:
CacheLineSizes() { CacheLineSizes() {
#ifdef USE_SIMULATOR #if defined(USE_SIMULATOR) || defined(V8_OS_WIN)
cache_type_register_ = 0; cache_type_register_ = 0;
#else #else
// Copy the content of the cache type register to a core register. // Copy the content of the cache type register to a core register.
@ -38,7 +38,9 @@ class CacheLineSizes {
}; };
void CpuFeatures::FlushICache(void* address, size_t length) { void CpuFeatures::FlushICache(void* address, size_t length) {
#ifdef V8_HOST_ARCH_ARM64 #if defined(V8_OS_WIN)
FlushInstructionCache(GetCurrentProcess(), address, length);
#elif defined(V8_HOST_ARCH_ARM64)
// The code below assumes user space cache operations are allowed. The goal // The code below assumes user space cache operations are allowed. The goal
// of this routine is to make sure the code generated is visible to the I // of this routine is to make sure the code generated is visible to the I
// side of the CPU. // side of the CPU.

View File

@ -69,11 +69,24 @@ void RestoreRegList(MacroAssembler* masm, const CPURegList& reg_list,
Register src = temps.AcquireX(); Register src = temps.AcquireX();
masm->Add(src, src_base, src_offset); masm->Add(src, src_base, src_offset);
#if defined(V8_OS_WIN)
// x18 is reserved as platform register on Windows.
restore_list.Remove(x18);
#endif
// Restore every register in restore_list from src. // Restore every register in restore_list from src.
while (!restore_list.IsEmpty()) { while (!restore_list.IsEmpty()) {
CPURegister reg0 = restore_list.PopLowestIndex(); CPURegister reg0 = restore_list.PopLowestIndex();
CPURegister reg1 = restore_list.PopLowestIndex(); CPURegister reg1 = restore_list.PopLowestIndex();
int offset0 = reg0.code() * reg_size; int offset0 = reg0.code() * reg_size;
#if defined(V8_OS_WIN)
if (reg1 == NoCPUReg) {
masm->Ldr(reg0, MemOperand(src, offset0));
break;
}
#endif
int offset1 = reg1.code() * reg_size; int offset1 = reg1.code() * reg_size;
// Pair up adjacent loads, otherwise read them separately. // Pair up adjacent loads, otherwise read them separately.

View File

@ -3744,7 +3744,7 @@ int DisassemblingDecoder::SubstituteImmediateField(Instruction* instr,
uint64_t imm8 = instr->ImmNEONabcdefgh(); uint64_t imm8 = instr->ImmNEONabcdefgh();
uint64_t imm = 0; uint64_t imm = 0;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
if (imm8 & (1 << i)) { if (imm8 & (1ULL << i)) {
imm |= (UINT64_C(0xFF) << (8 * i)); imm |= (UINT64_C(0xFF) << (8 * i));
} }
} }

View File

@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
#include <cstdint> #include <cstdint>
#include "include/v8config.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -21,6 +22,10 @@ namespace internal {
// then move this code back into instructions-arm64.cc with the same types // then move this code back into instructions-arm64.cc with the same types
// that client code uses. // that client code uses.
#if defined(V8_OS_WIN)
extern "C" {
#endif
extern const uint16_t kFP16PositiveInfinity = 0x7C00; extern const uint16_t kFP16PositiveInfinity = 0x7C00;
extern const uint16_t kFP16NegativeInfinity = 0xFC00; extern const uint16_t kFP16NegativeInfinity = 0xFC00;
extern const uint32_t kFP32PositiveInfinity = 0x7F800000; extern const uint32_t kFP32PositiveInfinity = 0x7F800000;
@ -42,5 +47,9 @@ extern const uint64_t kFP64DefaultNaN = 0x7FF8000000000000UL;
extern const uint32_t kFP32DefaultNaN = 0x7FC00000; extern const uint32_t kFP32DefaultNaN = 0x7FC00000;
extern const uint16_t kFP16DefaultNaN = 0x7E00; extern const uint16_t kFP16DefaultNaN = 0x7E00;
#if defined(V8_OS_WIN)
} // end of extern "C"
#endif
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8

View File

@ -72,7 +72,7 @@ static uint64_t RotateRight(uint64_t value,
unsigned int width) { unsigned int width) {
DCHECK_LE(width, 64); DCHECK_LE(width, 64);
rotate &= 63; rotate &= 63;
return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) | return ((value & ((1ULL << rotate) - 1ULL)) << (width - rotate)) |
(value >> rotate); (value >> rotate);
} }
@ -83,7 +83,7 @@ static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
DCHECK((width == 2) || (width == 4) || (width == 8) || (width == 16) || DCHECK((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
(width == 32)); (width == 32));
DCHECK((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits)); DCHECK((reg_size == kWRegSizeInBits) || (reg_size == kXRegSizeInBits));
uint64_t result = value & ((1UL << width) - 1UL); uint64_t result = value & ((1ULL << width) - 1ULL);
for (unsigned i = width; i < reg_size; i *= 2) { for (unsigned i = width; i < reg_size; i *= 2) {
result |= (result << i); result |= (result << i);
} }
@ -121,7 +121,7 @@ uint64_t Instruction::ImmLogical() {
if (imm_s == 0x3F) { if (imm_s == 0x3F) {
return 0; return 0;
} }
uint64_t bits = (1UL << (imm_s + 1)) - 1; uint64_t bits = (1ULL << (imm_s + 1)) - 1;
return RotateRight(bits, imm_r, 64); return RotateRight(bits, imm_r, 64);
} else { } else {
if ((imm_s >> 1) == 0x1F) { if ((imm_s >> 1) == 0x1F) {
@ -133,7 +133,7 @@ uint64_t Instruction::ImmLogical() {
if ((imm_s & mask) == mask) { if ((imm_s & mask) == mask) {
return 0; return 0;
} }
uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1; uint64_t bits = (1ULL << ((imm_s & mask) + 1)) - 1;
return RepeatBitsAcrossReg(reg_size, return RepeatBitsAcrossReg(reg_size,
RotateRight(bits, imm_r & mask, width), RotateRight(bits, imm_r & mask, width),
width); width);

View File

@ -19,6 +19,10 @@ struct AssemblerOptions;
typedef uint32_t Instr; typedef uint32_t Instr;
#if defined(V8_OS_WIN)
extern "C" {
#endif
extern const float16 kFP16PositiveInfinity; extern const float16 kFP16PositiveInfinity;
extern const float16 kFP16NegativeInfinity; extern const float16 kFP16NegativeInfinity;
extern const float kFP32PositiveInfinity; extern const float kFP32PositiveInfinity;
@ -40,6 +44,10 @@ extern const double kFP64DefaultNaN;
extern const float kFP32DefaultNaN; extern const float kFP32DefaultNaN;
extern const float16 kFP16DefaultNaN; extern const float16 kFP16DefaultNaN;
#if defined(V8_OS_WIN)
} // end of extern "C"
#endif
unsigned CalcLSDataSize(LoadStoreOp op); unsigned CalcLSDataSize(LoadStoreOp op);
unsigned CalcLSPairDataSize(LoadStorePairOp op); unsigned CalcLSPairDataSize(LoadStorePairOp op);

View File

@ -53,13 +53,27 @@ int TurboAssembler::RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion) const { Register exclusion) const {
int bytes = 0; int bytes = 0;
auto list = kCallerSaved; auto list = kCallerSaved;
DCHECK_EQ(list.Count() % 2, 0);
// We only allow one exclusion register, so if the list is of even length // We only allow one exclusion register, so if the list is of even length
// before exclusions, it must still be afterwards, to maintain alignment. // before exclusions, it must still be afterwards, to maintain alignment.
// Therefore, we can ignore the exclusion register in the computation. // Therefore, we can ignore the exclusion register in the computation.
// However, we leave it in the argument list to mirror the prototype for // However, we leave it in the argument list to mirror the prototype for
// Push/PopCallerSaved(). // Push/PopCallerSaved().
#if defined(V8_OS_WIN)
// X18 is excluded from caller-saved register list on Windows ARM64 which
// makes caller-saved registers in odd number. padreg is used accordingly
// to maintain the alignment.
DCHECK_EQ(list.Count() % 2, 1);
if (exclusion.Is(no_reg)) {
bytes += kXRegSizeInBits / 8;
} else {
bytes -= kXRegSizeInBits / 8;
}
#else
DCHECK_EQ(list.Count() % 2, 0);
USE(exclusion); USE(exclusion);
#endif
bytes += list.Count() * kXRegSizeInBits / 8; bytes += list.Count() * kXRegSizeInBits / 8;
if (fp_mode == kSaveFPRegs) { if (fp_mode == kSaveFPRegs) {
@ -73,12 +87,24 @@ int TurboAssembler::PushCallerSaved(SaveFPRegsMode fp_mode,
Register exclusion) { Register exclusion) {
int bytes = 0; int bytes = 0;
auto list = kCallerSaved; auto list = kCallerSaved;
DCHECK_EQ(list.Count() % 2, 0);
#if defined(V8_OS_WIN)
// X18 is excluded from caller-saved register list on Windows ARM64, use
// padreg accordingly to maintain alignment.
if (!exclusion.Is(no_reg)) {
list.Remove(exclusion);
} else {
list.Combine(padreg);
}
#else
if (!exclusion.Is(no_reg)) { if (!exclusion.Is(no_reg)) {
// Replace the excluded register with padding to maintain alignment. // Replace the excluded register with padding to maintain alignment.
list.Remove(exclusion); list.Remove(exclusion);
list.Combine(padreg); list.Combine(padreg);
} }
#endif
DCHECK_EQ(list.Count() % 2, 0);
PushCPURegList(list); PushCPURegList(list);
bytes += list.Count() * kXRegSizeInBits / 8; bytes += list.Count() * kXRegSizeInBits / 8;
@ -99,12 +125,24 @@ int TurboAssembler::PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion) {
} }
auto list = kCallerSaved; auto list = kCallerSaved;
DCHECK_EQ(list.Count() % 2, 0);
#if defined(V8_OS_WIN)
// X18 is excluded from caller-saved register list on Windows ARM64, use
// padreg accordingly to maintain alignment.
if (!exclusion.Is(no_reg)) {
list.Remove(exclusion);
} else {
list.Combine(padreg);
}
#else
if (!exclusion.Is(no_reg)) { if (!exclusion.Is(no_reg)) {
// Replace the excluded register with padding to maintain alignment. // Replace the excluded register with padding to maintain alignment.
list.Remove(exclusion); list.Remove(exclusion);
list.Combine(padreg); list.Combine(padreg);
} }
#endif
DCHECK_EQ(list.Count() % 2, 0);
PopCPURegList(list); PopCPURegList(list);
bytes += list.Count() * kXRegSizeInBits / 8; bytes += list.Count() * kXRegSizeInBits / 8;

View File

@ -48,7 +48,14 @@ constexpr Register kReturnRegister2 = x2;
constexpr Register kJSFunctionRegister = x1; constexpr Register kJSFunctionRegister = x1;
constexpr Register kContextRegister = cp; constexpr Register kContextRegister = cp;
constexpr Register kAllocateSizeRegister = x1; constexpr Register kAllocateSizeRegister = x1;
#if defined(V8_OS_WIN)
// x18 is reserved as platform register on Windows ARM64.
constexpr Register kSpeculationPoisonRegister = x23;
#else
constexpr Register kSpeculationPoisonRegister = x18; constexpr Register kSpeculationPoisonRegister = x18;
#endif
constexpr Register kInterpreterAccumulatorRegister = x0; constexpr Register kInterpreterAccumulatorRegister = x0;
constexpr Register kInterpreterBytecodeOffsetRegister = x19; constexpr Register kInterpreterBytecodeOffsetRegister = x19;
constexpr Register kInterpreterBytecodeArrayRegister = x20; constexpr Register kInterpreterBytecodeArrayRegister = x20;

View File

@ -277,7 +277,7 @@ uintptr_t Simulator::StackLimit(uintptr_t c_limit) const {
// The simulator uses a separate JS stack. If we have exhausted the C stack, // The simulator uses a separate JS stack. If we have exhausted the C stack,
// we also drop down the JS limit to reflect the exhaustion on the JS stack. // we also drop down the JS limit to reflect the exhaustion on the JS stack.
if (GetCurrentStackPosition() < c_limit) { if (GetCurrentStackPosition() < c_limit) {
return reinterpret_cast<uintptr_t>(get_sp()); return get_sp();
} }
// Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes // Otherwise the limit is the JS stack. Leave a safety margin of 1024 bytes
@ -332,7 +332,7 @@ void Simulator::Init(FILE* stream) {
stack_limit_ = stack_ + stack_protection_size_; stack_limit_ = stack_ + stack_protection_size_;
uintptr_t tos = stack_ + stack_size_ - stack_protection_size_; uintptr_t tos = stack_ + stack_size_ - stack_protection_size_;
// The stack pointer must be 16-byte aligned. // The stack pointer must be 16-byte aligned.
set_sp(tos & ~0xFUL); set_sp(tos & ~0xFULL);
stream_ = stream; stream_ = stream;
print_disasm_ = new PrintDisassembler(stream_); print_disasm_ = new PrintDisassembler(stream_);
@ -403,6 +403,14 @@ void Simulator::RunFrom(Instruction* start) {
// uses the ObjectPair structure. // uses the ObjectPair structure.
// The simulator assumes all runtime calls return two 64-bits values. If they // The simulator assumes all runtime calls return two 64-bits values. If they
// don't, register x1 is clobbered. This is fine because x1 is caller-saved. // don't, register x1 is clobbered. This is fine because x1 is caller-saved.
#if defined(V8_OS_WIN)
typedef int64_t (*SimulatorRuntimeCall_ReturnPtr)(int64_t arg0, int64_t arg1,
int64_t arg2, int64_t arg3,
int64_t arg4, int64_t arg5,
int64_t arg6, int64_t arg7,
int64_t arg8);
#endif
typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, int64_t arg1, typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, int64_t arg1,
int64_t arg2, int64_t arg3, int64_t arg2, int64_t arg3,
int64_t arg4, int64_t arg5, int64_t arg4, int64_t arg5,
@ -464,12 +472,16 @@ void Simulator::DoRuntimeCall(Instruction* instr) {
break; break;
case ExternalReference::BUILTIN_CALL: case ExternalReference::BUILTIN_CALL:
case ExternalReference::BUILTIN_CALL_PAIR: { #if defined(V8_OS_WIN)
// Object* f(v8::internal::Arguments) or {
// ObjectPair f(v8::internal::Arguments). // Object* f(v8::internal::Arguments).
TraceSim("Type: BUILTIN_CALL\n"); TraceSim("Type: BUILTIN_CALL\n");
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external); // When this simulator runs on Windows x64 host, function with ObjectPair
// return type accepts an implicit pointer to caller allocated memory for
// ObjectPair as return value. This diverges the calling convention from
// function which returns primitive type, so function returns ObjectPair
// and primitive type cannot share implementation.
// We don't know how many arguments are being passed, but we can // We don't know how many arguments are being passed, but we can
// pass 8 without touching the stack. They will be ignored by the // pass 8 without touching the stack. They will be ignored by the
@ -486,6 +498,43 @@ void Simulator::DoRuntimeCall(Instruction* instr) {
", " ", "
"0x%016" PRIx64, "0x%016" PRIx64,
arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
SimulatorRuntimeCall_ReturnPtr target =
reinterpret_cast<SimulatorRuntimeCall_ReturnPtr>(external);
int64_t result =
target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
TraceSim("Returned: 0x%16\n", result);
#ifdef DEBUG
CorruptAllCallerSavedCPURegisters();
#endif
set_xreg(0, result);
break;
}
#endif
case ExternalReference::BUILTIN_CALL_PAIR: {
// Object* f(v8::internal::Arguments) or
// ObjectPair f(v8::internal::Arguments).
TraceSim("Type: BUILTIN_CALL\n");
// We don't know how many arguments are being passed, but we can
// pass 8 without touching the stack. They will be ignored by the
// host function if they aren't used.
TraceSim(
"Arguments: "
"0x%016" PRIx64 ", 0x%016" PRIx64
", "
"0x%016" PRIx64 ", 0x%016" PRIx64
", "
"0x%016" PRIx64 ", 0x%016" PRIx64
", "
"0x%016" PRIx64 ", 0x%016" PRIx64
", "
"0x%016" PRIx64,
arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
ObjectPair result = ObjectPair result =
target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); target(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
TraceSim("Returned: {%p, %p}\n", static_cast<void*>(result.x), TraceSim("Returned: {%p, %p}\n", static_cast<void*>(result.x),
@ -1489,7 +1538,7 @@ void Simulator::VisitUnconditionalBranchToRegister(Instruction* instr) {
void Simulator::VisitTestBranch(Instruction* instr) { void Simulator::VisitTestBranch(Instruction* instr) {
unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) | unsigned bit_pos = (instr->ImmTestBranchBit5() << 5) |
instr->ImmTestBranchBit40(); instr->ImmTestBranchBit40();
bool take_branch = ((xreg(instr->Rt()) & (1UL << bit_pos)) == 0); bool take_branch = ((xreg(instr->Rt()) & (1ULL << bit_pos)) == 0);
switch (instr->Mask(TestBranchMask)) { switch (instr->Mask(TestBranchMask)) {
case TBZ: break; case TBZ: break;
case TBNZ: take_branch = !take_branch; break; case TBNZ: take_branch = !take_branch; break;
@ -1858,7 +1907,7 @@ void Simulator::LoadStorePairHelper(Instruction* instr,
unsigned rt = instr->Rt(); unsigned rt = instr->Rt();
unsigned rt2 = instr->Rt2(); unsigned rt2 = instr->Rt2();
unsigned addr_reg = instr->Rn(); unsigned addr_reg = instr->Rn();
size_t access_size = 1 << instr->SizeLSPair(); size_t access_size = 1ULL << instr->SizeLSPair();
int64_t offset = instr->ImmLSPair() * access_size; int64_t offset = instr->ImmLSPair() * access_size;
uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode); uintptr_t address = LoadStoreAddress(addr_reg, offset, addrmode);
uintptr_t address2 = address + access_size; uintptr_t address2 = address + access_size;
@ -2266,7 +2315,7 @@ void Simulator::VisitConditionalSelect(Instruction* instr) {
break; break;
case CSNEG_w: case CSNEG_w:
case CSNEG_x: case CSNEG_x:
new_val = -new_val; new_val = (uint64_t)(-(int64_t)new_val);
break; break;
default: UNIMPLEMENTED(); default: UNIMPLEMENTED();
} }
@ -2396,14 +2445,14 @@ static int64_t MultiplyHighSigned(int64_t u, int64_t v) {
uint64_t u0, v0, w0; uint64_t u0, v0, w0;
int64_t u1, v1, w1, w2, t; int64_t u1, v1, w1, w2, t;
u0 = u & 0xFFFFFFFFL; u0 = u & 0xFFFFFFFFLL;
u1 = u >> 32; u1 = u >> 32;
v0 = v & 0xFFFFFFFFL; v0 = v & 0xFFFFFFFFLL;
v1 = v >> 32; v1 = v >> 32;
w0 = u0 * v0; w0 = u0 * v0;
t = u1 * v0 + (w0 >> 32); t = u1 * v0 + (w0 >> 32);
w1 = t & 0xFFFFFFFFL; w1 = t & 0xFFFFFFFFLL;
w2 = t >> 32; w2 = t >> 32;
w1 = u0 * v1 + w1; w1 = u0 * v1 + w1;
@ -2458,7 +2507,7 @@ void Simulator::BitfieldHelper(Instruction* instr) {
mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1 mask = diff < reg_size - 1 ? (static_cast<T>(1) << (diff + 1)) - 1
: static_cast<T>(-1); : static_cast<T>(-1);
} else { } else {
uint64_t umask = ((1L << (S + 1)) - 1); uint64_t umask = ((1LL << (S + 1)) - 1);
umask = (umask >> R) | (umask << (reg_size - R)); umask = (umask >> R) | (umask << (reg_size - R));
mask = static_cast<T>(umask); mask = static_cast<T>(umask);
diff += reg_size; diff += reg_size;
@ -2973,7 +3022,11 @@ void Simulator::VisitSystem(Instruction* instr) {
default: UNIMPLEMENTED(); default: UNIMPLEMENTED();
} }
} else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
#if defined(V8_OS_WIN)
MemoryBarrier();
#else
__sync_synchronize(); __sync_synchronize();
#endif
} else { } else {
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
@ -4797,7 +4850,7 @@ void Simulator::VisitNEONModifiedImmediate(Instruction* instr) {
vform = q ? kFormat2D : kFormat1D; vform = q ? kFormat2D : kFormat1D;
imm = 0; imm = 0;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
if (imm8 & (1 << i)) { if (imm8 & (1ULL << i)) {
imm |= (UINT64_C(0xFF) << (8 * i)); imm |= (UINT64_C(0xFF) << (8 * i));
} }
} }

View File

@ -123,7 +123,7 @@ int HighestSetBitPosition(uint64_t value) {
uint64_t LargestPowerOf2Divisor(uint64_t value) { uint64_t LargestPowerOf2Divisor(uint64_t value) {
return value & -value; return value & (-(int64_t)value);
} }

View File

@ -44,7 +44,7 @@ int MaskToBit(uint64_t mask);
template <typename T> template <typename T>
T ReverseBytes(T value, int block_bytes_log2) { T ReverseBytes(T value, int block_bytes_log2) {
DCHECK((sizeof(value) == 4) || (sizeof(value) == 8)); DCHECK((sizeof(value) == 4) || (sizeof(value) == 8));
DCHECK((1U << block_bytes_log2) <= sizeof(value)); DCHECK((1ULL << block_bytes_log2) <= sizeof(value));
// Split the 64-bit value into an 8-bit array, where b[0] is the least // Split the 64-bit value into an 8-bit array, where b[0] is the least
// significant byte, and b[7] is the most significant. // significant byte, and b[7] is the most significant.
uint8_t bytes[8]; uint8_t bytes[8];

View File

@ -21,7 +21,7 @@
#elif defined(_M_IX86) || defined(__i386__) #elif defined(_M_IX86) || defined(__i386__)
#define V8_HOST_ARCH_IA32 1 #define V8_HOST_ARCH_IA32 1
#define V8_HOST_ARCH_32_BIT 1 #define V8_HOST_ARCH_32_BIT 1
#elif defined(__AARCH64EL__) #elif defined(__AARCH64EL__) || defined(_M_ARM64)
#define V8_HOST_ARCH_ARM64 1 #define V8_HOST_ARCH_ARM64 1
#define V8_HOST_ARCH_64_BIT 1 #define V8_HOST_ARCH_64_BIT 1
#elif defined(__ARMEL__) #elif defined(__ARMEL__)
@ -83,7 +83,7 @@
#define V8_TARGET_ARCH_X64 1 #define V8_TARGET_ARCH_X64 1
#elif defined(_M_IX86) || defined(__i386__) #elif defined(_M_IX86) || defined(__i386__)
#define V8_TARGET_ARCH_IA32 1 #define V8_TARGET_ARCH_IA32 1
#elif defined(__AARCH64EL__) #elif defined(__AARCH64EL__) || defined(_M_ARM64)
#define V8_TARGET_ARCH_ARM64 1 #define V8_TARGET_ARCH_ARM64 1
#elif defined(__ARMEL__) #elif defined(__ARMEL__)
#define V8_TARGET_ARCH_ARM 1 #define V8_TARGET_ARCH_ARM 1

View File

@ -189,10 +189,19 @@ void StackTrace::InitTrace(const CONTEXT* context_record) {
STACKFRAME64 stack_frame; STACKFRAME64 stack_frame;
memset(&stack_frame, 0, sizeof(stack_frame)); memset(&stack_frame, 0, sizeof(stack_frame));
#if defined(_WIN64) #if defined(_WIN64)
#if defined(_M_X64)
int machine_type = IMAGE_FILE_MACHINE_AMD64; int machine_type = IMAGE_FILE_MACHINE_AMD64;
stack_frame.AddrPC.Offset = context_record->Rip; stack_frame.AddrPC.Offset = context_record->Rip;
stack_frame.AddrFrame.Offset = context_record->Rbp; stack_frame.AddrFrame.Offset = context_record->Rbp;
stack_frame.AddrStack.Offset = context_record->Rsp; stack_frame.AddrStack.Offset = context_record->Rsp;
#elif defined(_M_ARM64)
int machine_type = IMAGE_FILE_MACHINE_ARM64;
stack_frame.AddrPC.Offset = context_record->Pc;
stack_frame.AddrFrame.Offset = context_record->Fp;
stack_frame.AddrStack.Offset = context_record->Sp;
#else
#error Unsupported Arch
#endif
#else #else
int machine_type = IMAGE_FILE_MACHINE_I386; int machine_type = IMAGE_FILE_MACHINE_I386;
stack_frame.AddrPC.Offset = context_record->Eip; stack_frame.AddrPC.Offset = context_record->Eip;

View File

@ -829,6 +829,12 @@ void ThreadTicks::WaitUntilInitializedWin() {
::Sleep(10); ::Sleep(10);
} }
#ifdef V8_HOST_ARCH_ARM64
#define ReadCycleCounter() _ReadStatusReg(ARM64_PMCCNTR_EL0)
#else
#define ReadCycleCounter() __rdtsc()
#endif
double ThreadTicks::TSCTicksPerSecond() { double ThreadTicks::TSCTicksPerSecond() {
DCHECK(IsSupported()); DCHECK(IsSupported());
@ -849,12 +855,12 @@ double ThreadTicks::TSCTicksPerSecond() {
// The first time that this function is called, make an initial reading of the // The first time that this function is called, make an initial reading of the
// TSC and the performance counter. // TSC and the performance counter.
static const uint64_t tsc_initial = __rdtsc(); static const uint64_t tsc_initial = ReadCycleCounter();
static const uint64_t perf_counter_initial = QPCNowRaw(); static const uint64_t perf_counter_initial = QPCNowRaw();
// Make a another reading of the TSC and the performance counter every time // Make a another reading of the TSC and the performance counter every time
// that this function is called. // that this function is called.
uint64_t tsc_now = __rdtsc(); uint64_t tsc_now = ReadCycleCounter();
uint64_t perf_counter_now = QPCNowRaw(); uint64_t perf_counter_now = QPCNowRaw();
// Reset the thread priority. // Reset the thread priority.
@ -887,6 +893,7 @@ double ThreadTicks::TSCTicksPerSecond() {
return tsc_ticks_per_second; return tsc_ticks_per_second;
} }
#undef ReadCycleCounter
#endif // V8_OS_WIN #endif // V8_OS_WIN
} // namespace base } // namespace base

View File

@ -549,6 +549,26 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
// Check if the arguments will overflow the stack. // Check if the arguments will overflow the stack.
__ Cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2)); __ Cmp(scratch, Operand(num_args, LSL, kPointerSizeLog2));
__ B(le, stack_overflow); __ B(le, stack_overflow);
#if defined(V8_OS_WIN)
// Simulate _chkstk to extend stack guard page on Windows ARM64.
const int kPageSize = 4096;
Label chkstk, chkstk_done;
Register probe = temps.AcquireX();
__ Sub(scratch, sp, Operand(num_args, LSL, kPointerSizeLog2));
__ Mov(probe, sp);
// Loop start of stack probe.
__ Bind(&chkstk);
__ Sub(probe, probe, kPageSize);
__ Cmp(probe, scratch);
__ B(lo, &chkstk_done);
__ Ldrb(xzr, MemOperand(probe));
__ B(&chkstk);
__ Bind(&chkstk_done);
#endif
} }
// Input: // Input:
@ -996,9 +1016,15 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Mov( __ Mov(
kInterpreterDispatchTableRegister, kInterpreterDispatchTableRegister,
ExternalReference::interpreter_dispatch_table_address(masm->isolate())); ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
#if defined(V8_OS_WIN)
__ Ldrb(x23, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ Mov(x1, Operand(x23, LSL, kPointerSizeLog2));
#else
__ Ldrb(x18, MemOperand(kInterpreterBytecodeArrayRegister, __ Ldrb(x18, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister)); kInterpreterBytecodeOffsetRegister));
__ Mov(x1, Operand(x18, LSL, kPointerSizeLog2)); __ Mov(x1, Operand(x18, LSL, kPointerSizeLog2));
#endif
__ Ldr(kJavaScriptCallCodeStartRegister, __ Ldr(kJavaScriptCallCodeStartRegister,
MemOperand(kInterpreterDispatchTableRegister, x1)); MemOperand(kInterpreterDispatchTableRegister, x1));
__ Call(kJavaScriptCallCodeStartRegister); __ Call(kJavaScriptCallCodeStartRegister);
@ -1232,9 +1258,15 @@ static void Generate_InterpreterEnterBytecode(MacroAssembler* masm) {
__ SmiUntag(kInterpreterBytecodeOffsetRegister); __ SmiUntag(kInterpreterBytecodeOffsetRegister);
// Dispatch to the target bytecode. // Dispatch to the target bytecode.
#if defined(V8_OS_WIN)
__ Ldrb(x23, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister));
__ Mov(x1, Operand(x23, LSL, kPointerSizeLog2));
#else
__ Ldrb(x18, MemOperand(kInterpreterBytecodeArrayRegister, __ Ldrb(x18, MemOperand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister)); kInterpreterBytecodeOffsetRegister));
__ Mov(x1, Operand(x18, LSL, kPointerSizeLog2)); __ Mov(x1, Operand(x18, LSL, kPointerSizeLog2));
#endif
__ Ldr(kJavaScriptCallCodeStartRegister, __ Ldr(kJavaScriptCallCodeStartRegister,
MemOperand(kInterpreterDispatchTableRegister, x1)); MemOperand(kInterpreterDispatchTableRegister, x1));
__ Jump(kJavaScriptCallCodeStartRegister); __ Jump(kJavaScriptCallCodeStartRegister);
@ -2957,7 +2989,7 @@ void Builtins::Generate_DoubleToI(MacroAssembler* masm) {
// Isolate the mantissa bits, and set the implicit '1'. // Isolate the mantissa bits, and set the implicit '1'.
Register mantissa = scratch2; Register mantissa = scratch2;
__ Ubfx(mantissa, result, 0, HeapNumber::kMantissaBits); __ Ubfx(mantissa, result, 0, HeapNumber::kMantissaBits);
__ Orr(mantissa, mantissa, 1UL << HeapNumber::kMantissaBits); __ Orr(mantissa, mantissa, 1ULL << HeapNumber::kMantissaBits);
// Negate the mantissa if necessary. // Negate the mantissa if necessary.
__ Tst(result, kXSignMask); __ Tst(result, kXSignMask);

View File

@ -1879,7 +1879,15 @@ FrameDescription::FrameDescription(uint32_t frame_size, int parameter_count)
// TODO(jbramley): It isn't safe to use kZapUint32 here. If the register // TODO(jbramley): It isn't safe to use kZapUint32 here. If the register
// isn't used before the next safepoint, the GC will try to scan it as a // isn't used before the next safepoint, the GC will try to scan it as a
// tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't. // tagged value. kZapUint32 looks like a valid tagged pointer, but it isn't.
#if defined(V8_OS_WIN) && defined(V8_TARGET_ARCH_ARM64)
// x18 is reserved as platform register on Windows arm64 platform
const int kPlatformRegister = 18;
if (r != kPlatformRegister) {
SetRegister(r, kZapUint32);
}
#else
SetRegister(r, kZapUint32); SetRegister(r, kZapUint32);
#endif
} }
// Zap all the slots. // Zap all the slots.

View File

@ -690,6 +690,10 @@ void Sampler::DoSample() {
state.pc = reinterpret_cast<void*>(context.Rip); state.pc = reinterpret_cast<void*>(context.Rip);
state.sp = reinterpret_cast<void*>(context.Rsp); state.sp = reinterpret_cast<void*>(context.Rsp);
state.fp = reinterpret_cast<void*>(context.Rbp); state.fp = reinterpret_cast<void*>(context.Rbp);
#elif V8_HOST_ARCH_ARM64
state.pc = reinterpret_cast<void*>(context.Pc);
state.sp = reinterpret_cast<void*>(context.Sp);
state.fp = reinterpret_cast<void*>(context.Fp);
#else #else
state.pc = reinterpret_cast<void*>(context.Eip); state.pc = reinterpret_cast<void*>(context.Eip);
state.sp = reinterpret_cast<void*>(context.Esp); state.sp = reinterpret_cast<void*>(context.Esp);

View File

@ -97,6 +97,10 @@ inline T XorSeqCst(T* p, T value) {
#define InterlockedOr32 _InterlockedOr #define InterlockedOr32 _InterlockedOr
#define InterlockedXor32 _InterlockedXor #define InterlockedXor32 _InterlockedXor
#if defined(V8_HOST_ARCH_ARM64)
#define InterlockedExchange8 _InterlockedExchange8
#endif
#define ATOMIC_OPS(type, suffix, vctype) \ #define ATOMIC_OPS(type, suffix, vctype) \
inline type ExchangeSeqCst(type* p, type value) { \ inline type ExchangeSeqCst(type* p, type value) { \
return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \ return InterlockedExchange##suffix(reinterpret_cast<vctype*>(p), \
@ -160,6 +164,10 @@ inline void StoreSeqCst(T* p, T value) {
#undef InterlockedOr32 #undef InterlockedOr32
#undef InterlockedXor32 #undef InterlockedXor32
#if defined(V8_HOST_ARCH_ARM64)
#undef InterlockedExchange8
#endif
#else #else
#error Unsupported platform! #error Unsupported platform!

View File

@ -250,7 +250,7 @@ class LiftoffCompiler {
int reg_code = param_loc.AsRegister(); int reg_code = param_loc.AsRegister();
RegList cache_regs = rc == kGpReg ? kLiftoffAssemblerGpCacheRegs RegList cache_regs = rc == kGpReg ? kLiftoffAssemblerGpCacheRegs
: kLiftoffAssemblerFpCacheRegs; : kLiftoffAssemblerFpCacheRegs;
if (cache_regs & (1 << reg_code)) { if (cache_regs & (1ULL << reg_code)) {
LiftoffRegister in_reg = LiftoffRegister::from_code(rc, reg_code); LiftoffRegister in_reg = LiftoffRegister::from_code(rc, reg_code);
param_regs.set(in_reg); param_regs.set(in_reg);
} }
@ -278,7 +278,7 @@ class LiftoffCompiler {
int reg_code = param_loc.AsRegister(); int reg_code = param_loc.AsRegister();
RegList cache_regs = rc == kGpReg ? kLiftoffAssemblerGpCacheRegs RegList cache_regs = rc == kGpReg ? kLiftoffAssemblerGpCacheRegs
: kLiftoffAssemblerFpCacheRegs; : kLiftoffAssemblerFpCacheRegs;
if (cache_regs & (1 << reg_code)) { if (cache_regs & (1ULL << reg_code)) {
// This is a cache register, just use it. // This is a cache register, just use it.
in_reg = LiftoffRegister::from_code(rc, reg_code); in_reg = LiftoffRegister::from_code(rc, reg_code);
} else { } else {

View File

@ -418,7 +418,9 @@ v8_source_set("cctest_sources") {
v8_current_cpu == "mipsel" || v8_current_cpu == "mipsel64") { v8_current_cpu == "mipsel" || v8_current_cpu == "mipsel64") {
# Disable fmadd/fmsub so that expected results match generated code in # Disable fmadd/fmsub so that expected results match generated code in
# RunFloat64MulAndFloat64Add1 and friends. # RunFloat64MulAndFloat64Add1 and friends.
cflags += [ "-ffp-contract=off" ] if (!is_win) {
cflags += [ "-ffp-contract=off" ]
}
} }
if (is_win) { if (is_win) {

View File

@ -354,9 +354,9 @@ TEST(mov) {
__ Mov(x0, 0x0123456789ABCDEFL); __ Mov(x0, 0x0123456789ABCDEFL);
__ movz(x1, 0xABCDL << 16); __ movz(x1, 0xABCDLL << 16);
__ movk(x2, 0xABCDL << 32); __ movk(x2, 0xABCDLL << 32);
__ movn(x3, 0xABCDL << 48); __ movn(x3, 0xABCDLL << 48);
__ Mov(x4, 0x0123456789ABCDEFL); __ Mov(x4, 0x0123456789ABCDEFL);
__ Mov(x5, x4); __ Mov(x5, x4);
@ -6769,7 +6769,11 @@ static void LdrLiteralRangeHelper(size_t range, LiteralPoolEmitOutcome outcome,
// can be handled by this test. // can be handled by this test.
CHECK_LE(code_size, range); CHECK_LE(code_size, range);
#if defined(_M_ARM64) && !defined(__clang__)
auto PoolSizeAt = [pool_entries, kEntrySize](int pc_offset) {
#else
auto PoolSizeAt = [](int pc_offset) { auto PoolSizeAt = [](int pc_offset) {
#endif
// To determine padding, consider the size of the prologue of the pool, // To determine padding, consider the size of the prologue of the pool,
// and the jump around the pool, which we always need. // and the jump around the pool, which we always need.
size_t prologue_size = 2 * kInstrSize + kInstrSize; size_t prologue_size = 2 * kInstrSize + kInstrSize;
@ -6947,7 +6951,7 @@ TEST(add_sub_wide_imm) {
CHECK_EQUAL_32(kWMinInt, w18); CHECK_EQUAL_32(kWMinInt, w18);
CHECK_EQUAL_32(kWMinInt, w19); CHECK_EQUAL_32(kWMinInt, w19);
CHECK_EQUAL_64(-0x1234567890ABCDEFUL, x20); CHECK_EQUAL_64(-0x1234567890ABCDEFLL, x20);
CHECK_EQUAL_32(-0x12345678, w21); CHECK_EQUAL_32(-0x12345678, w21);
TEARDOWN(); TEARDOWN();
@ -7724,7 +7728,7 @@ TEST(adc_sbc_shift) {
RUN(); RUN();
CHECK_EQUAL_64(0xFFFFFFFFFFFFFFFFL, x5); CHECK_EQUAL_64(0xFFFFFFFFFFFFFFFFL, x5);
CHECK_EQUAL_64(1L << 60, x6); CHECK_EQUAL_64(1LL << 60, x6);
CHECK_EQUAL_64(0xF0123456789ABCDDL, x7); CHECK_EQUAL_64(0xF0123456789ABCDDL, x7);
CHECK_EQUAL_64(0x0111111111111110L, x8); CHECK_EQUAL_64(0x0111111111111110L, x8);
CHECK_EQUAL_64(0x1222222222222221L, x9); CHECK_EQUAL_64(0x1222222222222221L, x9);
@ -7735,13 +7739,13 @@ TEST(adc_sbc_shift) {
CHECK_EQUAL_32(0x91111110, w13); CHECK_EQUAL_32(0x91111110, w13);
CHECK_EQUAL_32(0x9A222221, w14); CHECK_EQUAL_32(0x9A222221, w14);
CHECK_EQUAL_64(0xFFFFFFFFFFFFFFFFL + 1, x18); CHECK_EQUAL_64(0xFFFFFFFFFFFFFFFFLL + 1, x18);
CHECK_EQUAL_64((1L << 60) + 1, x19); CHECK_EQUAL_64((1LL << 60) + 1, x19);
CHECK_EQUAL_64(0xF0123456789ABCDDL + 1, x20); CHECK_EQUAL_64(0xF0123456789ABCDDL + 1, x20);
CHECK_EQUAL_64(0x0111111111111110L + 1, x21); CHECK_EQUAL_64(0x0111111111111110L + 1, x21);
CHECK_EQUAL_64(0x1222222222222221L + 1, x22); CHECK_EQUAL_64(0x1222222222222221L + 1, x22);
CHECK_EQUAL_32(0xFFFFFFFF + 1, w23); CHECK_EQUAL_32(0xFFFFFFFFULL + 1, w23);
CHECK_EQUAL_32((1 << 30) + 1, w24); CHECK_EQUAL_32((1 << 30) + 1, w24);
CHECK_EQUAL_32(0xF89ABCDD + 1, w25); CHECK_EQUAL_32(0xF89ABCDD + 1, w25);
CHECK_EQUAL_32(0x91111110 + 1, w26); CHECK_EQUAL_32(0x91111110 + 1, w26);
@ -12008,19 +12012,19 @@ TEST(register_bit) {
// teardown. // teardown.
// Simple tests. // Simple tests.
CHECK(x0.bit() == (1UL << 0)); CHECK(x0.bit() == (1ULL << 0));
CHECK(x1.bit() == (1UL << 1)); CHECK(x1.bit() == (1ULL << 1));
CHECK(x10.bit() == (1UL << 10)); CHECK(x10.bit() == (1ULL << 10));
// AAPCS64 definitions. // AAPCS64 definitions.
CHECK(fp.bit() == (1UL << kFramePointerRegCode)); CHECK(fp.bit() == (1ULL << kFramePointerRegCode));
CHECK(lr.bit() == (1UL << kLinkRegCode)); CHECK(lr.bit() == (1ULL << kLinkRegCode));
// Fixed (hardware) definitions. // Fixed (hardware) definitions.
CHECK(xzr.bit() == (1UL << kZeroRegCode)); CHECK(xzr.bit() == (1ULL << kZeroRegCode));
// Internal ABI definitions. // Internal ABI definitions.
CHECK(sp.bit() == (1UL << kSPRegInternalCode)); CHECK(sp.bit() == (1ULL << kSPRegInternalCode));
CHECK(sp.bit() != xzr.bit()); CHECK(sp.bit() != xzr.bit());
// xn.bit() == wn.bit() at all times, for the same n. // xn.bit() == wn.bit() at all times, for the same n.

View File

@ -29,6 +29,12 @@
#include "src/arm64/decoder-arm64-inl.h" #include "src/arm64/decoder-arm64-inl.h"
#include "src/arm64/disasm-arm64.h" #include "src/arm64/disasm-arm64.h"
#if defined(V8_OS_WIN)
#define RANDGEN() rand()
#else
#define RANDGEN() mrand48()
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
@ -37,14 +43,18 @@ TEST(FUZZ_decoder) {
// 43 million = ~1% of the instruction space. // 43 million = ~1% of the instruction space.
static const int instruction_count = 43 * 1024 * 1024; static const int instruction_count = 43 * 1024 * 1024;
#if defined(V8_OS_WIN)
srand(1);
#else
uint16_t seed[3] = {1, 2, 3}; uint16_t seed[3] = {1, 2, 3};
seed48(seed); seed48(seed);
#endif
Decoder<DispatchingDecoderVisitor> decoder; Decoder<DispatchingDecoderVisitor> decoder;
Instruction buffer[kInstrSize]; Instruction buffer[kInstrSize];
for (int i = 0; i < instruction_count; i++) { for (int i = 0; i < instruction_count; i++) {
uint32_t instr = static_cast<uint32_t>(mrand48()); uint32_t instr = static_cast<uint32_t>(RANDGEN());
buffer->SetInstructionBits(instr); buffer->SetInstructionBits(instr);
decoder.Decode(buffer); decoder.Decode(buffer);
} }
@ -56,8 +66,12 @@ TEST(FUZZ_disasm) {
// 9 million = ~0.2% of the instruction space. // 9 million = ~0.2% of the instruction space.
static const int instruction_count = 9 * 1024 * 1024; static const int instruction_count = 9 * 1024 * 1024;
#if defined(V8_OS_WIN)
srand(42);
#else
uint16_t seed[3] = {42, 43, 44}; uint16_t seed[3] = {42, 43, 44};
seed48(seed); seed48(seed);
#endif
Decoder<DispatchingDecoderVisitor> decoder; Decoder<DispatchingDecoderVisitor> decoder;
DisassemblingDecoder disasm; DisassemblingDecoder disasm;
@ -65,7 +79,7 @@ TEST(FUZZ_disasm) {
decoder.AppendVisitor(&disasm); decoder.AppendVisitor(&disasm);
for (int i = 0; i < instruction_count; i++) { for (int i = 0; i < instruction_count; i++) {
uint32_t instr = static_cast<uint32_t>(mrand48()); uint32_t instr = static_cast<uint32_t>(RANDGEN());
buffer->SetInstructionBits(instr); buffer->SetInstructionBits(instr);
decoder.Decode(buffer); decoder.Decode(buffer);
} }
@ -73,3 +87,5 @@ TEST(FUZZ_disasm) {
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
#undef RANDGEN

View File

@ -233,7 +233,7 @@ RegList PopulateRegisterArray(Register* w, Register* x, Register* r,
RegList list = 0; RegList list = 0;
int i = 0; int i = 0;
for (unsigned n = 0; (n < kNumberOfRegisters) && (i < reg_count); n++) { for (unsigned n = 0; (n < kNumberOfRegisters) && (i < reg_count); n++) {
if (((1UL << n) & allowed) != 0) { if (((1ULL << n) & allowed) != 0) {
// Only assign allowed registers. // Only assign allowed registers.
if (r) { if (r) {
r[i] = Register::Create(n, reg_size); r[i] = Register::Create(n, reg_size);
@ -244,7 +244,7 @@ RegList PopulateRegisterArray(Register* w, Register* x, Register* r,
if (w) { if (w) {
w[i] = Register::Create(n, kWRegSizeInBits); w[i] = Register::Create(n, kWRegSizeInBits);
} }
list |= (1UL << n); list |= (1ULL << n);
i++; i++;
} }
} }
@ -259,7 +259,7 @@ RegList PopulateVRegisterArray(VRegister* s, VRegister* d, VRegister* v,
RegList list = 0; RegList list = 0;
int i = 0; int i = 0;
for (unsigned n = 0; (n < kNumberOfVRegisters) && (i < reg_count); n++) { for (unsigned n = 0; (n < kNumberOfVRegisters) && (i < reg_count); n++) {
if (((1UL << n) & allowed) != 0) { if (((1ULL << n) & allowed) != 0) {
// Only assigned allowed registers. // Only assigned allowed registers.
if (v) { if (v) {
v[i] = VRegister::Create(n, reg_size); v[i] = VRegister::Create(n, reg_size);
@ -270,7 +270,7 @@ RegList PopulateVRegisterArray(VRegister* s, VRegister* d, VRegister* v,
if (s) { if (s) {
s[i] = VRegister::Create(n, kSRegSizeInBits); s[i] = VRegister::Create(n, kSRegSizeInBits);
} }
list |= (1UL << n); list |= (1ULL << n);
i++; i++;
} }
} }
@ -284,7 +284,7 @@ RegList PopulateVRegisterArray(VRegister* s, VRegister* d, VRegister* v,
void Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) { void Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) {
Register first = NoReg; Register first = NoReg;
for (unsigned i = 0; i < kNumberOfRegisters; i++) { for (unsigned i = 0; i < kNumberOfRegisters; i++) {
if (reg_list & (1UL << i)) { if (reg_list & (1ULL << i)) {
Register xn = Register::Create(i, kXRegSizeInBits); Register xn = Register::Create(i, kXRegSizeInBits);
// We should never write into sp here. // We should never write into sp here.
CHECK(!xn.Is(sp)); CHECK(!xn.Is(sp));
@ -307,7 +307,7 @@ void Clobber(MacroAssembler* masm, RegList reg_list, uint64_t const value) {
void ClobberFP(MacroAssembler* masm, RegList reg_list, double const value) { void ClobberFP(MacroAssembler* masm, RegList reg_list, double const value) {
VRegister first = NoVReg; VRegister first = NoVReg;
for (unsigned i = 0; i < kNumberOfVRegisters; i++) { for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
if (reg_list & (1UL << i)) { if (reg_list & (1ULL << i)) {
VRegister dn = VRegister::Create(i, kDRegSizeInBits); VRegister dn = VRegister::Create(i, kDRegSizeInBits);
if (!first.IsValid()) { if (!first.IsValid()) {
// This is the first register we've hit, so construct the literal. // This is the first register we've hit, so construct the literal.

View File

@ -1288,7 +1288,7 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) { TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
TRACED_FORRANGE(int, bit, 0, 63) { TRACED_FORRANGE(int, bit, 0, 63) {
uint64_t mask = 1L << bit; uint64_t mask = 1LL << bit;
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64()); StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
RawMachineLabel a, b; RawMachineLabel a, b;
m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b); m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
@ -1309,7 +1309,7 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) { TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
TRACED_FORRANGE(int, bit, 0, 63) { TRACED_FORRANGE(int, bit, 0, 63) {
uint64_t mask = 1L << bit; uint64_t mask = 1LL << bit;
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64()); StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
RawMachineLabel a, b; RawMachineLabel a, b;
m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b); m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);