| Index: src/arm64/simulator-arm64.h
|
| diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h
|
| index 29a6583ffd7ede78bb4b1c65bb9bc6c0e11ed569..0dc534c5f98b7b022500b973ff96eacbf256f51b 100644
|
| --- a/src/arm64/simulator-arm64.h
|
| +++ b/src/arm64/simulator-arm64.h
|
| @@ -133,35 +133,28 @@ class SimSystemRegister {
|
|
|
|
|
| // Represent a register (r0-r31, v0-v31).
|
| -template<int kSizeInBytes>
|
| class SimRegisterBase {
|
| public:
|
| template<typename T>
|
| - void Set(T new_value, unsigned size = sizeof(T)) {
|
| - ASSERT(size <= kSizeInBytes);
|
| - ASSERT(size <= sizeof(new_value));
|
| - // All AArch64 registers are zero-extending; Writing a W register clears the
|
| - // top bits of the corresponding X register.
|
| - memset(value_, 0, kSizeInBytes);
|
| - memcpy(value_, &new_value, size);
|
| + void Set(T new_value) {
|
| + value_ = 0;
|
| + memcpy(&value_, &new_value, sizeof(T));
|
| }
|
|
|
| - // Copy 'size' bytes of the register to the result, and zero-extend to fill
|
| - // the result.
|
| template<typename T>
|
| - T Get(unsigned size = sizeof(T)) const {
|
| - ASSERT(size <= kSizeInBytes);
|
| + T Get() const {
|
| T result;
|
| - memset(&result, 0, sizeof(result));
|
| - memcpy(&result, value_, size);
|
| + memcpy(&result, &value_, sizeof(T));
|
| return result;
|
| }
|
|
|
| protected:
|
| - uint8_t value_[kSizeInBytes];
|
| + int64_t value_;
|
| };
|
| -typedef SimRegisterBase<kXRegSize> SimRegister; // r0-r31
|
| -typedef SimRegisterBase<kDRegSize> SimFPRegister; // v0-v31
|
| +
|
| +
|
| +typedef SimRegisterBase SimRegister; // r0-r31
|
| +typedef SimRegisterBase SimFPRegister; // v0-v31
|
|
|
|
|
| class Simulator : public DecoderVisitor {
|
| @@ -328,86 +321,53 @@ class Simulator : public DecoderVisitor {
|
| VISITOR_LIST(DECLARE)
|
| #undef DECLARE
|
|
|
| - // Register accessors.
|
| + bool IsZeroRegister(unsigned code, Reg31Mode r31mode) const {
|
| + return ((code == 31) && (r31mode == Reg31IsZeroRegister));
|
| + }
|
|
|
| + // Register accessors.
|
| // Return 'size' bits of the value of an integer register, as the specified
|
| // type. The value is zero-extended to fill the result.
|
| //
|
| - // The only supported values of 'size' are kXRegSizeInBits and
|
| - // kWRegSizeInBits.
|
| template<typename T>
|
| - T reg(unsigned size, unsigned code,
|
| - Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| - unsigned size_in_bytes = size / 8;
|
| - ASSERT(size_in_bytes <= sizeof(T));
|
| - ASSERT((size == kXRegSizeInBits) || (size == kWRegSizeInBits));
|
| + T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| ASSERT(code < kNumberOfRegisters);
|
| -
|
| - if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
|
| - T result;
|
| - memset(&result, 0, sizeof(result));
|
| - return result;
|
| + if (IsZeroRegister(code, r31mode)) {
|
| + return 0;
|
| }
|
| - return registers_[code].Get<T>(size_in_bytes);
|
| - }
|
| -
|
| - // Like reg(), but infer the access size from the template type.
|
| - template<typename T>
|
| - T reg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| - return reg<T>(sizeof(T) * 8, code, r31mode);
|
| + return registers_[code].Get<T>();
|
| }
|
|
|
| // Common specialized accessors for the reg() template.
|
| - int32_t wreg(unsigned code,
|
| - Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| + int32_t wreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| return reg<int32_t>(code, r31mode);
|
| }
|
|
|
| - int64_t xreg(unsigned code,
|
| - Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| + int64_t xreg(unsigned code, Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| return reg<int64_t>(code, r31mode);
|
| }
|
|
|
| - int64_t reg(unsigned size, unsigned code,
|
| - Reg31Mode r31mode = Reg31IsZeroRegister) const {
|
| - return reg<int64_t>(size, code, r31mode);
|
| - }
|
| -
|
| // Write 'size' bits of 'value' into an integer register. The value is
|
| // zero-extended. This behaviour matches AArch64 register writes.
|
| - //
|
| - // The only supported values of 'size' are kXRegSizeInBits and
|
| - // kWRegSizeInBits.
|
| - template<typename T>
|
| - void set_reg(unsigned size, unsigned code, T value,
|
| - Reg31Mode r31mode = Reg31IsZeroRegister) {
|
| - unsigned size_in_bytes = size / 8;
|
| - ASSERT(size_in_bytes <= sizeof(T));
|
| - ASSERT((size == kXRegSizeInBits) || (size == kWRegSizeInBits));
|
| - ASSERT(code < kNumberOfRegisters);
|
| -
|
| - if ((code == 31) && (r31mode == Reg31IsZeroRegister)) {
|
| - return;
|
| - }
|
| - return registers_[code].Set(value, size_in_bytes);
|
| - }
|
|
|
| // Like set_reg(), but infer the access size from the template type.
|
| template<typename T>
|
| void set_reg(unsigned code, T value,
|
| Reg31Mode r31mode = Reg31IsZeroRegister) {
|
| - set_reg(sizeof(value) * 8, code, value, r31mode);
|
| + ASSERT(code < kNumberOfRegisters);
|
| + if (!IsZeroRegister(code, r31mode))
|
| + registers_[code].Set(value);
|
| }
|
|
|
| // Common specialized accessors for the set_reg() template.
|
| void set_wreg(unsigned code, int32_t value,
|
| Reg31Mode r31mode = Reg31IsZeroRegister) {
|
| - set_reg(kWRegSizeInBits, code, value, r31mode);
|
| + set_reg(code, value, r31mode);
|
| }
|
|
|
| void set_xreg(unsigned code, int64_t value,
|
| Reg31Mode r31mode = Reg31IsZeroRegister) {
|
| - set_reg(kXRegSizeInBits, code, value, r31mode);
|
| + set_reg(code, value, r31mode);
|
| }
|
|
|
| // Commonly-used special cases.
|
| @@ -432,24 +392,10 @@ class Simulator : public DecoderVisitor {
|
|
|
| Address get_sp() { return reg<Address>(31, Reg31IsStackPointer); }
|
|
|
| - // Return 'size' bits of the value of a floating-point register, as the
|
| - // specified type. The value is zero-extended to fill the result.
|
| - //
|
| - // The only supported values of 'size' are kDRegSizeInBits and
|
| - // kSRegSizeInBits.
|
| - template<typename T>
|
| - T fpreg(unsigned size, unsigned code) const {
|
| - unsigned size_in_bytes = size / 8;
|
| - ASSERT(size_in_bytes <= sizeof(T));
|
| - ASSERT((size == kDRegSizeInBits) || (size == kSRegSizeInBits));
|
| - ASSERT(code < kNumberOfFPRegisters);
|
| - return fpregisters_[code].Get<T>(size_in_bytes);
|
| - }
|
| -
|
| - // Like fpreg(), but infer the access size from the template type.
|
| template<typename T>
|
| T fpreg(unsigned code) const {
|
| - return fpreg<T>(sizeof(T) * 8, code);
|
| + ASSERT(code < kNumberOfRegisters);
|
| + return fpregisters_[code].Get<T>();
|
| }
|
|
|
| // Common specialized accessors for the fpreg() template.
|
| @@ -485,7 +431,7 @@ class Simulator : public DecoderVisitor {
|
| void set_fpreg(unsigned code, T value) {
|
| ASSERT((sizeof(value) == kDRegSize) || (sizeof(value) == kSRegSize));
|
| ASSERT(code < kNumberOfFPRegisters);
|
| - fpregisters_[code].Set(value, sizeof(value));
|
| + fpregisters_[code].Set(value);
|
| }
|
|
|
| // Common specialized accessors for the set_fpreg() template.
|
| @@ -625,14 +571,19 @@ class Simulator : public DecoderVisitor {
|
| return !ConditionPassed(cond);
|
| }
|
|
|
| - void AddSubHelper(Instruction* instr, int64_t op2);
|
| - int64_t AddWithCarry(unsigned reg_size,
|
| - bool set_flags,
|
| - int64_t src1,
|
| - int64_t src2,
|
| - int64_t carry_in = 0);
|
| - void LogicalHelper(Instruction* instr, int64_t op2);
|
| - void ConditionalCompareHelper(Instruction* instr, int64_t op2);
|
| + template<typename T>
|
| + void AddSubHelper(Instruction* instr, T op2);
|
| + template<typename T>
|
| + T AddWithCarry(bool set_flags,
|
| + T src1,
|
| + T src2,
|
| + T carry_in = 0);
|
| + template<typename T>
|
| + void AddSubWithCarry(Instruction* instr);
|
| + template<typename T>
|
| + void LogicalHelper(Instruction* instr, T op2);
|
| + template<typename T>
|
| + void ConditionalCompareHelper(Instruction* instr, T op2);
|
| void LoadStoreHelper(Instruction* instr,
|
| int64_t offset,
|
| AddrMode addrmode);
|
| @@ -659,18 +610,21 @@ class Simulator : public DecoderVisitor {
|
| void MemoryWrite64(uint8_t* address, uint64_t value);
|
| void MemoryWriteFP64(uint8_t* address, double value);
|
|
|
| - int64_t ShiftOperand(unsigned reg_size,
|
| - int64_t value,
|
| - Shift shift_type,
|
| - unsigned amount);
|
| - int64_t Rotate(unsigned reg_width,
|
| - int64_t value,
|
| +
|
| + template <typename T>
|
| + T ShiftOperand(T value,
|
| Shift shift_type,
|
| unsigned amount);
|
| - int64_t ExtendValue(unsigned reg_width,
|
| - int64_t value,
|
| - Extend extend_type,
|
| - unsigned left_shift = 0);
|
| + template <typename T>
|
| + T ExtendValue(T value,
|
| + Extend extend_type,
|
| + unsigned left_shift = 0);
|
| + template <typename T>
|
| + void Extract(Instruction* instr);
|
| + template <typename T>
|
| + void DataProcessing2Source(Instruction* instr);
|
| + template <typename T>
|
| + void BitfieldHelper(Instruction* instr);
|
|
|
| uint64_t ReverseBits(uint64_t value, unsigned num_bits);
|
| uint64_t ReverseBytes(uint64_t value, ReverseByteMode mode);
|
| @@ -796,8 +750,9 @@ class Simulator : public DecoderVisitor {
|
| // is irrelevant, and is not checked here.
|
| }
|
|
|
| - static int CalcNFlag(uint64_t result, unsigned reg_size) {
|
| - return (result >> (reg_size - 1)) & 1;
|
| + template <typename T>
|
| + static int CalcNFlag(T result) {
|
| + return (result >> (sizeof(T) * 8 - 1)) & 1;
|
| }
|
|
|
| static int CalcZFlag(uint64_t result) {
|
|
|