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:
parent
76968a2ff3
commit
a6423cca4a
1
AUTHORS
1
AUTHORS
@ -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>
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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];
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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!
|
||||||
|
@ -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 {
|
||||||
|
@ -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) {
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user