Chromium Code Reviews| Index: src/arm64/simulator-arm64.h |
| diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h |
| index 29a6583ffd7ede78bb4b1c65bb9bc6c0e11ed569..d0d093761e32436be77f2a5ed0c63b2b5fa6c125 100644 |
| --- a/src/arm64/simulator-arm64.h |
| +++ b/src/arm64/simulator-arm64.h |
| @@ -72,6 +72,13 @@ class SimulatorStack : public v8::internal::AllStatic { |
| #else // !defined(USE_SIMULATOR) |
| + |
| +template<typename T> |
|
Fritz
2014/05/20 19:44:24
utils-arm64.h or utils.h?
jbramley
2014/05/21 08:02:30
It's not ARM64-specific, so I'd say utils.h, but t
Fritz
2014/05/21 16:38:56
Done.
|
| +struct make_unsigned { |
| + typedef T type; |
| +}; |
| + |
| + |
| enum ReverseByteMode { |
| Reverse16 = 0, |
| Reverse32 = 1, |
| @@ -133,35 +140,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_; |
|
Fritz
2014/05/20 19:44:24
for the SIMD registers I considered templating thi
jbramley
2014/05/21 08:02:30
I don't think we can assume that uint128_t is avai
|
| }; |
| -typedef SimRegisterBase<kXRegSize> SimRegister; // r0-r31 |
| -typedef SimRegisterBase<kDRegSize> SimFPRegister; // v0-v31 |
| + |
| +STATIC_ASSERT(kXRegSize == kDRegSize); |
| +typedef SimRegisterBase SimRegister; // r0-r31 |
| +typedef SimRegisterBase SimFPRegister; // v0-v31 |
| class Simulator : public DecoderVisitor { |
| @@ -328,86 +328,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 +399,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 +438,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 +578,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 +617,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 +757,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) { |