diff --git a/disas/libvixl/a64/assembler-a64.h b/disas/libvixl/a64/assembler-a64.h index 93b3011868..1e2947b283 100644 --- a/disas/libvixl/a64/assembler-a64.h +++ b/disas/libvixl/a64/assembler-a64.h @@ -38,6 +38,7 @@ namespace vixl { typedef uint64_t RegList; static const int kRegListSizeInBits = sizeof(RegList) * 8; + // Registers. // Some CPURegister methods can return Register and FPRegister types, so we @@ -58,62 +59,62 @@ class CPURegister { }; CPURegister() : code_(0), size_(0), type_(kNoRegister) { - ASSERT(!IsValid()); - ASSERT(IsNone()); + VIXL_ASSERT(!IsValid()); + VIXL_ASSERT(IsNone()); } CPURegister(unsigned code, unsigned size, RegisterType type) : code_(code), size_(size), type_(type) { - ASSERT(IsValidOrNone()); + VIXL_ASSERT(IsValidOrNone()); } unsigned code() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return code_; } RegisterType type() const { - ASSERT(IsValidOrNone()); + VIXL_ASSERT(IsValidOrNone()); return type_; } RegList Bit() const { - ASSERT(code_ < (sizeof(RegList) * 8)); + VIXL_ASSERT(code_ < (sizeof(RegList) * 8)); return IsValid() ? (static_cast(1) << code_) : 0; } unsigned size() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return size_; } int SizeInBytes() const { - ASSERT(IsValid()); - ASSERT(size() % 8 == 0); + VIXL_ASSERT(IsValid()); + VIXL_ASSERT(size() % 8 == 0); return size_ / 8; } int SizeInBits() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return size_; } bool Is32Bits() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return size_ == 32; } bool Is64Bits() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return size_ == 64; } bool IsValid() const { if (IsValidRegister() || IsValidFPRegister()) { - ASSERT(!IsNone()); + VIXL_ASSERT(!IsNone()); return true; } else { - ASSERT(IsNone()); + VIXL_ASSERT(IsNone()); return false; } } @@ -132,25 +133,29 @@ class CPURegister { bool IsNone() const { // kNoRegister types should always have size 0 and code 0. - ASSERT((type_ != kNoRegister) || (code_ == 0)); - ASSERT((type_ != kNoRegister) || (size_ == 0)); + VIXL_ASSERT((type_ != kNoRegister) || (code_ == 0)); + VIXL_ASSERT((type_ != kNoRegister) || (size_ == 0)); return type_ == kNoRegister; } + bool Aliases(const CPURegister& other) const { + VIXL_ASSERT(IsValidOrNone() && other.IsValidOrNone()); + return (code_ == other.code_) && (type_ == other.type_); + } + bool Is(const CPURegister& other) const { - ASSERT(IsValidOrNone() && other.IsValidOrNone()); - return (code_ == other.code_) && (size_ == other.size_) && - (type_ == other.type_); + VIXL_ASSERT(IsValidOrNone() && other.IsValidOrNone()); + return Aliases(other) && (size_ == other.size_); } inline bool IsZero() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return IsRegister() && (code_ == kZeroRegCode); } inline bool IsSP() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return IsRegister() && (code_ == kSPRegInternalCode); } @@ -188,13 +193,13 @@ class Register : public CPURegister { explicit Register() : CPURegister() {} inline explicit Register(const CPURegister& other) : CPURegister(other.code(), other.size(), other.type()) { - ASSERT(IsValidRegister()); + VIXL_ASSERT(IsValidRegister()); } explicit Register(unsigned code, unsigned size) : CPURegister(code, size, kRegister) {} bool IsValid() const { - ASSERT(IsRegister() || IsNone()); + VIXL_ASSERT(IsRegister() || IsNone()); return IsValidRegister(); } @@ -216,13 +221,13 @@ class FPRegister : public CPURegister { inline FPRegister() : CPURegister() {} inline explicit FPRegister(const CPURegister& other) : CPURegister(other.code(), other.size(), other.type()) { - ASSERT(IsValidFPRegister()); + VIXL_ASSERT(IsValidFPRegister()); } inline FPRegister(unsigned code, unsigned size) : CPURegister(code, size, kFPRegister) {} bool IsValid() const { - ASSERT(IsFPRegister() || IsNone()); + VIXL_ASSERT(IsFPRegister() || IsNone()); return IsValidFPRegister(); } @@ -306,30 +311,30 @@ class CPURegList { CPURegister reg4 = NoCPUReg) : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()), size_(reg1.size()), type_(reg1.type()) { - ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4)); - ASSERT(IsValid()); + VIXL_ASSERT(AreSameSizeAndType(reg1, reg2, reg3, reg4)); + VIXL_ASSERT(IsValid()); } inline CPURegList(CPURegister::RegisterType type, unsigned size, RegList list) : list_(list), size_(size), type_(type) { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); } inline CPURegList(CPURegister::RegisterType type, unsigned size, unsigned first_reg, unsigned last_reg) : size_(size), type_(type) { - ASSERT(((type == CPURegister::kRegister) && - (last_reg < kNumberOfRegisters)) || - ((type == CPURegister::kFPRegister) && - (last_reg < kNumberOfFPRegisters))); - ASSERT(last_reg >= first_reg); - list_ = (1UL << (last_reg + 1)) - 1; - list_ &= ~((1UL << first_reg) - 1); - ASSERT(IsValid()); + VIXL_ASSERT(((type == CPURegister::kRegister) && + (last_reg < kNumberOfRegisters)) || + ((type == CPURegister::kFPRegister) && + (last_reg < kNumberOfFPRegisters))); + VIXL_ASSERT(last_reg >= first_reg); + list_ = (UINT64_C(1) << (last_reg + 1)) - 1; + list_ &= ~((UINT64_C(1) << first_reg) - 1); + VIXL_ASSERT(IsValid()); } inline CPURegister::RegisterType type() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return type_; } @@ -337,9 +342,9 @@ class CPURegList { // this list are left unchanged. The type and size of the registers in the // 'other' list must match those in this list. void Combine(const CPURegList& other) { - ASSERT(IsValid()); - ASSERT(other.type() == type_); - ASSERT(other.RegisterSizeInBits() == size_); + VIXL_ASSERT(IsValid()); + VIXL_ASSERT(other.type() == type_); + VIXL_ASSERT(other.RegisterSizeInBits() == size_); list_ |= other.list(); } @@ -347,44 +352,49 @@ class CPURegList { // do not exist in this list are ignored. The type and size of the registers // in the 'other' list must match those in this list. void Remove(const CPURegList& other) { - ASSERT(IsValid()); - ASSERT(other.type() == type_); - ASSERT(other.RegisterSizeInBits() == size_); + VIXL_ASSERT(IsValid()); + VIXL_ASSERT(other.type() == type_); + VIXL_ASSERT(other.RegisterSizeInBits() == size_); list_ &= ~other.list(); } // Variants of Combine and Remove which take a single register. inline void Combine(const CPURegister& other) { - ASSERT(other.type() == type_); - ASSERT(other.size() == size_); + VIXL_ASSERT(other.type() == type_); + VIXL_ASSERT(other.size() == size_); Combine(other.code()); } inline void Remove(const CPURegister& other) { - ASSERT(other.type() == type_); - ASSERT(other.size() == size_); + VIXL_ASSERT(other.type() == type_); + VIXL_ASSERT(other.size() == size_); Remove(other.code()); } // Variants of Combine and Remove which take a single register by its code; // the type and size of the register is inferred from this list. inline void Combine(int code) { - ASSERT(IsValid()); - ASSERT(CPURegister(code, size_, type_).IsValid()); - list_ |= (1UL << code); + VIXL_ASSERT(IsValid()); + VIXL_ASSERT(CPURegister(code, size_, type_).IsValid()); + list_ |= (UINT64_C(1) << code); } inline void Remove(int code) { - ASSERT(IsValid()); - ASSERT(CPURegister(code, size_, type_).IsValid()); - list_ &= ~(1UL << code); + VIXL_ASSERT(IsValid()); + VIXL_ASSERT(CPURegister(code, size_, type_).IsValid()); + list_ &= ~(UINT64_C(1) << code); } inline RegList list() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return list_; } + inline void set_list(RegList new_list) { + VIXL_ASSERT(IsValid()); + list_ = new_list; + } + // Remove all callee-saved registers from the list. This can be useful when // preparing registers for an AAPCS64 function call, for example. void RemoveCalleeSaved(); @@ -401,31 +411,41 @@ class CPURegList { static CPURegList GetCallerSavedFP(unsigned size = kDRegSize); inline bool IsEmpty() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return list_ == 0; } inline bool IncludesAliasOf(const CPURegister& other) const { - ASSERT(IsValid()); - return (type_ == other.type()) && (other.Bit() & list_); + VIXL_ASSERT(IsValid()); + return (type_ == other.type()) && ((other.Bit() & list_) != 0); + } + + inline bool IncludesAliasOf(int code) const { + VIXL_ASSERT(IsValid()); + return ((code & list_) != 0); } inline int Count() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return CountSetBits(list_, kRegListSizeInBits); } inline unsigned RegisterSizeInBits() const { - ASSERT(IsValid()); + VIXL_ASSERT(IsValid()); return size_; } inline unsigned RegisterSizeInBytes() const { int size_in_bits = RegisterSizeInBits(); - ASSERT((size_in_bits % 8) == 0); + VIXL_ASSERT((size_in_bits % 8) == 0); return size_in_bits / 8; } + inline unsigned TotalSizeInBytes() const { + VIXL_ASSERT(IsValid()); + return RegisterSizeInBytes() * Count(); + } + private: RegList list_; unsigned size_; @@ -471,33 +491,34 @@ class Operand { bool IsImmediate() const; bool IsShiftedRegister() const; bool IsExtendedRegister() const; + bool IsZero() const; // This returns an LSL shift (<= 4) operand as an equivalent extend operand, // which helps in the encoding of instructions that use the stack pointer. Operand ToExtendedRegister() const; int64_t immediate() const { - ASSERT(IsImmediate()); + VIXL_ASSERT(IsImmediate()); return immediate_; } Register reg() const { - ASSERT(IsShiftedRegister() || IsExtendedRegister()); + VIXL_ASSERT(IsShiftedRegister() || IsExtendedRegister()); return reg_; } Shift shift() const { - ASSERT(IsShiftedRegister()); + VIXL_ASSERT(IsShiftedRegister()); return shift_; } Extend extend() const { - ASSERT(IsExtendedRegister()); + VIXL_ASSERT(IsExtendedRegister()); return extend_; } unsigned shift_amount() const { - ASSERT(IsShiftedRegister() || IsExtendedRegister()); + VIXL_ASSERT(IsShiftedRegister() || IsExtendedRegister()); return shift_amount_; } @@ -556,7 +577,7 @@ class Label { Label() : is_bound_(false), link_(NULL), target_(NULL) {} ~Label() { // If the label has been linked to, it needs to be bound to a target. - ASSERT(!IsLinked() || IsBound()); + VIXL_ASSERT(!IsLinked() || IsBound()); } inline Instruction* link() const { return link_; } @@ -643,7 +664,7 @@ class Assembler { void bind(Label* label); int UpdateAndGetByteOffsetTo(Label* label); inline int UpdateAndGetInstructionOffsetTo(Label* label) { - ASSERT(Label::kEndOfChain == 0); + VIXL_ASSERT(Label::kEndOfChain == 0); return UpdateAndGetByteOffsetTo(label) >> kInstructionSizeLog2; } @@ -716,8 +737,12 @@ class Assembler { // Add. void add(const Register& rd, const Register& rn, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Add and update status flags. + void adds(const Register& rd, + const Register& rn, + const Operand& operand); // Compare negative. void cmn(const Register& rn, const Operand& operand); @@ -725,40 +750,62 @@ class Assembler { // Subtract. void sub(const Register& rd, const Register& rn, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Subtract and update status flags. + void subs(const Register& rd, + const Register& rn, + const Operand& operand); // Compare. void cmp(const Register& rn, const Operand& operand); // Negate. void neg(const Register& rd, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Negate and update status flags. + void negs(const Register& rd, + const Operand& operand); // Add with carry bit. void adc(const Register& rd, const Register& rn, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Add with carry bit and update status flags. + void adcs(const Register& rd, + const Register& rn, + const Operand& operand); // Subtract with carry bit. void sbc(const Register& rd, const Register& rn, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Subtract with carry bit and update status flags. + void sbcs(const Register& rd, + const Register& rn, + const Operand& operand); // Negate with carry bit. void ngc(const Register& rd, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Negate with carry bit and update status flags. + void ngcs(const Register& rd, + const Operand& operand); // Logical instructions. // Bitwise and (A & B). void and_(const Register& rd, const Register& rn, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Bitwise and (A & B) and update status flags. + void ands(const Register& rd, + const Register& rn, + const Operand& operand); // Bit test and set flags. void tst(const Register& rn, const Operand& operand); @@ -766,8 +813,12 @@ class Assembler { // Bit clear (A & ~B). void bic(const Register& rd, const Register& rn, - const Operand& operand, - FlagsUpdate S = LeaveFlags); + const Operand& operand); + + // Bit clear (A & ~B) and update status flags. + void bics(const Register& rd, + const Register& rn, + const Operand& operand); // Bitwise or (A | B). void orr(const Register& rd, const Register& rn, const Operand& operand); @@ -818,8 +869,8 @@ class Assembler { const Register& rn, unsigned lsb, unsigned width) { - ASSERT(width >= 1); - ASSERT(lsb + width <= rn.size()); + VIXL_ASSERT(width >= 1); + VIXL_ASSERT(lsb + width <= rn.size()); bfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); } @@ -828,15 +879,15 @@ class Assembler { const Register& rn, unsigned lsb, unsigned width) { - ASSERT(width >= 1); - ASSERT(lsb + width <= rn.size()); + VIXL_ASSERT(width >= 1); + VIXL_ASSERT(lsb + width <= rn.size()); bfm(rd, rn, lsb, lsb + width - 1); } // Sbfm aliases. // Arithmetic shift right. inline void asr(const Register& rd, const Register& rn, unsigned shift) { - ASSERT(shift < rd.size()); + VIXL_ASSERT(shift < rd.size()); sbfm(rd, rn, shift, rd.size() - 1); } @@ -845,8 +896,8 @@ class Assembler { const Register& rn, unsigned lsb, unsigned width) { - ASSERT(width >= 1); - ASSERT(lsb + width <= rn.size()); + VIXL_ASSERT(width >= 1); + VIXL_ASSERT(lsb + width <= rn.size()); sbfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); } @@ -855,8 +906,8 @@ class Assembler { const Register& rn, unsigned lsb, unsigned width) { - ASSERT(width >= 1); - ASSERT(lsb + width <= rn.size()); + VIXL_ASSERT(width >= 1); + VIXL_ASSERT(lsb + width <= rn.size()); sbfm(rd, rn, lsb, lsb + width - 1); } @@ -879,13 +930,13 @@ class Assembler { // Logical shift left. inline void lsl(const Register& rd, const Register& rn, unsigned shift) { unsigned reg_size = rd.size(); - ASSERT(shift < reg_size); + VIXL_ASSERT(shift < reg_size); ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1); } // Logical shift right. inline void lsr(const Register& rd, const Register& rn, unsigned shift) { - ASSERT(shift < rd.size()); + VIXL_ASSERT(shift < rd.size()); ubfm(rd, rn, shift, rd.size() - 1); } @@ -894,8 +945,8 @@ class Assembler { const Register& rn, unsigned lsb, unsigned width) { - ASSERT(width >= 1); - ASSERT(lsb + width <= rn.size()); + VIXL_ASSERT(width >= 1); + VIXL_ASSERT(lsb + width <= rn.size()); ubfm(rd, rn, (rd.size() - lsb) & (rd.size() - 1), width - 1); } @@ -904,8 +955,8 @@ class Assembler { const Register& rn, unsigned lsb, unsigned width) { - ASSERT(width >= 1); - ASSERT(lsb + width <= rn.size()); + VIXL_ASSERT(width >= 1); + VIXL_ASSERT(lsb + width <= rn.size()); ubfm(rd, rn, lsb, lsb + width - 1); } @@ -1109,9 +1160,12 @@ class Assembler { // Load literal to register. void ldr(const Register& rt, uint64_t imm); - // Load literal to FP register. + // Load double precision floating point literal to FP register. void ldr(const FPRegister& ft, double imm); + // Load single precision floating point literal to FP register. + void ldr(const FPRegister& ft, float imm); + // Move instructions. The default shift of -1 indicates that the move // instruction will calculate an appropriate 16-bit immediate and left shift // that is equal to the 64-bit immediate argument. If an explicit left shift @@ -1160,6 +1214,15 @@ class Assembler { // System hint. void hint(SystemHint code); + // Data memory barrier. + void dmb(BarrierDomain domain, BarrierType type); + + // Data synchronization barrier. + void dsb(BarrierDomain domain, BarrierType type); + + // Instruction synchronization barrier. + void isb(); + // Alias for system instructions. // No-op. void nop() { @@ -1167,17 +1230,20 @@ class Assembler { } // FP instructions. - // Move immediate to FP register. - void fmov(FPRegister fd, double imm); + // Move double precision immediate to FP register. + void fmov(const FPRegister& fd, double imm); + + // Move single precision immediate to FP register. + void fmov(const FPRegister& fd, float imm); // Move FP register to register. - void fmov(Register rd, FPRegister fn); + void fmov(const Register& rd, const FPRegister& fn); // Move register to FP register. - void fmov(FPRegister fd, Register rn); + void fmov(const FPRegister& fd, const Register& rn); // Move FP register to FP register. - void fmov(FPRegister fd, FPRegister fn); + void fmov(const FPRegister& fd, const FPRegister& fn); // FP add. void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); @@ -1188,12 +1254,30 @@ class Assembler { // FP multiply. void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); - // FP multiply and subtract. + // FP fused multiply and add. + void fmadd(const FPRegister& fd, + const FPRegister& fn, + const FPRegister& fm, + const FPRegister& fa); + + // FP fused multiply and subtract. void fmsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm, const FPRegister& fa); + // FP fused multiply, add and negate. + void fnmadd(const FPRegister& fd, + const FPRegister& fn, + const FPRegister& fm, + const FPRegister& fa); + + // FP fused multiply, subtract and negate. + void fnmsub(const FPRegister& fd, + const FPRegister& fn, + const FPRegister& fm, + const FPRegister& fa); + // FP divide. void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); @@ -1203,6 +1287,12 @@ class Assembler { // FP minimum. void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); + // FP maximum number. + void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); + + // FP minimum number. + void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm); + // FP absolute. void fabs(const FPRegister& fd, const FPRegister& fn); @@ -1212,6 +1302,12 @@ class Assembler { // FP square root. void fsqrt(const FPRegister& fd, const FPRegister& fn); + // FP round to integer (nearest with ties to away). + void frinta(const FPRegister& fd, const FPRegister& fn); + + // FP round to integer (toward minus infinity). + void frintm(const FPRegister& fd, const FPRegister& fn); + // FP round to integer (nearest with ties to even). void frintn(const FPRegister& fd, const FPRegister& fn); @@ -1244,24 +1340,30 @@ class Assembler { // FP convert between single and double precision. void fcvt(const FPRegister& fd, const FPRegister& fn); - // Convert FP to unsigned integer (round towards -infinity). - void fcvtmu(const Register& rd, const FPRegister& fn); + // Convert FP to signed integer (nearest with ties to away). + void fcvtas(const Register& rd, const FPRegister& fn); + + // Convert FP to unsigned integer (nearest with ties to away). + void fcvtau(const Register& rd, const FPRegister& fn); // Convert FP to signed integer (round towards -infinity). void fcvtms(const Register& rd, const FPRegister& fn); - // Convert FP to unsigned integer (nearest with ties to even). - void fcvtnu(const Register& rd, const FPRegister& fn); + // Convert FP to unsigned integer (round towards -infinity). + void fcvtmu(const Register& rd, const FPRegister& fn); // Convert FP to signed integer (nearest with ties to even). void fcvtns(const Register& rd, const FPRegister& fn); - // Convert FP to unsigned integer (round towards zero). - void fcvtzu(const Register& rd, const FPRegister& fn); + // Convert FP to unsigned integer (nearest with ties to even). + void fcvtnu(const Register& rd, const FPRegister& fn); // Convert FP to signed integer (round towards zero). void fcvtzs(const Register& rd, const FPRegister& fn); + // Convert FP to unsigned integer (round towards zero). + void fcvtzu(const Register& rd, const FPRegister& fn); + // Convert signed integer or fixed point to FP. void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0); @@ -1282,14 +1384,14 @@ class Assembler { // character. The instruction pointer (pc_) is then aligned correctly for // subsequent instructions. void EmitStringData(const char * string) { - ASSERT(string != NULL); + VIXL_ASSERT(string != NULL); size_t len = strlen(string) + 1; EmitData(string, len); // Pad with NULL characters until pc_ is aligned. const char pad[] = {'\0', '\0', '\0', '\0'}; - ASSERT(sizeof(pad) == kInstructionSize); + VIXL_STATIC_ASSERT(sizeof(pad) == kInstructionSize); Instruction* next_pc = AlignUp(pc_, kInstructionSize); EmitData(&pad, next_pc - pc_); } @@ -1298,44 +1400,44 @@ class Assembler { // Register encoding. static Instr Rd(CPURegister rd) { - ASSERT(rd.code() != kSPRegInternalCode); + VIXL_ASSERT(rd.code() != kSPRegInternalCode); return rd.code() << Rd_offset; } static Instr Rn(CPURegister rn) { - ASSERT(rn.code() != kSPRegInternalCode); + VIXL_ASSERT(rn.code() != kSPRegInternalCode); return rn.code() << Rn_offset; } static Instr Rm(CPURegister rm) { - ASSERT(rm.code() != kSPRegInternalCode); + VIXL_ASSERT(rm.code() != kSPRegInternalCode); return rm.code() << Rm_offset; } static Instr Ra(CPURegister ra) { - ASSERT(ra.code() != kSPRegInternalCode); + VIXL_ASSERT(ra.code() != kSPRegInternalCode); return ra.code() << Ra_offset; } static Instr Rt(CPURegister rt) { - ASSERT(rt.code() != kSPRegInternalCode); + VIXL_ASSERT(rt.code() != kSPRegInternalCode); return rt.code() << Rt_offset; } static Instr Rt2(CPURegister rt2) { - ASSERT(rt2.code() != kSPRegInternalCode); + VIXL_ASSERT(rt2.code() != kSPRegInternalCode); return rt2.code() << Rt2_offset; } // These encoding functions allow the stack pointer to be encoded, and // disallow the zero register. static Instr RdSP(Register rd) { - ASSERT(!rd.IsZero()); + VIXL_ASSERT(!rd.IsZero()); return (rd.code() & kRegCodeMask) << Rd_offset; } static Instr RnSP(Register rn) { - ASSERT(!rn.IsZero()); + VIXL_ASSERT(!rn.IsZero()); return (rn.code() & kRegCodeMask) << Rn_offset; } @@ -1346,7 +1448,7 @@ class Assembler { } else if (S == LeaveFlags) { return 0 << FlagsUpdate_offset; } - UNREACHABLE(); + VIXL_UNREACHABLE(); return 0; } @@ -1356,7 +1458,7 @@ class Assembler { // PC-relative address encoding. static Instr ImmPCRelAddress(int imm21) { - ASSERT(is_int21(imm21)); + VIXL_ASSERT(is_int21(imm21)); Instr imm = static_cast(truncate_to_int21(imm21)); Instr immhi = (imm >> ImmPCRelLo_width) << ImmPCRelHi_offset; Instr immlo = imm << ImmPCRelLo_offset; @@ -1365,27 +1467,27 @@ class Assembler { // Branch encoding. static Instr ImmUncondBranch(int imm26) { - ASSERT(is_int26(imm26)); + VIXL_ASSERT(is_int26(imm26)); return truncate_to_int26(imm26) << ImmUncondBranch_offset; } static Instr ImmCondBranch(int imm19) { - ASSERT(is_int19(imm19)); + VIXL_ASSERT(is_int19(imm19)); return truncate_to_int19(imm19) << ImmCondBranch_offset; } static Instr ImmCmpBranch(int imm19) { - ASSERT(is_int19(imm19)); + VIXL_ASSERT(is_int19(imm19)); return truncate_to_int19(imm19) << ImmCmpBranch_offset; } static Instr ImmTestBranch(int imm14) { - ASSERT(is_int14(imm14)); + VIXL_ASSERT(is_int14(imm14)); return truncate_to_int14(imm14) << ImmTestBranch_offset; } static Instr ImmTestBranchBit(unsigned bit_pos) { - ASSERT(is_uint6(bit_pos)); + VIXL_ASSERT(is_uint6(bit_pos)); // Subtract five from the shift offset, as we need bit 5 from bit_pos. unsigned b5 = bit_pos << (ImmTestBranchBit5_offset - 5); unsigned b40 = bit_pos << ImmTestBranchBit40_offset; @@ -1400,7 +1502,7 @@ class Assembler { } static Instr ImmAddSub(int64_t imm) { - ASSERT(IsImmAddSub(imm)); + VIXL_ASSERT(IsImmAddSub(imm)); if (is_uint12(imm)) { // No shift required. return imm << ImmAddSub_offset; } else { @@ -1409,55 +1511,55 @@ class Assembler { } static inline Instr ImmS(unsigned imms, unsigned reg_size) { - ASSERT(((reg_size == kXRegSize) && is_uint6(imms)) || + VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(imms)) || ((reg_size == kWRegSize) && is_uint5(imms))); USE(reg_size); return imms << ImmS_offset; } static inline Instr ImmR(unsigned immr, unsigned reg_size) { - ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || + VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || ((reg_size == kWRegSize) && is_uint5(immr))); USE(reg_size); - ASSERT(is_uint6(immr)); + VIXL_ASSERT(is_uint6(immr)); return immr << ImmR_offset; } static inline Instr ImmSetBits(unsigned imms, unsigned reg_size) { - ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); - ASSERT(is_uint6(imms)); - ASSERT((reg_size == kXRegSize) || is_uint6(imms + 3)); + VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); + VIXL_ASSERT(is_uint6(imms)); + VIXL_ASSERT((reg_size == kXRegSize) || is_uint6(imms + 3)); USE(reg_size); return imms << ImmSetBits_offset; } static inline Instr ImmRotate(unsigned immr, unsigned reg_size) { - ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); - ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || + VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); + VIXL_ASSERT(((reg_size == kXRegSize) && is_uint6(immr)) || ((reg_size == kWRegSize) && is_uint5(immr))); USE(reg_size); return immr << ImmRotate_offset; } static inline Instr ImmLLiteral(int imm19) { - ASSERT(is_int19(imm19)); + VIXL_ASSERT(is_int19(imm19)); return truncate_to_int19(imm19) << ImmLLiteral_offset; } static inline Instr BitN(unsigned bitn, unsigned reg_size) { - ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); - ASSERT((reg_size == kXRegSize) || (bitn == 0)); + VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); + VIXL_ASSERT((reg_size == kXRegSize) || (bitn == 0)); USE(reg_size); return bitn << BitN_offset; } static Instr ShiftDP(Shift shift) { - ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR); + VIXL_ASSERT(shift == LSL || shift == LSR || shift == ASR || shift == ROR); return shift << ShiftDP_offset; } static Instr ImmDPShift(unsigned amount) { - ASSERT(is_uint6(amount)); + VIXL_ASSERT(is_uint6(amount)); return amount << ImmDPShift_offset; } @@ -1466,12 +1568,12 @@ class Assembler { } static Instr ImmExtendShift(unsigned left_shift) { - ASSERT(left_shift <= 4); + VIXL_ASSERT(left_shift <= 4); return left_shift << ImmExtendShift_offset; } static Instr ImmCondCmp(unsigned imm) { - ASSERT(is_uint5(imm)); + VIXL_ASSERT(is_uint5(imm)); return imm << ImmCondCmp_offset; } @@ -1481,55 +1583,65 @@ class Assembler { // MemOperand offset encoding. static Instr ImmLSUnsigned(int imm12) { - ASSERT(is_uint12(imm12)); + VIXL_ASSERT(is_uint12(imm12)); return imm12 << ImmLSUnsigned_offset; } static Instr ImmLS(int imm9) { - ASSERT(is_int9(imm9)); + VIXL_ASSERT(is_int9(imm9)); return truncate_to_int9(imm9) << ImmLS_offset; } static Instr ImmLSPair(int imm7, LSDataSize size) { - ASSERT(((imm7 >> size) << size) == imm7); + VIXL_ASSERT(((imm7 >> size) << size) == imm7); int scaled_imm7 = imm7 >> size; - ASSERT(is_int7(scaled_imm7)); + VIXL_ASSERT(is_int7(scaled_imm7)); return truncate_to_int7(scaled_imm7) << ImmLSPair_offset; } static Instr ImmShiftLS(unsigned shift_amount) { - ASSERT(is_uint1(shift_amount)); + VIXL_ASSERT(is_uint1(shift_amount)); return shift_amount << ImmShiftLS_offset; } static Instr ImmException(int imm16) { - ASSERT(is_uint16(imm16)); + VIXL_ASSERT(is_uint16(imm16)); return imm16 << ImmException_offset; } static Instr ImmSystemRegister(int imm15) { - ASSERT(is_uint15(imm15)); + VIXL_ASSERT(is_uint15(imm15)); return imm15 << ImmSystemRegister_offset; } static Instr ImmHint(int imm7) { - ASSERT(is_uint7(imm7)); + VIXL_ASSERT(is_uint7(imm7)); return imm7 << ImmHint_offset; } + static Instr ImmBarrierDomain(int imm2) { + VIXL_ASSERT(is_uint2(imm2)); + return imm2 << ImmBarrierDomain_offset; + } + + static Instr ImmBarrierType(int imm2) { + VIXL_ASSERT(is_uint2(imm2)); + return imm2 << ImmBarrierType_offset; + } + static LSDataSize CalcLSDataSize(LoadStoreOp op) { - ASSERT((SizeLS_offset + SizeLS_width) == (kInstructionSize * 8)); + VIXL_ASSERT((SizeLS_offset + SizeLS_width) == (kInstructionSize * 8)); return static_cast(op >> SizeLS_offset); } // Move immediates encoding. static Instr ImmMoveWide(uint64_t imm) { - ASSERT(is_uint16(imm)); + VIXL_ASSERT(is_uint16(imm)); return imm << ImmMoveWide_offset; } static Instr ShiftMoveWide(int64_t shift) { - ASSERT(is_uint2(shift)); + VIXL_ASSERT(is_uint2(shift)); return shift << ShiftMoveWide_offset; } @@ -1543,20 +1655,20 @@ class Assembler { } static Instr FPScale(unsigned scale) { - ASSERT(is_uint6(scale)); + VIXL_ASSERT(is_uint6(scale)); return scale << FPScale_offset; } // Size of the code generated in bytes uint64_t SizeOfCodeGenerated() const { - ASSERT((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_))); + VIXL_ASSERT((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_))); return pc_ - buffer_; } // Size of the code generated since label to the current position. uint64_t SizeOfCodeGeneratedSince(Label* label) const { - ASSERT(label->IsBound()); - ASSERT((pc_ >= label->target()) && (pc_ < (buffer_ + buffer_size_))); + VIXL_ASSERT(label->IsBound()); + VIXL_ASSERT((pc_ >= label->target()) && (pc_ < (buffer_ + buffer_size_))); return pc_ - label->target(); } @@ -1568,7 +1680,7 @@ class Assembler { inline void ReleaseLiteralPool() { if (--literal_pool_monitor_ == 0) { // Has the literal pool been blocked for too long? - ASSERT(literals_.empty() || + VIXL_ASSERT(literals_.empty() || (pc_ < (literals_.back()->pc_ + kMaxLoadLiteralRange))); } } @@ -1622,6 +1734,9 @@ class Assembler { FlagsUpdate S, AddSubWithCarryOp op); + static bool IsImmFP32(float imm); + static bool IsImmFP64(double imm); + // Functions for emulating operands not directly supported by the instruction // set. void EmitShift(const Register& rd, @@ -1706,17 +1821,13 @@ class Assembler { const FPRegister& fa, FPDataProcessing3SourceOp op); - // Encoding helpers. - static bool IsImmFP32(float imm); - static bool IsImmFP64(double imm); - void RecordLiteral(int64_t imm, unsigned size); // Emit the instruction at pc_. void Emit(Instr instruction) { - ASSERT(sizeof(*pc_) == 1); - ASSERT(sizeof(instruction) == kInstructionSize); - ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_)); + VIXL_STATIC_ASSERT(sizeof(*pc_) == 1); + VIXL_STATIC_ASSERT(sizeof(instruction) == kInstructionSize); + VIXL_ASSERT((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_)); #ifdef DEBUG finalized_ = false; @@ -1729,8 +1840,8 @@ class Assembler { // Emit data inline in the instruction stream. void EmitData(void const * data, unsigned size) { - ASSERT(sizeof(*pc_) == 1); - ASSERT((pc_ + size) <= (buffer_ + buffer_size_)); + VIXL_STATIC_ASSERT(sizeof(*pc_) == 1); + VIXL_ASSERT((pc_ + size) <= (buffer_ + buffer_size_)); #ifdef DEBUG finalized_ = false; @@ -1744,7 +1855,7 @@ class Assembler { } inline void CheckBufferSpace() { - ASSERT(pc_ < (buffer_ + buffer_size_)); + VIXL_ASSERT(pc_ < (buffer_ + buffer_size_)); if (pc_ > next_literal_pool_check_) { CheckLiteralPool(); } diff --git a/disas/libvixl/a64/constants-a64.h b/disas/libvixl/a64/constants-a64.h index 2e0336dd0f..99677c1be3 100644 --- a/disas/libvixl/a64/constants-a64.h +++ b/disas/libvixl/a64/constants-a64.h @@ -116,6 +116,8 @@ V_(ImmCmpBranch, 23, 5, SignedBits) \ V_(ImmLLiteral, 23, 5, SignedBits) \ V_(ImmException, 20, 5, Bits) \ V_(ImmHint, 11, 5, Bits) \ +V_(ImmBarrierDomain, 11, 10, Bits) \ +V_(ImmBarrierType, 9, 8, Bits) \ \ /* System (MRS, MSR) */ \ V_(ImmSystemRegister, 19, 5, Bits) \ @@ -181,7 +183,7 @@ enum Condition { inline Condition InvertCondition(Condition cond) { // Conditions al and nv behave identically, as "always true". They can't be // inverted, because there is no "always false" condition. - ASSERT((cond != al) && (cond != nv)); + VIXL_ASSERT((cond != al) && (cond != nv)); return static_cast(cond ^ 1); } @@ -246,6 +248,20 @@ enum SystemHint { SEVL = 5 }; +enum BarrierDomain { + OuterShareable = 0, + NonShareable = 1, + InnerShareable = 2, + FullSystem = 3 +}; + +enum BarrierType { + BarrierOther = 0, + BarrierReads = 1, + BarrierWrites = 2, + BarrierAll = 3 +}; + // System/special register names. // This information is not encoded as one field but as the concatenation of // multiple fields (Op0<0>, Op1, Crn, Crm, Op2). @@ -274,7 +290,7 @@ enum SystemRegister { // // The enumerations can be used like this: // -// ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed); +// VIXL_ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed); // switch(instr->Mask(PCRelAddressingMask)) { // case ADR: Format("adr 'Xd, 'AddrPCRelByte"); break; // case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break; @@ -560,6 +576,15 @@ enum ExceptionOp { DCPS3 = ExceptionFixed | 0x00A00003 }; +enum MemBarrierOp { + MemBarrierFixed = 0xD503309F, + MemBarrierFMask = 0xFFFFF09F, + MemBarrierMask = 0xFFFFF0FF, + DSB = MemBarrierFixed | 0x00000000, + DMB = MemBarrierFixed | 0x00000020, + ISB = MemBarrierFixed | 0x00000040 +}; + // Any load or store. enum LoadStoreAnyOp { LoadStoreAnyFMask = 0x0a000000, @@ -927,17 +952,22 @@ enum FPDataProcessing1SourceOp { FRINTN = FRINTN_s, FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000, FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000, + FRINTP = FRINTP_s, FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000, FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000, + FRINTM = FRINTM_s, FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000, FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000, FRINTZ = FRINTZ_s, FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000, FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000, + FRINTA = FRINTA_s, FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000, FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000, + FRINTX = FRINTX_s, FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000, - FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000 + FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000, + FRINTI = FRINTI_s }; // Floating point data processing 2 source. diff --git a/disas/libvixl/a64/decoder-a64.cc b/disas/libvixl/a64/decoder-a64.cc index 9e9033c49c..8450eb3b49 100644 --- a/disas/libvixl/a64/decoder-a64.cc +++ b/disas/libvixl/a64/decoder-a64.cc @@ -132,7 +132,7 @@ void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor, } // We reached the end of the list. The last element must be // registered_visitor. - ASSERT(*it == registered_visitor); + VIXL_ASSERT(*it == registered_visitor); visitors_.insert(it, new_visitor); } @@ -150,7 +150,7 @@ void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor, } // We reached the end of the list. The last element must be // registered_visitor. - ASSERT(*it == registered_visitor); + VIXL_ASSERT(*it == registered_visitor); visitors_.push_back(new_visitor); } @@ -161,16 +161,16 @@ void Decoder::RemoveVisitor(DecoderVisitor* visitor) { void Decoder::DecodePCRelAddressing(Instruction* instr) { - ASSERT(instr->Bits(27, 24) == 0x0); + VIXL_ASSERT(instr->Bits(27, 24) == 0x0); // We know bit 28 is set, as = 0 is filtered out at the top level // decode. - ASSERT(instr->Bit(28) == 0x1); + VIXL_ASSERT(instr->Bit(28) == 0x1); VisitPCRelAddressing(instr); } void Decoder::DecodeBranchSystemException(Instruction* instr) { - ASSERT((instr->Bits(27, 24) == 0x4) || + VIXL_ASSERT((instr->Bits(27, 24) == 0x4) || (instr->Bits(27, 24) == 0x5) || (instr->Bits(27, 24) == 0x6) || (instr->Bits(27, 24) == 0x7) ); @@ -271,7 +271,7 @@ void Decoder::DecodeBranchSystemException(Instruction* instr) { void Decoder::DecodeLoadStore(Instruction* instr) { - ASSERT((instr->Bits(27, 24) == 0x8) || + VIXL_ASSERT((instr->Bits(27, 24) == 0x8) || (instr->Bits(27, 24) == 0x9) || (instr->Bits(27, 24) == 0xC) || (instr->Bits(27, 24) == 0xD) ); @@ -390,7 +390,7 @@ void Decoder::DecodeLoadStore(Instruction* instr) { void Decoder::DecodeLogical(Instruction* instr) { - ASSERT(instr->Bits(27, 24) == 0x2); + VIXL_ASSERT(instr->Bits(27, 24) == 0x2); if (instr->Mask(0x80400000) == 0x00400000) { VisitUnallocated(instr); @@ -409,7 +409,7 @@ void Decoder::DecodeLogical(Instruction* instr) { void Decoder::DecodeBitfieldExtract(Instruction* instr) { - ASSERT(instr->Bits(27, 24) == 0x3); + VIXL_ASSERT(instr->Bits(27, 24) == 0x3); if ((instr->Mask(0x80400000) == 0x80000000) || (instr->Mask(0x80400000) == 0x00400000) || @@ -434,7 +434,7 @@ void Decoder::DecodeBitfieldExtract(Instruction* instr) { void Decoder::DecodeAddSubImmediate(Instruction* instr) { - ASSERT(instr->Bits(27, 24) == 0x1); + VIXL_ASSERT(instr->Bits(27, 24) == 0x1); if (instr->Bit(23) == 1) { VisitUnallocated(instr); } else { @@ -444,8 +444,8 @@ void Decoder::DecodeAddSubImmediate(Instruction* instr) { void Decoder::DecodeDataProcessing(Instruction* instr) { - ASSERT((instr->Bits(27, 24) == 0xA) || - (instr->Bits(27, 24) == 0xB) ); + VIXL_ASSERT((instr->Bits(27, 24) == 0xA) || + (instr->Bits(27, 24) == 0xB)); if (instr->Bit(24) == 0) { if (instr->Bit(28) == 0) { @@ -559,8 +559,8 @@ void Decoder::DecodeDataProcessing(Instruction* instr) { void Decoder::DecodeFP(Instruction* instr) { - ASSERT((instr->Bits(27, 24) == 0xE) || - (instr->Bits(27, 24) == 0xF) ); + VIXL_ASSERT((instr->Bits(27, 24) == 0xE) || + (instr->Bits(27, 24) == 0xF)); if (instr->Bit(28) == 0) { DecodeAdvSIMDDataProcessing(instr); @@ -665,14 +665,14 @@ void Decoder::DecodeFP(Instruction* instr) { VisitFPConditionalSelect(instr); break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } } } } } else { // Bit 30 == 1 has been handled earlier. - ASSERT(instr->Bit(30) == 0); + VIXL_ASSERT(instr->Bit(30) == 0); if (instr->Mask(0xA0800000) != 0) { VisitUnallocated(instr); } else { @@ -687,21 +687,21 @@ void Decoder::DecodeFP(Instruction* instr) { void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) { // TODO: Implement Advanced SIMD load/store instruction decode. - ASSERT(instr->Bits(29, 25) == 0x6); + VIXL_ASSERT(instr->Bits(29, 25) == 0x6); VisitUnimplemented(instr); } void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) { // TODO: Implement Advanced SIMD data processing instruction decode. - ASSERT(instr->Bits(27, 25) == 0x7); + VIXL_ASSERT(instr->Bits(27, 25) == 0x7); VisitUnimplemented(instr); } #define DEFINE_VISITOR_CALLERS(A) \ void Decoder::Visit##A(Instruction *instr) { \ - ASSERT(instr->Mask(A##FMask) == A##Fixed); \ + VIXL_ASSERT(instr->Mask(A##FMask) == A##Fixed); \ std::list::iterator it; \ for (it = visitors_.begin(); it != visitors_.end(); it++) { \ (*it)->Visit##A(instr); \ diff --git a/disas/libvixl/a64/disasm-a64.cc b/disas/libvixl/a64/disasm-a64.cc index 5f172da7d3..aa133a99bf 100644 --- a/disas/libvixl/a64/disasm-a64.cc +++ b/disas/libvixl/a64/disasm-a64.cc @@ -95,7 +95,7 @@ void Disassembler::VisitAddSubImmediate(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -142,7 +142,7 @@ void Disassembler::VisitAddSubShifted(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -180,7 +180,7 @@ void Disassembler::VisitAddSubExtended(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -215,7 +215,7 @@ void Disassembler::VisitAddSubWithCarry(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -258,30 +258,30 @@ void Disassembler::VisitLogicalImmediate(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) { - ASSERT((reg_size == kXRegSize) || - ((reg_size == kWRegSize) && (value <= 0xffffffff))); + VIXL_ASSERT((reg_size == kXRegSize) || + ((reg_size == kWRegSize) && (value <= 0xffffffff))); // Test for movz: 16 bits set at positions 0, 16, 32 or 48. - if (((value & 0xffffffffffff0000ULL) == 0ULL) || - ((value & 0xffffffff0000ffffULL) == 0ULL) || - ((value & 0xffff0000ffffffffULL) == 0ULL) || - ((value & 0x0000ffffffffffffULL) == 0ULL)) { + if (((value & UINT64_C(0xffffffffffff0000)) == 0) || + ((value & UINT64_C(0xffffffff0000ffff)) == 0) || + ((value & UINT64_C(0xffff0000ffffffff)) == 0) || + ((value & UINT64_C(0x0000ffffffffffff)) == 0)) { return true; } // Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48). if ((reg_size == kXRegSize) && - (((value & 0xffffffffffff0000ULL) == 0xffffffffffff0000ULL) || - ((value & 0xffffffff0000ffffULL) == 0xffffffff0000ffffULL) || - ((value & 0xffff0000ffffffffULL) == 0xffff0000ffffffffULL) || - ((value & 0x0000ffffffffffffULL) == 0x0000ffffffffffffULL))) { + (((~value & UINT64_C(0xffffffffffff0000)) == 0) || + ((~value & UINT64_C(0xffffffff0000ffff)) == 0) || + ((~value & UINT64_C(0xffff0000ffffffff)) == 0) || + ((~value & UINT64_C(0x0000ffffffffffff)) == 0))) { return true; } if ((reg_size == kWRegSize) && @@ -337,7 +337,7 @@ void Disassembler::VisitLogicalShifted(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); @@ -353,7 +353,7 @@ void Disassembler::VisitConditionalCompareRegister(Instruction* instr) { case CCMN_x: mnemonic = "ccmn"; break; case CCMP_w: case CCMP_x: mnemonic = "ccmp"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -368,7 +368,7 @@ void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) { case CCMN_x_imm: mnemonic = "ccmn"; break; case CCMP_w_imm: case CCMP_x_imm: mnemonic = "ccmp"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -421,7 +421,7 @@ void Disassembler::VisitConditionalSelect(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -520,7 +520,7 @@ void Disassembler::VisitExtract(Instruction* instr) { } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -538,7 +538,7 @@ void Disassembler::VisitPCRelAddressing(Instruction* instr) { void Disassembler::VisitConditionalBranch(Instruction* instr) { switch (instr->Mask(ConditionalBranchMask)) { case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } } @@ -570,7 +570,7 @@ void Disassembler::VisitUnconditionalBranch(Instruction* instr) { switch (instr->Mask(UnconditionalBranchMask)) { case B: mnemonic = "b"; break; case BL: mnemonic = "bl"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -591,7 +591,7 @@ void Disassembler::VisitDataProcessing1Source(Instruction* instr) { FORMAT(CLS, "cls"); #undef FORMAT case REV32_x: mnemonic = "rev32"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -690,7 +690,7 @@ void Disassembler::VisitDataProcessing3Source(Instruction* instr) { form = form_xxx; break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -705,7 +705,7 @@ void Disassembler::VisitCompareBranch(Instruction* instr) { case CBZ_x: mnemonic = "cbz"; break; case CBNZ_w: case CBNZ_x: mnemonic = "cbnz"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -722,7 +722,7 @@ void Disassembler::VisitTestBranch(Instruction* instr) { switch (instr->Mask(TestBranchMask)) { case TBZ: mnemonic = "tbz"; break; case TBNZ: mnemonic = "tbnz"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -742,7 +742,7 @@ void Disassembler::VisitMoveWideImmediate(Instruction* instr) { case MOVZ_x: mnemonic = "movz"; break; case MOVK_w: case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -981,7 +981,7 @@ void Disassembler::VisitFPConditionalSelect(Instruction* instr) { switch (instr->Mask(FPConditionalSelectMask)) { case FCSEL_s: case FCSEL_d: mnemonic = "fcsel"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -1033,7 +1033,7 @@ void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) { FORMAT(FMINNM, "fminnm"); FORMAT(FNMUL, "fnmul"); #undef FORMAT - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -1052,7 +1052,7 @@ void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) { FORMAT(FNMADD, "fnmadd"); FORMAT(FNMSUB, "fnmsub"); #undef FORMAT - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -1065,7 +1065,7 @@ void Disassembler::VisitFPImmediate(Instruction* instr) { switch (instr->Mask(FPImmediateMask)) { case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break; case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -1082,6 +1082,14 @@ void Disassembler::VisitFPIntegerConvert(Instruction* instr) { case FMOV_xd: mnemonic = "fmov"; form = form_rf; break; case FMOV_sw: case FMOV_dx: mnemonic = "fmov"; form = form_fr; break; + case FCVTAS_ws: + case FCVTAS_xs: + case FCVTAS_wd: + case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break; + case FCVTAU_ws: + case FCVTAU_xs: + case FCVTAU_wd: + case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break; case FCVTMS_ws: case FCVTMS_xs: case FCVTMS_wd: @@ -1141,7 +1149,7 @@ void Disassembler::VisitFPFixedPointConvert(Instruction* instr) { case UCVTF_sx_fixed: case UCVTF_dw_fixed: case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } Format(instr, mnemonic, form); } @@ -1176,7 +1184,7 @@ void Disassembler::VisitSystem(Instruction* instr) { } } } else if (instr->Mask(SystemHintFMask) == SystemHintFixed) { - ASSERT(instr->Mask(SystemHintMask) == HINT); + VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT); switch (instr->ImmHint()) { case NOP: { mnemonic = "nop"; @@ -1184,6 +1192,24 @@ void Disassembler::VisitSystem(Instruction* instr) { break; } } + } else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) { + switch (instr->Mask(MemBarrierMask)) { + case DMB: { + mnemonic = "dmb"; + form = "'M"; + break; + } + case DSB: { + mnemonic = "dsb"; + form = "'M"; + break; + } + case ISB: { + mnemonic = "isb"; + form = NULL; + break; + } + } } Format(instr, mnemonic, form); @@ -1226,7 +1252,7 @@ void Disassembler::ProcessOutput(Instruction* /*instr*/) { void Disassembler::Format(Instruction* instr, const char* mnemonic, const char* format) { - ASSERT(mnemonic != NULL); + VIXL_ASSERT(mnemonic != NULL); ResetOutput(); Substitute(instr, mnemonic); if (format != NULL) { @@ -1268,8 +1294,9 @@ int Disassembler::SubstituteField(Instruction* instr, const char* format) { case 'A': return SubstitutePCRelAddressField(instr, format); case 'B': return SubstituteBranchTargetField(instr, format); case 'O': return SubstituteLSRegOffsetField(instr, format); + case 'M': return SubstituteBarrierField(instr, format); default: { - UNREACHABLE(); + VIXL_UNREACHABLE(); return 1; } } @@ -1294,7 +1321,7 @@ int Disassembler::SubstituteRegisterField(Instruction* instr, } break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } // Increase field length for registers tagged as stack. @@ -1331,7 +1358,7 @@ int Disassembler::SubstituteRegisterField(Instruction* instr, int Disassembler::SubstituteImmediateField(Instruction* instr, const char* format) { - ASSERT(format[0] == 'I'); + VIXL_ASSERT(format[0] == 'I'); switch (format[1]) { case 'M': { // IMoveImm or IMoveLSL. @@ -1339,10 +1366,10 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide()); AppendToOutput("#0x%" PRIx64, imm); } else { - ASSERT(format[5] == 'L'); + VIXL_ASSERT(format[5] == 'L'); AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide()); if (instr->ShiftMoveWide() > 0) { - AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide()); + AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide()); } } return 8; @@ -1384,14 +1411,14 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, return 6; } case 'A': { // IAddSub. - ASSERT(instr->ShiftAddSub() <= 1); + VIXL_ASSERT(instr->ShiftAddSub() <= 1); int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub()); AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm); return 7; } case 'F': { // IFPSingle, IFPDouble or IFPFBits. if (format[3] == 'F') { // IFPFbits. - AppendToOutput("#%" PRId64, 64 - instr->FPScale()); + AppendToOutput("#%d", 64 - instr->FPScale()); return 8; } else { AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(), @@ -1412,27 +1439,27 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, return 5; } case 'P': { // IP - Conditional compare. - AppendToOutput("#%" PRId64, instr->ImmCondCmp()); + AppendToOutput("#%d", instr->ImmCondCmp()); return 2; } case 'B': { // Bitfields. return SubstituteBitfieldImmediateField(instr, format); } case 'E': { // IExtract. - AppendToOutput("#%" PRId64, instr->ImmS()); + AppendToOutput("#%d", instr->ImmS()); return 8; } case 'S': { // IS - Test and branch bit. - AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) | - instr->ImmTestBranchBit40()); + AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) | + instr->ImmTestBranchBit40()); return 2; } case 'D': { // IDebug - HLT and BRK instructions. - AppendToOutput("#0x%" PRIx64, instr->ImmException()); + AppendToOutput("#0x%x", instr->ImmException()); return 6; } default: { - UNIMPLEMENTED(); + VIXL_UNIMPLEMENTED(); return 0; } } @@ -1441,7 +1468,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr, int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr, const char* format) { - ASSERT((format[0] == 'I') && (format[1] == 'B')); + VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B')); unsigned r = instr->ImmR(); unsigned s = instr->ImmS(); @@ -1455,19 +1482,19 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr, AppendToOutput("#%d", s + 1); return 5; } else { - ASSERT(format[3] == '-'); + VIXL_ASSERT(format[3] == '-'); AppendToOutput("#%d", s - r + 1); return 7; } } case 'Z': { // IBZ-r. - ASSERT((format[3] == '-') && (format[4] == 'r')); + VIXL_ASSERT((format[3] == '-') && (format[4] == 'r')); unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize; AppendToOutput("#%d", reg_size - r); return 5; } default: { - UNREACHABLE(); + VIXL_UNREACHABLE(); return 0; } } @@ -1476,7 +1503,7 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr, int Disassembler::SubstituteLiteralField(Instruction* instr, const char* format) { - ASSERT(strncmp(format, "LValue", 6) == 0); + VIXL_ASSERT(strncmp(format, "LValue", 6) == 0); USE(format); switch (instr->Mask(LoadLiteralMask)) { @@ -1484,7 +1511,7 @@ int Disassembler::SubstituteLiteralField(Instruction* instr, case LDR_x_lit: case LDR_s_lit: case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break; - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } return 6; @@ -1492,12 +1519,12 @@ int Disassembler::SubstituteLiteralField(Instruction* instr, int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) { - ASSERT(format[0] == 'H'); - ASSERT(instr->ShiftDP() <= 0x3); + VIXL_ASSERT(format[0] == 'H'); + VIXL_ASSERT(instr->ShiftDP() <= 0x3); switch (format[1]) { case 'D': { // HDP. - ASSERT(instr->ShiftDP() != ROR); + VIXL_ASSERT(instr->ShiftDP() != ROR); } // Fall through. case 'L': { // HLo. if (instr->ImmDPShift() != 0) { @@ -1508,7 +1535,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) { return 3; } default: - UNIMPLEMENTED(); + VIXL_UNIMPLEMENTED(); return 0; } } @@ -1516,7 +1543,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) { int Disassembler::SubstituteConditionField(Instruction* instr, const char* format) { - ASSERT(format[0] == 'C'); + VIXL_ASSERT(format[0] == 'C'); const char* condition_code[] = { "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", "hi", "ls", "ge", "lt", @@ -1538,27 +1565,27 @@ int Disassembler::SubstituteConditionField(Instruction* instr, int Disassembler::SubstitutePCRelAddressField(Instruction* instr, const char* format) { USE(format); - ASSERT(strncmp(format, "AddrPCRel", 9) == 0); + VIXL_ASSERT(strncmp(format, "AddrPCRel", 9) == 0); int offset = instr->ImmPCRel(); // Only ADR (AddrPCRelByte) is supported. - ASSERT(strcmp(format, "AddrPCRelByte") == 0); + VIXL_ASSERT(strcmp(format, "AddrPCRelByte") == 0); char sign = '+'; if (offset < 0) { offset = -offset; sign = '-'; } - // TODO: Extend this to support printing the target address. - AppendToOutput("#%c0x%x", sign, offset); + VIXL_STATIC_ASSERT(sizeof(*instr) == 1); + AppendToOutput("#%c0x%x (addr %p)", sign, offset, instr + offset); return 13; } int Disassembler::SubstituteBranchTargetField(Instruction* instr, const char* format) { - ASSERT(strncmp(format, "BImm", 4) == 0); + VIXL_ASSERT(strncmp(format, "BImm", 4) == 0); int64_t offset = 0; switch (format[5]) { @@ -1570,7 +1597,7 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr, case 'm': offset = instr->ImmCmpBranch(); break; // BImmTest - test and branch immediate. case 'e': offset = instr->ImmTestBranch(); break; - default: UNIMPLEMENTED(); + default: VIXL_UNIMPLEMENTED(); } offset <<= kInstructionSizeLog2; char sign = '+'; @@ -1578,15 +1605,16 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr, offset = -offset; sign = '-'; } - AppendToOutput("#%c0x%" PRIx64, sign, offset); + VIXL_STATIC_ASSERT(sizeof(*instr) == 1); + AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset, instr + offset); return 8; } int Disassembler::SubstituteExtendField(Instruction* instr, const char* format) { - ASSERT(strncmp(format, "Ext", 3) == 0); - ASSERT(instr->ExtendMode() <= 7); + VIXL_ASSERT(strncmp(format, "Ext", 3) == 0); + VIXL_ASSERT(instr->ExtendMode() <= 7); USE(format); const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx", @@ -1598,12 +1626,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr, (((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) || (instr->ExtendMode() == UXTX))) { if (instr->ImmExtendShift() > 0) { - AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift()); + AppendToOutput(", lsl #%d", instr->ImmExtendShift()); } } else { AppendToOutput(", %s", extend_mode[instr->ExtendMode()]); if (instr->ImmExtendShift() > 0) { - AppendToOutput(" #%" PRId64, instr->ImmExtendShift()); + AppendToOutput(" #%d", instr->ImmExtendShift()); } } return 3; @@ -1612,7 +1640,7 @@ int Disassembler::SubstituteExtendField(Instruction* instr, int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, const char* format) { - ASSERT(strncmp(format, "Offsetreg", 9) == 0); + VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0); const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl", "undefined", "undefined", "sxtw", "sxtx" }; USE(format); @@ -1632,7 +1660,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, if (!((ext == UXTX) && (shift == 0))) { AppendToOutput(", %s", extend_mode[ext]); if (shift != 0) { - AppendToOutput(" #%" PRId64, instr->SizeLS()); + AppendToOutput(" #%d", instr->SizeLS()); } } return 9; @@ -1641,7 +1669,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr, int Disassembler::SubstitutePrefetchField(Instruction* instr, const char* format) { - ASSERT(format[0] == 'P'); + VIXL_ASSERT(format[0] == 'P'); USE(format); int prefetch_mode = instr->PrefetchMode(); @@ -1654,6 +1682,23 @@ int Disassembler::SubstitutePrefetchField(Instruction* instr, return 6; } +int Disassembler::SubstituteBarrierField(Instruction* instr, + const char* format) { + VIXL_ASSERT(format[0] == 'M'); + USE(format); + + static const char* options[4][4] = { + { "sy (0b0000)", "oshld", "oshst", "osh" }, + { "sy (0b0100)", "nshld", "nshst", "nsh" }, + { "sy (0b1000)", "ishld", "ishst", "ish" }, + { "sy (0b1100)", "ld", "st", "sy" } + }; + int domain = instr->ImmBarrierDomain(); + int type = instr->ImmBarrierType(); + + AppendToOutput("%s", options[domain][type]); + return 1; +} void Disassembler::ResetOutput() { buffer_pos_ = 0; diff --git a/disas/libvixl/a64/disasm-a64.h b/disas/libvixl/a64/disasm-a64.h index 857a5acac4..3a56e15515 100644 --- a/disas/libvixl/a64/disasm-a64.h +++ b/disas/libvixl/a64/disasm-a64.h @@ -64,6 +64,7 @@ class Disassembler: public DecoderVisitor { int SubstituteBranchTargetField(Instruction* instr, const char* format); int SubstituteLSRegOffsetField(Instruction* instr, const char* format); int SubstitutePrefetchField(Instruction* instr, const char* format); + int SubstituteBarrierField(Instruction* instr, const char* format); inline bool RdIsZROrSP(Instruction* instr) const { return (instr->Rd() == kZeroRegCode); diff --git a/disas/libvixl/a64/instructions-a64.cc b/disas/libvixl/a64/instructions-a64.cc index e87fa3acce..c4eb7c4518 100644 --- a/disas/libvixl/a64/instructions-a64.cc +++ b/disas/libvixl/a64/instructions-a64.cc @@ -33,20 +33,20 @@ namespace vixl { static uint64_t RotateRight(uint64_t value, unsigned int rotate, unsigned int width) { - ASSERT(width <= 64); + VIXL_ASSERT(width <= 64); rotate &= 63; - return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) | - (value >> rotate); + return ((value & ((UINT64_C(1) << rotate) - 1)) << + (width - rotate)) | (value >> rotate); } static uint64_t RepeatBitsAcrossReg(unsigned reg_size, uint64_t value, unsigned width) { - ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) || - (width == 32)); - ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); - uint64_t result = value & ((1UL << width) - 1UL); + VIXL_ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) || + (width == 32)); + VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize)); + uint64_t result = value & ((UINT64_C(1) << width) - 1); for (unsigned i = width; i < reg_size; i *= 2) { result |= (result << i); } @@ -84,7 +84,7 @@ uint64_t Instruction::ImmLogical() { if (imm_s == 0x3F) { return 0; } - uint64_t bits = (1UL << (imm_s + 1)) - 1; + uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1; return RotateRight(bits, imm_r, 64); } else { if ((imm_s >> 1) == 0x1F) { @@ -96,14 +96,14 @@ uint64_t Instruction::ImmLogical() { if ((imm_s & mask) == mask) { return 0; } - uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1; + uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1; return RepeatBitsAcrossReg(reg_size, RotateRight(bits, imm_r & mask, width), width); } } } - UNREACHABLE(); + VIXL_UNREACHABLE(); return 0; } @@ -155,7 +155,7 @@ Instruction* Instruction::ImmPCOffsetTarget() { offset = ImmPCRel(); } else { // All PC-relative branches. - ASSERT(BranchType() != UnknownBranchType); + VIXL_ASSERT(BranchType() != UnknownBranchType); // Relative branch offsets are instruction-size-aligned. offset = ImmBranch() << kInstructionSizeLog2; } @@ -169,7 +169,7 @@ inline int Instruction::ImmBranch() const { case UncondBranchType: return ImmUncondBranch(); case CompareBranchType: return ImmCmpBranch(); case TestBranchType: return ImmTestBranch(); - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } return 0; } @@ -186,7 +186,7 @@ void Instruction::SetImmPCOffsetTarget(Instruction* target) { void Instruction::SetPCRelImmTarget(Instruction* target) { // ADRP is not supported, so 'this' must point to an ADR instruction. - ASSERT(Mask(PCRelAddressingMask) == ADR); + VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR); Instr imm = Assembler::ImmPCRelAddress(target - this); @@ -195,7 +195,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) { void Instruction::SetBranchImmTarget(Instruction* target) { - ASSERT(((target - this) & 3) == 0); + VIXL_ASSERT(((target - this) & 3) == 0); Instr branch_imm = 0; uint32_t imm_mask = 0; int offset = (target - this) >> kInstructionSizeLog2; @@ -220,14 +220,14 @@ void Instruction::SetBranchImmTarget(Instruction* target) { imm_mask = ImmTestBranch_mask; break; } - default: UNREACHABLE(); + default: VIXL_UNREACHABLE(); } SetInstructionBits(Mask(~imm_mask) | branch_imm); } void Instruction::SetImmLLiteral(Instruction* source) { - ASSERT(((source - this) & 3) == 0); + VIXL_ASSERT(((source - this) & 3) == 0); int offset = (source - this) >> kLiteralEntrySizeLog2; Instr imm = Assembler::ImmLLiteral(offset); Instr mask = ImmLLiteral_mask; diff --git a/disas/libvixl/a64/instructions-a64.h b/disas/libvixl/a64/instructions-a64.h index ba9068ca8b..a4240d7d33 100644 --- a/disas/libvixl/a64/instructions-a64.h +++ b/disas/libvixl/a64/instructions-a64.h @@ -44,30 +44,36 @@ const unsigned kMaxLoadLiteralRange = 1 * MBytes; const unsigned kWRegSize = 32; const unsigned kWRegSizeLog2 = 5; const unsigned kWRegSizeInBytes = kWRegSize / 8; +const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3; const unsigned kXRegSize = 64; const unsigned kXRegSizeLog2 = 6; const unsigned kXRegSizeInBytes = kXRegSize / 8; +const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3; const unsigned kSRegSize = 32; const unsigned kSRegSizeLog2 = 5; const unsigned kSRegSizeInBytes = kSRegSize / 8; +const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3; const unsigned kDRegSize = 64; const unsigned kDRegSizeLog2 = 6; const unsigned kDRegSizeInBytes = kDRegSize / 8; -const int64_t kWRegMask = 0x00000000ffffffffLL; -const int64_t kXRegMask = 0xffffffffffffffffLL; -const int64_t kSRegMask = 0x00000000ffffffffLL; -const int64_t kDRegMask = 0xffffffffffffffffLL; -const int64_t kXSignMask = 0x1LL << 63; -const int64_t kWSignMask = 0x1LL << 31; -const int64_t kByteMask = 0xffL; -const int64_t kHalfWordMask = 0xffffL; -const int64_t kWordMask = 0xffffffffLL; -const uint64_t kXMaxUInt = 0xffffffffffffffffULL; -const uint64_t kWMaxUInt = 0xffffffffULL; -const int64_t kXMaxInt = 0x7fffffffffffffffLL; -const int64_t kXMinInt = 0x8000000000000000LL; -const int32_t kWMaxInt = 0x7fffffff; -const int32_t kWMinInt = 0x80000000; +const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3; +const uint64_t kWRegMask = UINT64_C(0xffffffff); +const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff); +const uint64_t kSRegMask = UINT64_C(0xffffffff); +const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff); +const uint64_t kSSignMask = UINT64_C(0x80000000); +const uint64_t kDSignMask = UINT64_C(0x8000000000000000); +const uint64_t kWSignMask = UINT64_C(0x80000000); +const uint64_t kXSignMask = UINT64_C(0x8000000000000000); +const uint64_t kByteMask = UINT64_C(0xff); +const uint64_t kHalfWordMask = UINT64_C(0xffff); +const uint64_t kWordMask = UINT64_C(0xffffffff); +const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff); +const uint64_t kWMaxUInt = UINT64_C(0xffffffff); +const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff); +const int64_t kXMinInt = INT64_C(0x8000000000000000); +const int32_t kWMaxInt = INT32_C(0x7fffffff); +const int32_t kWMinInt = INT32_C(0x80000000); const unsigned kLinkRegCode = 30; const unsigned kZeroRegCode = 31; const unsigned kSPRegInternalCode = 63; @@ -81,18 +87,28 @@ const unsigned kFloatExponentBits = 8; const float kFP32PositiveInfinity = rawbits_to_float(0x7f800000); const float kFP32NegativeInfinity = rawbits_to_float(0xff800000); -const double kFP64PositiveInfinity = rawbits_to_double(0x7ff0000000000000ULL); -const double kFP64NegativeInfinity = rawbits_to_double(0xfff0000000000000ULL); +const double kFP64PositiveInfinity = + rawbits_to_double(UINT64_C(0x7ff0000000000000)); +const double kFP64NegativeInfinity = + rawbits_to_double(UINT64_C(0xfff0000000000000)); // This value is a signalling NaN as both a double and as a float (taking the // least-significant word). -static const double kFP64SignallingNaN = rawbits_to_double(0x7ff000007f800001ULL); +static const double kFP64SignallingNaN = + rawbits_to_double(UINT64_C(0x7ff000007f800001)); static const float kFP32SignallingNaN = rawbits_to_float(0x7f800001); // A similar value, but as a quiet NaN. -static const double kFP64QuietNaN = rawbits_to_double(0x7ff800007fc00001ULL); +static const double kFP64QuietNaN = + rawbits_to_double(UINT64_C(0x7ff800007fc00001)); static const float kFP32QuietNaN = rawbits_to_float(0x7fc00001); +// The default NaN values (for FPCR.DN=1). +static const double kFP64DefaultNaN = + rawbits_to_double(UINT64_C(0x7ff8000000000000)); +static const float kFP32DefaultNaN = rawbits_to_float(0x7fc00000); + + enum LSDataSize { LSByte = 0, LSHalfword = 1, @@ -325,7 +341,7 @@ class Instruction { } inline Instruction* InstructionAtOffset(int64_t offset) { - ASSERT(IsWordAligned(this + offset)); + VIXL_ASSERT(IsWordAligned(this + offset)); return this + offset; } diff --git a/disas/libvixl/globals.h b/disas/libvixl/globals.h index a6a3fccd8a..e28dc6663a 100644 --- a/disas/libvixl/globals.h +++ b/disas/libvixl/globals.h @@ -27,8 +27,20 @@ #ifndef VIXL_GLOBALS_H #define VIXL_GLOBALS_H -// Get the standard printf format macros for C99 stdint types. +// Get standard C99 macros for integer types. +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif + +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS +#endif + +#ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS +#endif + +#include #include #include @@ -45,21 +57,29 @@ typedef uint8_t byte; const int KBytes = 1024; const int MBytes = 1024 * KBytes; - #define ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort() +#define VIXL_ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort() #ifdef DEBUG - #define ASSERT(condition) assert(condition) - #define CHECK(condition) ASSERT(condition) - #define UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); ABORT() - #define UNREACHABLE() printf("UNREACHABLE\t"); ABORT() + #define VIXL_ASSERT(condition) assert(condition) + #define VIXL_CHECK(condition) VIXL_ASSERT(condition) + #define VIXL_UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); VIXL_ABORT() + #define VIXL_UNREACHABLE() printf("UNREACHABLE\t"); VIXL_ABORT() #else - #define ASSERT(condition) ((void) 0) - #define CHECK(condition) assert(condition) - #define UNIMPLEMENTED() ((void) 0) - #define UNREACHABLE() ((void) 0) + #define VIXL_ASSERT(condition) ((void) 0) + #define VIXL_CHECK(condition) assert(condition) + #define VIXL_UNIMPLEMENTED() ((void) 0) + #define VIXL_UNREACHABLE() ((void) 0) #endif +// This is not as powerful as template based assertions, but it is simple. +// It assumes that the descriptions are unique. If this starts being a problem, +// we can switch to a different implemention. +#define VIXL_CONCAT(a, b) a##b +#define VIXL_STATIC_ASSERT_LINE(line, condition) \ + typedef char VIXL_CONCAT(STATIC_ASSERT_LINE_, line)[(condition) ? 1 : -1] \ + __attribute__((unused)) +#define VIXL_STATIC_ASSERT(condition) VIXL_STATIC_ASSERT_LINE(__LINE__, condition) //NOLINT template inline void USE(T) {} -#define ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); ABORT() +#define VIXL_ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); VIXL_ABORT() #endif // VIXL_GLOBALS_H diff --git a/disas/libvixl/platform.h b/disas/libvixl/platform.h index a2600f370d..b5c2085b90 100644 --- a/disas/libvixl/platform.h +++ b/disas/libvixl/platform.h @@ -34,9 +34,7 @@ namespace vixl { // Currently we assume running the simulator implies running on x86 hardware. inline void HostBreakpoint() { asm("int3"); } #else -inline void HostBreakpoint() { - // TODO: Implement HostBreakpoint on a64. -} +inline void HostBreakpoint() { asm("brk"); } #endif } // namespace vixl diff --git a/disas/libvixl/utils.cc b/disas/libvixl/utils.cc index a45fb95f47..c9c05d1e18 100644 --- a/disas/libvixl/utils.cc +++ b/disas/libvixl/utils.cc @@ -58,9 +58,9 @@ double rawbits_to_double(uint64_t bits) { int CountLeadingZeros(uint64_t value, int width) { - ASSERT((width == 32) || (width == 64)); + VIXL_ASSERT((width == 32) || (width == 64)); int count = 0; - uint64_t bit_test = 1UL << (width - 1); + uint64_t bit_test = UINT64_C(1) << (width - 1); while ((count < width) && ((bit_test & value) == 0)) { count++; bit_test >>= 1; @@ -70,7 +70,7 @@ int CountLeadingZeros(uint64_t value, int width) { int CountLeadingSignBits(int64_t value, int width) { - ASSERT((width == 32) || (width == 64)); + VIXL_ASSERT((width == 32) || (width == 64)); if (value >= 0) { return CountLeadingZeros(value, width) - 1; } else { @@ -80,7 +80,7 @@ int CountLeadingSignBits(int64_t value, int width) { int CountTrailingZeros(uint64_t value, int width) { - ASSERT((width == 32) || (width == 64)); + VIXL_ASSERT((width == 32) || (width == 64)); int count = 0; while ((count < width) && (((value >> count) & 1) == 0)) { count++; @@ -92,10 +92,10 @@ int CountTrailingZeros(uint64_t value, int width) { int CountSetBits(uint64_t value, int width) { // TODO: Other widths could be added here, as the implementation already // supports them. - ASSERT((width == 32) || (width == 64)); + VIXL_ASSERT((width == 32) || (width == 64)); // Mask out unused bits to ensure that they are not counted. - value &= (0xffffffffffffffffULL >> (64-width)); + value &= (UINT64_C(0xffffffffffffffff) >> (64-width)); // Add up the set bits. // The algorithm works by adding pairs of bit fields together iteratively, @@ -108,18 +108,19 @@ int CountSetBits(uint64_t value, int width) { // value = h+g+f+e d+c+b+a // \ | // value = h+g+f+e+d+c+b+a - value = ((value >> 1) & 0x5555555555555555ULL) + - (value & 0x5555555555555555ULL); - value = ((value >> 2) & 0x3333333333333333ULL) + - (value & 0x3333333333333333ULL); - value = ((value >> 4) & 0x0f0f0f0f0f0f0f0fULL) + - (value & 0x0f0f0f0f0f0f0f0fULL); - value = ((value >> 8) & 0x00ff00ff00ff00ffULL) + - (value & 0x00ff00ff00ff00ffULL); - value = ((value >> 16) & 0x0000ffff0000ffffULL) + - (value & 0x0000ffff0000ffffULL); - value = ((value >> 32) & 0x00000000ffffffffULL) + - (value & 0x00000000ffffffffULL); + const uint64_t kMasks[] = { + UINT64_C(0x5555555555555555), + UINT64_C(0x3333333333333333), + UINT64_C(0x0f0f0f0f0f0f0f0f), + UINT64_C(0x00ff00ff00ff00ff), + UINT64_C(0x0000ffff0000ffff), + UINT64_C(0x00000000ffffffff), + }; + + for (unsigned i = 0; i < (sizeof(kMasks) / sizeof(kMasks[0])); i++) { + int shift = 1 << i; + value = ((value >> shift) & kMasks[i]) + (value & kMasks[i]); + } return value; } diff --git a/disas/libvixl/utils.h b/disas/libvixl/utils.h index 029341eb14..83c928c8e3 100644 --- a/disas/libvixl/utils.h +++ b/disas/libvixl/utils.h @@ -27,7 +27,7 @@ #ifndef VIXL_UTILS_H #define VIXL_UTILS_H - +#include #include #include "globals.h" @@ -35,19 +35,19 @@ namespace vixl { // Check number width. inline bool is_intn(unsigned n, int64_t x) { - ASSERT((0 < n) && (n < 64)); - int64_t limit = 1ULL << (n - 1); + VIXL_ASSERT((0 < n) && (n < 64)); + int64_t limit = INT64_C(1) << (n - 1); return (-limit <= x) && (x < limit); } inline bool is_uintn(unsigned n, int64_t x) { - ASSERT((0 < n) && (n < 64)); + VIXL_ASSERT((0 < n) && (n < 64)); return !(x >> n); } inline unsigned truncate_to_intn(unsigned n, int64_t x) { - ASSERT((0 < n) && (n < 64)); - return (x & ((1ULL << n) - 1)); + VIXL_ASSERT((0 < n) && (n < 64)); + return (x & ((INT64_C(1) << n) - 1)); } #define INT_1_TO_63_LIST(V) \ @@ -90,13 +90,67 @@ inline int64_t signed_bitextract_64(int msb, int lsb, int64_t x) { return (x << (63 - msb)) >> (lsb + 63 - msb); } -// floating point representation +// Floating point representation. uint32_t float_to_rawbits(float value); uint64_t double_to_rawbits(double value); float rawbits_to_float(uint32_t bits); double rawbits_to_double(uint64_t bits); -// Bits counting. + +// NaN tests. +inline bool IsSignallingNaN(double num) { + const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000); + uint64_t raw = double_to_rawbits(num); + if (isnan(num) && ((raw & kFP64QuietNaNMask) == 0)) { + return true; + } + return false; +} + + +inline bool IsSignallingNaN(float num) { + const uint32_t kFP32QuietNaNMask = 0x00400000; + uint32_t raw = float_to_rawbits(num); + if (isnan(num) && ((raw & kFP32QuietNaNMask) == 0)) { + return true; + } + return false; +} + + +template +inline bool IsQuietNaN(T num) { + return isnan(num) && !IsSignallingNaN(num); +} + + +// Convert the NaN in 'num' to a quiet NaN. +inline double ToQuietNaN(double num) { + const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000); + VIXL_ASSERT(isnan(num)); + return rawbits_to_double(double_to_rawbits(num) | kFP64QuietNaNMask); +} + + +inline float ToQuietNaN(float num) { + const uint32_t kFP32QuietNaNMask = 0x00400000; + VIXL_ASSERT(isnan(num)); + return rawbits_to_float(float_to_rawbits(num) | kFP32QuietNaNMask); +} + + +// Fused multiply-add. +inline double FusedMultiplyAdd(double op1, double op2, double a) { + return fma(op1, op2, a); +} + + +inline float FusedMultiplyAdd(float op1, float op2, float a) { + return fmaf(op1, op2, a); +} + + +// Bit counting. int CountLeadingZeros(uint64_t value, int width); int CountLeadingSignBits(int64_t value, int width); int CountTrailingZeros(uint64_t value, int width); @@ -106,20 +160,30 @@ int CountSetBits(uint64_t value, int width); // TODO: rename/refactor to make it specific to instructions. template bool IsWordAligned(T pointer) { - ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof) + VIXL_ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof) return (reinterpret_cast(pointer) & 3) == 0; } // Increment a pointer until it has the specified alignment. template T AlignUp(T pointer, size_t alignment) { - ASSERT(sizeof(pointer) == sizeof(uintptr_t)); + VIXL_STATIC_ASSERT(sizeof(pointer) == sizeof(uintptr_t)); uintptr_t pointer_raw = reinterpret_cast(pointer); size_t align_step = (alignment - pointer_raw) % alignment; - ASSERT((pointer_raw + align_step) % alignment == 0); + VIXL_ASSERT((pointer_raw + align_step) % alignment == 0); return reinterpret_cast(pointer_raw + align_step); } +// Decrement a pointer until it has the specified alignment. +template +T AlignDown(T pointer, size_t alignment) { + VIXL_STATIC_ASSERT(sizeof(pointer) == sizeof(uintptr_t)); + uintptr_t pointer_raw = reinterpret_cast(pointer); + size_t align_step = pointer_raw % alignment; + VIXL_ASSERT((pointer_raw - align_step) % alignment == 0); + return reinterpret_cast(pointer_raw - align_step); +} + } // namespace vixl diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 46b9f1e0c0..24231e5448 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -134,7 +134,6 @@ static VMStateDescription vmstate_highbank_regs = { .name = "highbank-regs", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS), VMSTATE_END_OF_LIST(), diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index de542010aa..2a27a19d76 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -405,7 +405,6 @@ static const VMStateDescription mv88w8618_eth_vmsd = { .name = "mv88w8618_eth", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(smir, mv88w8618_eth_state), VMSTATE_UINT32(icr, mv88w8618_eth_state), @@ -642,7 +641,6 @@ static const VMStateDescription musicpal_lcd_vmsd = { .name = "musicpal_lcd", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(brightness, musicpal_lcd_state), VMSTATE_UINT32(mode, musicpal_lcd_state), @@ -769,7 +767,6 @@ static const VMStateDescription mv88w8618_pic_vmsd = { .name = "mv88w8618_pic", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(level, mv88w8618_pic_state), VMSTATE_UINT32(enabled, mv88w8618_pic_state), @@ -940,7 +937,6 @@ static const VMStateDescription mv88w8618_timer_vmsd = { .name = "timer", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_PTIMER(ptimer, mv88w8618_timer_state), VMSTATE_UINT32(limit, mv88w8618_timer_state), @@ -952,7 +948,6 @@ static const VMStateDescription mv88w8618_pit_vmsd = { .name = "mv88w8618_pit", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT_ARRAY(timer, mv88w8618_pit_state, 4, 1, mv88w8618_timer_vmsd, mv88w8618_timer_state), @@ -1041,7 +1036,6 @@ static const VMStateDescription mv88w8618_flashcfg_vmsd = { .name = "mv88w8618_flashcfg", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(cfgr0, mv88w8618_flashcfg_state), VMSTATE_END_OF_LIST() @@ -1381,7 +1375,6 @@ static const VMStateDescription musicpal_gpio_vmsd = { .name = "musicpal_gpio", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(lcd_brightness, musicpal_gpio_state), VMSTATE_UINT32(out_state, musicpal_gpio_state), @@ -1548,7 +1541,6 @@ static const VMStateDescription musicpal_key_vmsd = { .name = "musicpal_key", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(kbd_extended, musicpal_key_state), VMSTATE_UINT32(pressed_keys, musicpal_key_state), diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index b433748c60..b28e0521b4 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -2709,8 +2709,8 @@ static void omap_rtc_write(void *opaque, hwaddr addr, s->ti += ti[1]; } else { /* A less accurate version */ - s->ti -= (s->current_tm.tm_year % 100) * 31536000; - s->ti += from_bcd(value) * 31536000; + s->ti -= (time_t)(s->current_tm.tm_year % 100) * 31536000; + s->ti += (time_t)from_bcd(value) * 31536000; } return; diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index e0cd847b95..2d28a11d5e 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -148,8 +148,7 @@ static const VMStateDescription vmstate_pxa2xx_pm = { .name = "pxa2xx_pm", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(pm_regs, PXA2xxState, 0x40), VMSTATE_END_OF_LIST() } @@ -215,8 +214,7 @@ static const VMStateDescription vmstate_pxa2xx_cm = { .name = "pxa2xx_cm", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(cm_regs, PXA2xxState, 4), VMSTATE_UINT32(clkcfg, PXA2xxState), VMSTATE_UINT32(pmnc, PXA2xxState), @@ -440,8 +438,7 @@ static const VMStateDescription vmstate_pxa2xx_mm = { .name = "pxa2xx_mm", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(mm_regs, PXA2xxState, 0x1a), VMSTATE_END_OF_LIST() } @@ -1172,7 +1169,6 @@ static const VMStateDescription vmstate_pxa2xx_rtc_regs = { .name = "pxa2xx_rtc", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .pre_save = pxa2xx_rtc_pre_save, .post_load = pxa2xx_rtc_post_load, .fields = (VMStateField[]) { @@ -1436,8 +1432,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c_slave = { .name = "pxa2xx_i2c_slave", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_I2C_SLAVE(parent_obj, PXA2xxI2CSlaveState), VMSTATE_END_OF_LIST() } @@ -1447,8 +1442,7 @@ static const VMStateDescription vmstate_pxa2xx_i2c = { .name = "pxa2xx_i2c", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT16(control, PXA2xxI2CState), VMSTATE_UINT16(status, PXA2xxI2CState), VMSTATE_UINT8(ibmr, PXA2xxI2CState), @@ -1705,8 +1699,7 @@ static const VMStateDescription vmstate_pxa2xx_i2s = { .name = "pxa2xx_i2s", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(control, PXA2xxI2SState, 2), VMSTATE_UINT32(status, PXA2xxI2SState), VMSTATE_UINT32(mask, PXA2xxI2SState), diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c index 07274285ab..7f75f05137 100644 --- a/hw/arm/pxa2xx_gpio.c +++ b/hw/arm/pxa2xx_gpio.c @@ -313,8 +313,7 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = { .name = "pxa2xx-gpio", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_INT32(lines, PXA2xxGPIOInfo), VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS), diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index d37fb543e8..9cfc714874 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -296,7 +296,6 @@ static VMStateDescription vmstate_pxa2xx_pic_regs = { .name = "pxa2xx_pic", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = pxa2xx_pic_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(int_enabled, PXA2xxPICState, 2), diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index 392ca84c81..a179c1d694 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -1006,8 +1006,7 @@ static VMStateDescription vmstate_sl_nand_info = { .name = "sl-nand", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT8(ctl, SLNANDState), VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState), VMSTATE_END_OF_LIST(), @@ -1041,9 +1040,8 @@ static VMStateDescription vmstate_spitz_kbd = { .name = "spitz-keyboard", .version_id = 1, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = spitz_keyboard_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT16(sense_state, SpitzKeyboardState), VMSTATE_UINT16(strobe_state, SpitzKeyboardState), VMSTATE_UNUSED_TEST(is_version_0, 5), @@ -1076,8 +1074,7 @@ static const VMStateDescription vmstate_corgi_ssp_regs = { .name = "corgi-ssp", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_SSI_SLAVE(ssidev, CorgiSSPState), VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3), VMSTATE_END_OF_LIST(), @@ -1105,8 +1102,7 @@ static const VMStateDescription vmstate_spitz_lcdtg_regs = { .name = "spitz-lcdtg", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_SSI_SLAVE(ssidev, SpitzLCDTG), VMSTATE_UINT32(bl_intensity, SpitzLCDTG), VMSTATE_UINT32(bl_power, SpitzLCDTG), diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index d6cc77b458..a2095c0e84 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -185,12 +185,19 @@ static uint64_t gptm_read(void *opaque, hwaddr offset, case 0x44: /* TBPMR */ return s->match_prescale[1]; case 0x48: /* TAR */ - if (s->control == 1) + if (s->config == 1) { return s->rtc; + } + qemu_log_mask(LOG_UNIMP, + "GPTM: read of TAR but timer read not supported"); + return 0; case 0x4c: /* TBR */ - hw_error("TODO: Timer value read\n"); + qemu_log_mask(LOG_UNIMP, + "GPTM: read of TBR but timer read not supported"); + return 0; default: - hw_error("gptm_read: Bad offset 0x%x\n", (int)offset); + qemu_log_mask(LOG_GUEST_ERROR, + "GPTM: read at bad offset 0x%x\n", (int)offset); return 0; } } @@ -286,8 +293,7 @@ static const VMStateDescription vmstate_stellaris_gptm = { .name = "stellaris_gptm", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(config, gptm_state), VMSTATE_UINT32_ARRAY(mode, gptm_state, 2), VMSTATE_UINT32(control, gptm_state), @@ -643,9 +649,8 @@ static const VMStateDescription vmstate_stellaris_sys = { .name = "stellaris_sys", .version_id = 2, .minimum_version_id = 1, - .minimum_version_id_old = 1, .post_load = stellaris_sys_post_load, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(pborctl, ssys_state), VMSTATE_UINT32(ldopctl, ssys_state), VMSTATE_UINT32(int_mask, ssys_state), @@ -851,8 +856,7 @@ static const VMStateDescription vmstate_stellaris_i2c = { .name = "stellaris_i2c", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(msa, stellaris_i2c_state), VMSTATE_UINT32(mcs, stellaris_i2c_state), VMSTATE_UINT32(mdr, stellaris_i2c_state), @@ -1121,8 +1125,7 @@ static const VMStateDescription vmstate_stellaris_adc = { .name = "stellaris_adc", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(actss, stellaris_adc_state), VMSTATE_UINT32(ris, stellaris_adc_state), VMSTATE_UINT32(im, stellaris_adc_state), diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 170d0ce267..0da9015333 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -199,7 +199,6 @@ static VMStateDescription vmstate_strongarm_pic_regs = { .name = "strongarm_pic", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = strongarm_pic_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32(pending, StrongARMPICState), @@ -424,7 +423,6 @@ static const VMStateDescription vmstate_strongarm_rtc_regs = { .name = "strongarm-rtc", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .pre_save = strongarm_rtc_pre_save, .post_load = strongarm_rtc_post_load, .fields = (VMStateField[]) { @@ -670,7 +668,6 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = { .name = "strongarm-gpio", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .fields = (VMStateField[]) { VMSTATE_UINT32(ilevel, StrongARMGPIOInfo), VMSTATE_UINT32(olevel, StrongARMGPIOInfo), @@ -842,7 +839,6 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = { .name = "strongarm-ppc", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .fields = (VMStateField[]) { VMSTATE_UINT32(ilevel, StrongARMPPCInfo), VMSTATE_UINT32(olevel, StrongARMPPCInfo), @@ -1293,7 +1289,6 @@ static const VMStateDescription vmstate_strongarm_uart_regs = { .name = "strongarm-uart", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = strongarm_uart_post_load, .fields = (VMStateField[]) { VMSTATE_UINT8(utcr0, StrongARMUARTState), @@ -1553,7 +1548,6 @@ static const VMStateDescription vmstate_strongarm_ssp_regs = { .name = "strongarm-ssp", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = strongarm_ssp_post_load, .fields = (VMStateField[]) { VMSTATE_UINT16_ARRAY(sscr, StrongARMSSPState, 2), diff --git a/hw/arm/z2.c b/hw/arm/z2.c index 67c1be84ac..5df014b15e 100644 --- a/hw/arm/z2.c +++ b/hw/arm/z2.c @@ -164,7 +164,6 @@ static VMStateDescription vmstate_zipit_lcd_state = { .name = "zipit-lcd", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, .fields = (VMStateField[]) { VMSTATE_SSI_SLAVE(ssidev, ZipitLCD), VMSTATE_INT32(selected, ZipitLCD), @@ -275,7 +274,6 @@ static VMStateDescription vmstate_aer915_state = { .name = "aer915", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_INT32(len, AER915State), VMSTATE_BUFFER(buf, AER915State), diff --git a/hw/audio/lm4549.c b/hw/audio/lm4549.c index d75f7ec21f..380ef603bd 100644 --- a/hw/audio/lm4549.c +++ b/hw/audio/lm4549.c @@ -324,9 +324,8 @@ const VMStateDescription vmstate_lm4549_state = { .name = "lm4549_state", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .post_load = &lm4549_post_load, - .fields = (VMStateField[]) { + .post_load = lm4549_post_load, + .fields = (VMStateField[]) { VMSTATE_UINT32(voice_is_active, lm4549_state), VMSTATE_UINT16_ARRAY(regfile, lm4549_state, 128), VMSTATE_UINT16_ARRAY(buffer, lm4549_state, LM4549_BUFFER_SIZE), diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index cdce238f55..86992677e3 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -259,7 +259,6 @@ static const VMStateDescription mv88w8618_audio_vmsd = { .name = "mv88w8618_audio", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(playback_mode, mv88w8618_audio_state), VMSTATE_UINT32(status, mv88w8618_audio_state), diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c index ed82be54e8..19982f2477 100644 --- a/hw/audio/pl041.c +++ b/hw/audio/pl041.c @@ -561,8 +561,7 @@ static const VMStateDescription vmstate_pl041_regfile = { .name = "pl041_regfile", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { #define REGISTER(name, offset) VMSTATE_UINT32(name, pl041_regfile), #include "pl041.hx" #undef REGISTER @@ -574,8 +573,7 @@ static const VMStateDescription vmstate_pl041_fifo = { .name = "pl041_fifo", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(level, pl041_fifo), VMSTATE_UINT32_ARRAY(data, pl041_fifo, MAX_FIFO_DEPTH), VMSTATE_END_OF_LIST() @@ -586,8 +584,7 @@ static const VMStateDescription vmstate_pl041_channel = { .name = "pl041_channel", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_STRUCT(tx_fifo, pl041_channel, 0, vmstate_pl041_fifo, pl041_fifo), VMSTATE_UINT8(tx_enabled, pl041_channel), diff --git a/hw/audio/wm8750.c b/hw/audio/wm8750.c index c18f2457a1..b50b331402 100644 --- a/hw/audio/wm8750.c +++ b/hw/audio/wm8750.c @@ -583,10 +583,9 @@ static const VMStateDescription vmstate_wm8750 = { .name = CODEC, .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .pre_save = wm8750_pre_save, .post_load = wm8750_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT8_ARRAY(i2c_data, WM8750State, 2), VMSTATE_INT32(i2c_len, WM8750State), VMSTATE_INT32(enable, WM8750State), diff --git a/hw/block/ecc.c b/hw/block/ecc.c index 8c888cc12a..10bb233089 100644 --- a/hw/block/ecc.c +++ b/hw/block/ecc.c @@ -81,8 +81,7 @@ VMStateDescription vmstate_ecc_state = { .name = "ecc-state", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT8(cp, ECCState), VMSTATE_UINT16_ARRAY(lp, ECCState, 2), VMSTATE_UINT16(count, ECCState), diff --git a/hw/block/nand.c b/hw/block/nand.c index 6d7c804f01..38eefd436d 100644 --- a/hw/block/nand.c +++ b/hw/block/nand.c @@ -346,10 +346,9 @@ static const VMStateDescription vmstate_nand = { .name = "nand", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .pre_save = nand_pre_save, .post_load = nand_post_load, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT8(cle, NANDFlashState), VMSTATE_UINT8(ale, NANDFlashState), VMSTATE_UINT8(ce, NANDFlashState), diff --git a/hw/block/onenand.c b/hw/block/onenand.c index aae9ee7536..60d5311d04 100644 --- a/hw/block/onenand.c +++ b/hw/block/onenand.c @@ -169,7 +169,6 @@ static const VMStateDescription vmstate_onenand = { .name = "onenand", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .pre_save = onenand_pre_save, .post_load = onenand_post_load, .fields = (VMStateField[]) { diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 1012f1ad64..bf0c853499 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -504,7 +504,6 @@ static const VMStateDescription vmstate_cadence_uart = { .name = "cadence_uart", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, .post_load = cadence_uart_post_load, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(r, UartState, R_MAX), diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c index fd8e07713d..8abe944de6 100644 --- a/hw/char/digic-uart.c +++ b/hw/char/digic-uart.c @@ -162,7 +162,6 @@ static const VMStateDescription vmstate_digic_uart = { .name = "digic-uart", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(reg_rx, DigicUartState), VMSTATE_UINT32(reg_st, DigicUartState), diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 19b59ccddb..7614e5860f 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -560,7 +560,6 @@ static const VMStateDescription vmstate_exynos4210_uart_fifo = { .name = "exynos4210.uart.fifo", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(sp, Exynos4210UartFIFO), VMSTATE_UINT32(rp, Exynos4210UartFIFO), @@ -573,7 +572,6 @@ static const VMStateDescription vmstate_exynos4210_uart = { .name = "exynos4210.uart", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT(rx, Exynos4210UartState, 1, vmstate_exynos4210_uart_fifo, Exynos4210UartFIFO), diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 7f16835aeb..f3fbc776be 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -76,7 +76,6 @@ static const VMStateDescription vmstate_imx_serial = { .name = "imx-serial", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_INT32(readbuff, IMXSerialState), VMSTATE_UINT32(usr1, IMXSerialState), diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 644aad7cf0..0a451150e5 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -251,8 +251,7 @@ static const VMStateDescription vmstate_pl011 = { .name = "pl011", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(readbuff, PL011State), VMSTATE_UINT32(flags, PL011State), VMSTATE_UINT32(lcr, PL011State), diff --git a/hw/display/ads7846.c b/hw/display/ads7846.c index 85252a2329..3f35369bb4 100644 --- a/hw/display/ads7846.c +++ b/hw/display/ads7846.c @@ -121,9 +121,8 @@ static const VMStateDescription vmstate_ads7846 = { .name = "ads7846", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .post_load = ads7856_post_load, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_SSI_SLAVE(ssidev, ADS7846State), VMSTATE_INT32_ARRAY(input, ADS7846State, 8), VMSTATE_INT32(noise, ADS7846State), diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 9750330c25..45c62afac1 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1845,7 +1845,7 @@ static const VMStateDescription exynos4210_fimd_window_vmstate = { .name = "exynos4210.fimd_window", .version_id = 1, .minimum_version_id = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(wincon, Exynos4210fimdWindow), VMSTATE_UINT32_ARRAY(buf_start, Exynos4210fimdWindow, 3), VMSTATE_UINT32_ARRAY(buf_end, Exynos4210fimdWindow, 3), @@ -1875,7 +1875,7 @@ static const VMStateDescription exynos4210_fimd_vmstate = { .version_id = 1, .minimum_version_id = 1, .post_load = exynos4210_fimd_load, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(vidcon, Exynos4210fimdState, 4), VMSTATE_UINT32_ARRAY(vidtcon, Exynos4210fimdState, 4), VMSTATE_UINT32(shadowcon, Exynos4210fimdState), diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index 09cdf17ab9..80edb70676 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -932,8 +932,7 @@ static const VMStateDescription vmstate_dma_channel = { .name = "dma_channel", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(branch, struct DMAChannel), VMSTATE_UINT8(up, struct DMAChannel), VMSTATE_BUFFER(pbuffer, struct DMAChannel), @@ -959,9 +958,8 @@ static const VMStateDescription vmstate_pxa2xx_lcdc = { .name = "pxa2xx_lcdc", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = pxa2xx_lcdc_post_load, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_INT32(irqlevel, PXA2xxLCDState), VMSTATE_INT32(transp, PXA2xxLCDState), VMSTATE_UINT32_ARRAY(control, PXA2xxLCDState, 6), diff --git a/hw/display/ssd0303.c b/hw/display/ssd0303.c index c2eea04934..f6804fb51b 100644 --- a/hw/display/ssd0303.c +++ b/hw/display/ssd0303.c @@ -272,8 +272,7 @@ static const VMStateDescription vmstate_ssd0303 = { .name = "ssd0303_oled", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_INT32(row, ssd0303_state), VMSTATE_INT32(col, ssd0303_state), VMSTATE_INT32(start_line, ssd0303_state), diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index 0e8cccd27f..0f35c42c05 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -973,7 +973,7 @@ static int omap_dma_ch_reg_write(struct omap_dma_s *s, case 0x22: /* DMA_COLOR_U */ ch->color &= 0xffff; - ch->color |= value << 16; + ch->color |= (uint32_t)value << 16; break; case 0x24: /* DMA_CCR2 */ @@ -1043,7 +1043,7 @@ static int omap_dma_3_2_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, case 0xbca: /* TOP_B1_U */ s->src_f1_top &= 0x0000ffff; - s->src_f1_top |= value << 16; + s->src_f1_top |= (uint32_t)value << 16; break; case 0xbcc: /* BOT_B1_L */ @@ -1265,7 +1265,7 @@ static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, case 0x304: /* SYS_DMA_LCD_TOP_F1_U */ s->src_f1_top &= 0x0000ffff; - s->src_f1_top |= value << 16; + s->src_f1_top |= (uint32_t)value << 16; break; case 0x306: /* SYS_DMA_LCD_BOT_F1_L */ @@ -1275,7 +1275,7 @@ static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, case 0x308: /* SYS_DMA_LCD_BOT_F1_U */ s->src_f1_bottom &= 0x0000ffff; - s->src_f1_bottom |= value << 16; + s->src_f1_bottom |= (uint32_t)value << 16; break; case 0x30a: /* SYS_DMA_LCD_TOP_F2_L */ @@ -1285,7 +1285,7 @@ static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, case 0x30c: /* SYS_DMA_LCD_TOP_F2_U */ s->src_f2_top &= 0x0000ffff; - s->src_f2_top |= value << 16; + s->src_f2_top |= (uint32_t)value << 16; break; case 0x30e: /* SYS_DMA_LCD_BOT_F2_L */ @@ -1295,7 +1295,7 @@ static int omap_dma_3_1_lcd_write(struct omap_dma_lcd_channel_s *s, int offset, case 0x310: /* SYS_DMA_LCD_BOT_F2_U */ s->src_f2_bottom &= 0x0000ffff; - s->src_f2_bottom |= value << 16; + s->src_f2_bottom |= (uint32_t)value << 16; break; default: diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index 608a58c47d..6b6eaaeb47 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -138,7 +138,6 @@ static const VMStateDescription vmstate_pl330_chan = { .name = "pl330_chan", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(src, PL330Chan), VMSTATE_UINT32(dst, PL330Chan), @@ -170,7 +169,6 @@ static const VMStateDescription vmstate_pl330_fifo = { .name = "pl330_chan", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_VBUFFER_UINT32(buf, PL330Fifo, 1, NULL, 0, buf_size), VMSTATE_VBUFFER_UINT32(tag, PL330Fifo, 1, NULL, 0, buf_size), @@ -195,7 +193,6 @@ static const VMStateDescription vmstate_pl330_queue_entry = { .name = "pl330_queue_entry", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(addr, PL330QueueEntry), VMSTATE_UINT32(len, PL330QueueEntry), @@ -218,7 +215,6 @@ static const VMStateDescription vmstate_pl330_queue = { .name = "pl330_queue", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT_VARRAY_UINT32(queue, PL330Queue, queue_size, 1, vmstate_pl330_queue_entry, PL330QueueEntry), @@ -279,7 +275,6 @@ static const VMStateDescription vmstate_pl330 = { .name = "pl330", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT(manager, PL330State, 0, vmstate_pl330_chan, PL330Chan), VMSTATE_STRUCT_VARRAY_UINT32(chan, PL330State, num_chnls, 0, diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c index c013abb313..d4501fb4cb 100644 --- a/hw/dma/pxa2xx_dma.c +++ b/hw/dma/pxa2xx_dma.c @@ -514,7 +514,6 @@ static VMStateDescription vmstate_pxa2xx_dma_chan = { .name = "pxa2xx_dma_chan", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(descr, PXA2xxDMAChannel), VMSTATE_UINT32(src, PXA2xxDMAChannel), @@ -530,7 +529,6 @@ static VMStateDescription vmstate_pxa2xx_dma = { .name = "pxa2xx_dma", .version_id = 1, .minimum_version_id = 0, - .minimum_version_id_old = 0, .fields = (VMStateField[]) { VMSTATE_UNUSED_TEST(is_version_0, 4), VMSTATE_UINT32(stopintr, PXA2xxDMAState), diff --git a/hw/gpio/max7310.c b/hw/gpio/max7310.c index cfcd89ca2b..7fbf313ce8 100644 --- a/hw/gpio/max7310.c +++ b/hw/gpio/max7310.c @@ -152,8 +152,7 @@ static const VMStateDescription vmstate_max7310 = { .name = "max7310", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_INT32(i2c_command_byte, MAX7310State), VMSTATE_INT32(len, MAX7310State), VMSTATE_UINT8(level, MAX7310State), diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c index 8e2ce049de..94083424f8 100644 --- a/hw/gpio/zaurus.c +++ b/hw/gpio/zaurus.c @@ -216,9 +216,8 @@ static const VMStateDescription vmstate_scoop_regs = { .name = "scoop", .version_id = 1, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = scoop_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT16(status, ScoopInfo), VMSTATE_UINT16(power, ScoopInfo), VMSTATE_UINT32(gpio_level, ScoopInfo), diff --git a/hw/input/lm832x.c b/hw/input/lm832x.c index 4ae1cd9c80..9eb68e87cb 100644 --- a/hw/input/lm832x.c +++ b/hw/input/lm832x.c @@ -432,9 +432,8 @@ static const VMStateDescription vmstate_lm_kbd = { .name = "LM8323", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = lm_kbd_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_I2C_SLAVE(parent_obj, LM823KbdState), VMSTATE_UINT8(i2c_dir, LM823KbdState), VMSTATE_UINT8(i2c_cycle, LM823KbdState), diff --git a/hw/input/pxa2xx_keypad.c b/hw/input/pxa2xx_keypad.c index b90b0ba102..85011145e6 100644 --- a/hw/input/pxa2xx_keypad.c +++ b/hw/input/pxa2xx_keypad.c @@ -291,8 +291,7 @@ static const VMStateDescription vmstate_pxa2xx_keypad = { .name = "pxa2xx_keypad", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(kpc, PXA2xxKeyPadState), VMSTATE_UINT32(kpdk, PXA2xxKeyPadState), VMSTATE_UINT32(kprec, PXA2xxKeyPadState), diff --git a/hw/input/stellaris_input.c b/hw/input/stellaris_input.c index 4e407922a0..0609e80868 100644 --- a/hw/input/stellaris_input.c +++ b/hw/input/stellaris_input.c @@ -51,8 +51,7 @@ static const VMStateDescription vmstate_stellaris_button = { .name = "stellaris_button", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT8(pressed, gamepad_button), VMSTATE_END_OF_LIST() } @@ -62,8 +61,7 @@ static const VMStateDescription vmstate_stellaris_gamepad = { .name = "stellaris_gamepad", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_INT32(extension, gamepad_state), VMSTATE_STRUCT_VARRAY_INT32(buttons, gamepad_state, num_buttons, 0, vmstate_stellaris_button, gamepad_button), diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c index 0924d9855c..de820b9723 100644 --- a/hw/intc/allwinner-a10-pic.c +++ b/hw/intc/allwinner-a10-pic.c @@ -97,6 +97,7 @@ static void aw_a10_pic_write(void *opaque, hwaddr offset, uint64_t value, switch (offset) { case AW_A10_PIC_BASE_ADDR: s->base_addr = value & ~0x3; + break; case AW_A10_PIC_PROTECT: s->protect = value; break; @@ -141,7 +142,6 @@ static const VMStateDescription vmstate_aw_a10_pic = { .name = "a10.pic", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(vector, AwA10PICState), VMSTATE_UINT32(base_addr, AwA10PICState), diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 9aa8ab208f..75d9c6e41e 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -443,8 +443,7 @@ static const VMStateDescription vmstate_nvic = { .name = "armv7m_nvic", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(systick.control, nvic_state), VMSTATE_UINT32(systick.reload, nvic_state), VMSTATE_INT64(systick.tick, nvic_state), diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c index 3287479456..a6b7028906 100644 --- a/hw/intc/exynos4210_combiner.c +++ b/hw/intc/exynos4210_combiner.c @@ -77,7 +77,6 @@ static const VMStateDescription vmstate_exynos4210_combiner_group_state = { .name = "exynos4210.combiner.groupstate", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT8(src_mask, CombinerGroupState), VMSTATE_UINT8(src_pending, CombinerGroupState), @@ -89,7 +88,6 @@ static const VMStateDescription vmstate_exynos4210_combiner = { .name = "exynos4210.combiner", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT_ARRAY(group, Exynos4210CombinerState, IIC_NGRP, 0, vmstate_exynos4210_combiner_group_state, CombinerGroupState), diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c index 5b913f786e..0590d5dfb8 100644 --- a/hw/intc/exynos4210_gic.c +++ b/hw/intc/exynos4210_gic.c @@ -394,7 +394,6 @@ static const VMStateDescription vmstate_exynos4210_irq_gate = { .name = "exynos4210.irq_gate", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, .fields = (VMStateField[]) { VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, 0, n_in), VMSTATE_END_OF_LIST() diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c index fb00e910f6..ec5f9ad815 100644 --- a/hw/intc/imx_avic.c +++ b/hw/intc/imx_avic.c @@ -77,7 +77,6 @@ static const VMStateDescription vmstate_imx_avic = { .name = "imx-avic", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT64(pending, IMXAVICState), VMSTATE_UINT64(enabled, IMXAVICState), diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c index 5ec14d1c86..2b118c7255 100644 --- a/hw/misc/exynos4210_pmu.c +++ b/hw/misc/exynos4210_pmu.c @@ -471,7 +471,7 @@ static const VMStateDescription exynos4210_pmu_vmstate = { .name = "exynos4210.pmu", .version_id = 1, .minimum_version_id = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(reg, Exynos4210PmuState, PMU_NUM_OF_REGISTERS), VMSTATE_END_OF_LIST() } diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c index 63e33a41da..750b9061db 100644 --- a/hw/misc/imx_ccm.c +++ b/hw/misc/imx_ccm.c @@ -57,7 +57,6 @@ static const VMStateDescription vmstate_imx_ccm = { .name = "imx-ccm", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(ccmr, IMXCCMState), VMSTATE_UINT32(pdr0, IMXCCMState), diff --git a/hw/misc/max111x.c b/hw/misc/max111x.c index bba87c2ec5..bef3651d6e 100644 --- a/hw/misc/max111x.c +++ b/hw/misc/max111x.c @@ -110,8 +110,7 @@ static const VMStateDescription vmstate_max111x = { .name = "max111x", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_SSI_SLAVE(parent_obj, MAX111xState), VMSTATE_UINT8(tb1, MAX111xState), VMSTATE_UINT8(rb2, MAX111xState), diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c index c96810fec1..d5090799f8 100644 --- a/hw/misc/mst_fpga.c +++ b/hw/misc/mst_fpga.c @@ -219,12 +219,11 @@ static int mst_fpga_init(SysBusDevice *sbd) } static VMStateDescription vmstate_mst_fpga_regs = { - .name = "mainstone_fpga", - .version_id = 0, - .minimum_version_id = 0, - .minimum_version_id_old = 0, - .post_load = mst_fpga_post_load, - .fields = (VMStateField []) { + .name = "mainstone_fpga", + .version_id = 0, + .minimum_version_id = 0, + .post_load = mst_fpga_post_load, + .fields = (VMStateField[]) { VMSTATE_UINT32(prev_level, mst_irq_state), VMSTATE_UINT32(leddat1, mst_irq_state), VMSTATE_UINT32(leddat2, mst_irq_state), diff --git a/hw/misc/omap_gpmc.c b/hw/misc/omap_gpmc.c index 2047274123..cddea241d4 100644 --- a/hw/misc/omap_gpmc.c +++ b/hw/misc/omap_gpmc.c @@ -242,6 +242,10 @@ static void fill_prefetch_fifo(struct omap_gpmc_s *s) if (bytes > s->prefetch.count) { bytes = s->prefetch.count; } + if (is16bit) { + bytes &= ~1; + } + s->prefetch.count -= bytes; s->prefetch.fifopointer += bytes; fptr = 64 - s->prefetch.fifopointer; diff --git a/hw/misc/tmp105.c b/hw/misc/tmp105.c index 636ee97b16..f3fe8b81fd 100644 --- a/hw/misc/tmp105.c +++ b/hw/misc/tmp105.c @@ -199,9 +199,8 @@ static const VMStateDescription vmstate_tmp105 = { .name = "TMP105", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .post_load = tmp105_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT8(len, TMP105State), VMSTATE_UINT8_ARRAY(buf, TMP105State, 2), VMSTATE_UINT8(pointer, TMP105State), diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index 2e53a2e21f..964f2532ff 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -428,8 +428,7 @@ static const VMStateDescription vmstate_zynq_slcr = { .name = "zynq_slcr", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, ZynqSLCRState, ZYNQ_SLCR_NUM_REGS), VMSTATE_END_OF_LIST() } diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index cdb18253b6..47e70381fe 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -717,7 +717,6 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) rxbuf_ptr = (void *)buf; } else { unsigned crc_val; - int crc_offset; /* The application wants the FCS field, which QEMU does not provide. * We must try and caclculate one. @@ -727,12 +726,7 @@ static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size) memset(rxbuf + size, 0, sizeof(rxbuf) - size); rxbuf_ptr = rxbuf; crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60))); - if (size < 60) { - crc_offset = 60; - } else { - crc_offset = size; - } - memcpy(rxbuf + crc_offset, &crc_val, sizeof(crc_val)); + memcpy(rxbuf + size, &crc_val, sizeof(crc_val)); bytes_to_copy += 4; size += 4; @@ -1257,8 +1251,7 @@ static const VMStateDescription vmstate_cadence_gem = { .name = "cadence_gem", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(regs, GemState, GEM_MAXREG), VMSTATE_UINT16_ARRAY(phy_regs, GemState, 32), VMSTATE_UINT8(phy_loop, GemState), diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c index a8e29b3b42..d1dca8f4e2 100644 --- a/hw/net/smc91c111.c +++ b/hw/net/smc91c111.c @@ -54,7 +54,7 @@ static const VMStateDescription vmstate_smc91c111 = { .name = "smc91c111", .version_id = 1, .minimum_version_id = 1, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT16(tcr, smc91c111_state), VMSTATE_UINT16(rcr, smc91c111_state), VMSTATE_UINT16(cr, smc91c111_state), diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index d04e6a46f8..c9ee5d3f10 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -46,6 +46,11 @@ do { fprintf(stderr, "stellaris_enet: error: " fmt , ## __VA_ARGS__);} while (0) #define STELLARIS_ENET(obj) \ OBJECT_CHECK(stellaris_enet_state, (obj), TYPE_STELLARIS_ENET) +typedef struct { + uint8_t data[2048]; + uint32_t len; +} StellarisEnetRxFrame; + typedef struct { SysBusDevice parent_obj; @@ -59,29 +64,159 @@ typedef struct { uint32_t mtxd; uint32_t mrxd; uint32_t np; - int tx_frame_len; - int tx_fifo_len; + uint32_t tx_fifo_len; uint8_t tx_fifo[2048]; /* Real hardware has a 2k fifo, which works out to be at most 31 packets. We implement a full 31 packet fifo. */ - struct { - uint8_t data[2048]; - int len; - } rx[31]; - uint8_t *rx_fifo; - int rx_fifo_len; - int next_packet; + StellarisEnetRxFrame rx[31]; + uint32_t rx_fifo_offset; + uint32_t next_packet; NICState *nic; NICConf conf; qemu_irq irq; MemoryRegion mmio; } stellaris_enet_state; +static const VMStateDescription vmstate_rx_frame = { + .name = "stellaris_enet/rx_frame", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8_ARRAY(data, StellarisEnetRxFrame, 2048), + VMSTATE_UINT32(len, StellarisEnetRxFrame), + VMSTATE_END_OF_LIST() + } +}; + +static int stellaris_enet_post_load(void *opaque, int version_id) +{ + stellaris_enet_state *s = opaque; + int i; + + /* Sanitize inbound state. Note that next_packet is an index but + * np is a size; hence their valid upper bounds differ. + */ + if (s->next_packet >= ARRAY_SIZE(s->rx)) { + return -1; + } + + if (s->np > ARRAY_SIZE(s->rx)) { + return -1; + } + + for (i = 0; i < ARRAY_SIZE(s->rx); i++) { + if (s->rx[i].len > ARRAY_SIZE(s->rx[i].data)) { + return -1; + } + } + + if (s->rx_fifo_offset > ARRAY_SIZE(s->rx[0].data) - 4) { + return -1; + } + + if (s->tx_fifo_len > ARRAY_SIZE(s->tx_fifo)) { + return -1; + } + + return 0; +} + +static const VMStateDescription vmstate_stellaris_enet = { + .name = "stellaris_enet", + .version_id = 2, + .minimum_version_id = 2, + .post_load = stellaris_enet_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(ris, stellaris_enet_state), + VMSTATE_UINT32(im, stellaris_enet_state), + VMSTATE_UINT32(rctl, stellaris_enet_state), + VMSTATE_UINT32(tctl, stellaris_enet_state), + VMSTATE_UINT32(thr, stellaris_enet_state), + VMSTATE_UINT32(mctl, stellaris_enet_state), + VMSTATE_UINT32(mdv, stellaris_enet_state), + VMSTATE_UINT32(mtxd, stellaris_enet_state), + VMSTATE_UINT32(mrxd, stellaris_enet_state), + VMSTATE_UINT32(np, stellaris_enet_state), + VMSTATE_UINT32(tx_fifo_len, stellaris_enet_state), + VMSTATE_UINT8_ARRAY(tx_fifo, stellaris_enet_state, 2048), + VMSTATE_STRUCT_ARRAY(rx, stellaris_enet_state, 31, 1, + vmstate_rx_frame, StellarisEnetRxFrame), + VMSTATE_UINT32(rx_fifo_offset, stellaris_enet_state), + VMSTATE_UINT32(next_packet, stellaris_enet_state), + VMSTATE_END_OF_LIST() + } +}; + static void stellaris_enet_update(stellaris_enet_state *s) { qemu_set_irq(s->irq, (s->ris & s->im) != 0); } +/* Return the data length of the packet currently being assembled + * in the TX fifo. + */ +static inline int stellaris_txpacket_datalen(stellaris_enet_state *s) +{ + return s->tx_fifo[0] | (s->tx_fifo[1] << 8); +} + +/* Return true if the packet currently in the TX FIFO is complete, +* ie the FIFO holds enough bytes for the data length, ethernet header, +* payload and optionally CRC. +*/ +static inline bool stellaris_txpacket_complete(stellaris_enet_state *s) +{ + int framelen = stellaris_txpacket_datalen(s); + framelen += 16; + if (!(s->tctl & SE_TCTL_CRC)) { + framelen += 4; + } + /* Cover the corner case of a 2032 byte payload with auto-CRC disabled: + * this requires more bytes than will fit in the FIFO. It's not totally + * clear how the h/w handles this, but if using threshold-based TX + * it will definitely try to transmit something. + */ + framelen = MIN(framelen, ARRAY_SIZE(s->tx_fifo)); + return s->tx_fifo_len >= framelen; +} + +/* Return true if the TX FIFO threshold is enabled and the FIFO + * has filled enough to reach it. + */ +static inline bool stellaris_tx_thr_reached(stellaris_enet_state *s) +{ + return (s->thr < 0x3f && + (s->tx_fifo_len >= 4 * (s->thr * 8 + 1))); +} + +/* Send the packet currently in the TX FIFO */ +static void stellaris_enet_send(stellaris_enet_state *s) +{ + int framelen = stellaris_txpacket_datalen(s); + + /* Ethernet header is in the FIFO but not in the datacount. + * We don't implement explicit CRC, so just ignore any + * CRC value in the FIFO. + */ + framelen += 14; + if ((s->tctl & SE_TCTL_PADEN) && framelen < 60) { + memset(&s->tx_fifo[framelen + 2], 0, 60 - framelen); + framelen = 60; + } + /* This MIN will have no effect unless the FIFO data is corrupt + * (eg bad data from an incoming migration); otherwise the check + * on the datalen at the start of writing the data into the FIFO + * will have caught this. Silently write a corrupt half-packet, + * which is what the hardware does in FIFO underrun situations. + */ + framelen = MIN(framelen, ARRAY_SIZE(s->tx_fifo) - 2); + qemu_send_packet(qemu_get_queue(s->nic), s->tx_fifo + 2, framelen); + s->tx_fifo_len = 0; + s->ris |= SE_INT_TXEMP; + stellaris_enet_update(s); + DPRINTF("Done TX\n"); +} + /* TODO: Implement MAC address filtering. */ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, size_t size) { @@ -97,7 +232,7 @@ static ssize_t stellaris_enet_receive(NetClientState *nc, const uint8_t *buf, si return -1; } - DPRINTF("Received packet len=%d\n", size); + DPRINTF("Received packet len=%zu\n", size); n = s->next_packet + s->np; if (n >= 31) n -= 31; @@ -152,21 +287,21 @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, case 0x0c: /* TCTL */ return s->tctl; case 0x10: /* DATA */ - if (s->rx_fifo_len == 0) { - if (s->np == 0) { - BADF("RX underflow\n"); - return 0; - } - s->rx_fifo_len = s->rx[s->next_packet].len; - s->rx_fifo = s->rx[s->next_packet].data; - DPRINTF("RX FIFO start packet len=%d\n", s->rx_fifo_len); + { + uint8_t *rx_fifo; + + if (s->np == 0) { + BADF("RX underflow\n"); + return 0; } - val = s->rx_fifo[0] | (s->rx_fifo[1] << 8) | (s->rx_fifo[2] << 16) - | (s->rx_fifo[3] << 24); - s->rx_fifo += 4; - s->rx_fifo_len -= 4; - if (s->rx_fifo_len <= 0) { - s->rx_fifo_len = 0; + + rx_fifo = s->rx[s->next_packet].data + s->rx_fifo_offset; + + val = rx_fifo[0] | (rx_fifo[1] << 8) | (rx_fifo[2] << 16) + | (rx_fifo[3] << 24); + s->rx_fifo_offset += 4; + if (s->rx_fifo_offset >= s->rx[s->next_packet].len) { + s->rx_fifo_offset = 0; s->next_packet++; if (s->next_packet >= 31) s->next_packet = 0; @@ -174,6 +309,7 @@ static uint64_t stellaris_enet_read(void *opaque, hwaddr offset, DPRINTF("RX done np=%d\n", s->np); } return val; + } case 0x14: /* IA0 */ return s->conf.macaddr.a[0] | (s->conf.macaddr.a[1] << 8) | (s->conf.macaddr.a[2] << 16) @@ -212,22 +348,23 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, switch (offset) { case 0x00: /* IACK */ s->ris &= ~value; - DPRINTF("IRQ ack %02x/%02x\n", value, s->ris); + DPRINTF("IRQ ack %02" PRIx64 "/%02x\n", value, s->ris); stellaris_enet_update(s); /* Clearing TXER also resets the TX fifo. */ - if (value & SE_INT_TXER) - s->tx_frame_len = -1; + if (value & SE_INT_TXER) { + s->tx_fifo_len = 0; + } break; case 0x04: /* IM */ - DPRINTF("IRQ mask %02x/%02x\n", value, s->ris); + DPRINTF("IRQ mask %02" PRIx64 "/%02x\n", value, s->ris); s->im = value; stellaris_enet_update(s); break; case 0x08: /* RCTL */ s->rctl = value; if (value & SE_RCTL_RSTFIFO) { - s->rx_fifo_len = 0; s->np = 0; + s->rx_fifo_offset = 0; stellaris_enet_update(s); } break; @@ -235,43 +372,26 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, s->tctl = value; break; case 0x10: /* DATA */ - if (s->tx_frame_len == -1) { - s->tx_frame_len = value & 0xffff; - if (s->tx_frame_len > 2032) { - DPRINTF("TX frame too long (%d)\n", s->tx_frame_len); - s->tx_frame_len = 0; + if (s->tx_fifo_len == 0) { + /* The first word is special, it contains the data length */ + int framelen = value & 0xffff; + if (framelen > 2032) { + DPRINTF("TX frame too long (%d)\n", framelen); s->ris |= SE_INT_TXER; stellaris_enet_update(s); - } else { - DPRINTF("Start TX frame len=%d\n", s->tx_frame_len); - /* The value written does not include the ethernet header. */ - s->tx_frame_len += 14; - if ((s->tctl & SE_TCTL_CRC) == 0) - s->tx_frame_len += 4; - s->tx_fifo_len = 0; - s->tx_fifo[s->tx_fifo_len++] = value >> 16; - s->tx_fifo[s->tx_fifo_len++] = value >> 24; + break; } - } else { + } + + if (s->tx_fifo_len + 4 <= ARRAY_SIZE(s->tx_fifo)) { s->tx_fifo[s->tx_fifo_len++] = value; s->tx_fifo[s->tx_fifo_len++] = value >> 8; s->tx_fifo[s->tx_fifo_len++] = value >> 16; s->tx_fifo[s->tx_fifo_len++] = value >> 24; - if (s->tx_fifo_len >= s->tx_frame_len) { - /* We don't implement explicit CRC, so just chop it off. */ - if ((s->tctl & SE_TCTL_CRC) == 0) - s->tx_frame_len -= 4; - if ((s->tctl & SE_TCTL_PADEN) && s->tx_frame_len < 60) { - memset(&s->tx_fifo[s->tx_frame_len], 0, 60 - s->tx_frame_len); - s->tx_fifo_len = 60; - } - qemu_send_packet(qemu_get_queue(s->nic), s->tx_fifo, - s->tx_frame_len); - s->tx_frame_len = -1; - s->ris |= SE_INT_TXEMP; - stellaris_enet_update(s); - DPRINTF("Done TX\n"); - } + } + + if (stellaris_tx_thr_reached(s) && stellaris_txpacket_complete(s)) { + stellaris_enet_send(s); } break; case 0x14: /* IA0 */ @@ -299,9 +419,13 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, case 0x2c: /* MTXD */ s->mtxd = value & 0xff; break; + case 0x38: /* TR */ + if (value & 1) { + stellaris_enet_send(s); + } + break; case 0x30: /* MRXD */ case 0x34: /* NP */ - case 0x38: /* TR */ /* Ignored. */ case 0x3c: /* Undocuented: Timestamp? */ /* Ignored. */ @@ -324,68 +448,7 @@ static void stellaris_enet_reset(stellaris_enet_state *s) s->im = SE_INT_PHY | SE_INT_MD | SE_INT_RXER | SE_INT_FOV | SE_INT_TXEMP | SE_INT_TXER | SE_INT_RX; s->thr = 0x3f; - s->tx_frame_len = -1; -} - -static void stellaris_enet_save(QEMUFile *f, void *opaque) -{ - stellaris_enet_state *s = (stellaris_enet_state *)opaque; - int i; - - qemu_put_be32(f, s->ris); - qemu_put_be32(f, s->im); - qemu_put_be32(f, s->rctl); - qemu_put_be32(f, s->tctl); - qemu_put_be32(f, s->thr); - qemu_put_be32(f, s->mctl); - qemu_put_be32(f, s->mdv); - qemu_put_be32(f, s->mtxd); - qemu_put_be32(f, s->mrxd); - qemu_put_be32(f, s->np); - qemu_put_be32(f, s->tx_frame_len); - qemu_put_be32(f, s->tx_fifo_len); - qemu_put_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); - for (i = 0; i < 31; i++) { - qemu_put_be32(f, s->rx[i].len); - qemu_put_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); - - } - qemu_put_be32(f, s->next_packet); - qemu_put_be32(f, s->rx_fifo - s->rx[s->next_packet].data); - qemu_put_be32(f, s->rx_fifo_len); -} - -static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) -{ - stellaris_enet_state *s = (stellaris_enet_state *)opaque; - int i; - - if (version_id != 1) - return -EINVAL; - - s->ris = qemu_get_be32(f); - s->im = qemu_get_be32(f); - s->rctl = qemu_get_be32(f); - s->tctl = qemu_get_be32(f); - s->thr = qemu_get_be32(f); - s->mctl = qemu_get_be32(f); - s->mdv = qemu_get_be32(f); - s->mtxd = qemu_get_be32(f); - s->mrxd = qemu_get_be32(f); - s->np = qemu_get_be32(f); - s->tx_frame_len = qemu_get_be32(f); - s->tx_fifo_len = qemu_get_be32(f); - qemu_get_buffer(f, s->tx_fifo, sizeof(s->tx_fifo)); - for (i = 0; i < 31; i++) { - s->rx[i].len = qemu_get_be32(f); - qemu_get_buffer(f, s->rx[i].data, sizeof(s->rx[i].data)); - - } - s->next_packet = qemu_get_be32(f); - s->rx_fifo = s->rx[s->next_packet].data + qemu_get_be32(f); - s->rx_fifo_len = qemu_get_be32(f); - - return 0; + s->tx_fifo_len = 0; } static void stellaris_enet_cleanup(NetClientState *nc) @@ -419,8 +482,6 @@ static int stellaris_enet_init(SysBusDevice *sbd) qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); stellaris_enet_reset(s); - register_savevm(dev, "stellaris_enet", -1, 1, - stellaris_enet_save, stellaris_enet_load, s); return 0; } @@ -428,8 +489,6 @@ static void stellaris_enet_unrealize(DeviceState *dev, Error **errp) { stellaris_enet_state *s = STELLARIS_ENET(dev); - unregister_savevm(DEVICE(s), "stellaris_enet", s); - memory_region_destroy(&s->mmio); } @@ -446,6 +505,7 @@ static void stellaris_enet_class_init(ObjectClass *klass, void *data) k->init = stellaris_enet_init; dc->unrealize = stellaris_enet_unrealize; dc->props = stellaris_enet_properties; + dc->vmsd = &vmstate_stellaris_enet; } static const TypeInfo stellaris_enet_info = { diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 88349ac6a2..aeffcb58b7 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -156,7 +156,7 @@ static const VMStateDescription vmstate_rxtx_stats = { .name = "xgmac_stats", .version_id = 1, .minimum_version_id = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT64(rx_bytes, RxTxStats), VMSTATE_UINT64(tx_bytes, RxTxStats), VMSTATE_UINT64(rx, RxTxStats), diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c index b19bc7174a..61d568f36e 100644 --- a/hw/ssi/pl022.c +++ b/hw/ssi/pl022.c @@ -257,9 +257,8 @@ static const VMStateDescription vmstate_pl022 = { .name = "pl022_ssp", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .post_load = pl022_post_load, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(cr0, PL022State), VMSTATE_UINT32(cr1, PL022State), VMSTATE_UINT32(bitmask, PL022State), diff --git a/hw/ssi/ssi.c b/hw/ssi/ssi.c index 017f0221fb..1c82a93590 100644 --- a/hw/ssi/ssi.c +++ b/hw/ssi/ssi.c @@ -126,8 +126,7 @@ const VMStateDescription vmstate_ssi_slave = { .name = "SSISlave", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_BOOL(cs, SSISlave), VMSTATE_END_OF_LIST() } diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c index d44caae8ad..207f47a1c0 100644 --- a/hw/ssi/xilinx_spi.c +++ b/hw/ssi/xilinx_spi.c @@ -351,7 +351,6 @@ static const VMStateDescription vmstate_xilinx_spi = { .name = "xilinx_spi", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_FIFO8(tx_fifo, XilinxSPI), VMSTATE_FIFO8(rx_fifo, XilinxSPI), diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index 8977243725..0910f5479a 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -704,7 +704,6 @@ static const VMStateDescription vmstate_xilinx_spips = { .name = "xilinx_spips", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, .post_load = xilinx_spips_post_load, .fields = (VMStateField[]) { VMSTATE_FIFO8(tx_fifo, XilinxSPIPS), diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c index d3c02ea18f..34124fe3d1 100644 --- a/hw/timer/allwinner-a10-pit.c +++ b/hw/timer/allwinner-a10-pit.c @@ -190,7 +190,6 @@ static const VMStateDescription vmstate_a10_pit = { .name = "a10.pit", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(irq_enable, AwA10PITState), VMSTATE_UINT32(irq_status, AwA10PITState), diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index fb0a45c889..145291016b 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -150,8 +150,7 @@ static const VMStateDescription vmstate_arm_timer = { .name = "arm_timer", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(control, arm_timer_state), VMSTATE_UINT32(limit, arm_timer_state), VMSTATE_INT32(int_level, arm_timer_state), @@ -271,8 +270,7 @@ static const VMStateDescription vmstate_sp804 = { .name = "sp804", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_INT32_ARRAY(level, SP804State, 2), VMSTATE_END_OF_LIST() } diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c index 28cb328f9b..52bbbbca7f 100644 --- a/hw/timer/cadence_ttc.c +++ b/hw/timer/cadence_ttc.c @@ -443,7 +443,6 @@ static const VMStateDescription vmstate_cadence_timer = { .name = "cadence_timer", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .pre_save = cadence_timer_pre_save, .post_load = cadence_timer_post_load, .fields = (VMStateField[]) { @@ -464,7 +463,6 @@ static const VMStateDescription vmstate_cadence_ttc = { .name = "cadence_TTC", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT_ARRAY(timer, CadenceTTCState, 3, 0, vmstate_cadence_timer, diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c index 1fde22c67f..7e28e7e5f5 100644 --- a/hw/timer/digic-timer.c +++ b/hw/timer/digic-timer.c @@ -36,7 +36,6 @@ static const VMStateDescription vmstate_digic_timer = { .name = "digic.timer", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_PTIMER(ptimer, DigicTimerState), VMSTATE_UINT32(control, DigicTimerState), diff --git a/hw/timer/ds1338.c b/hw/timer/ds1338.c index bb2f8ee8b3..ec6dbeeab0 100644 --- a/hw/timer/ds1338.c +++ b/hw/timer/ds1338.c @@ -40,7 +40,6 @@ static const VMStateDescription vmstate_ds1338 = { .name = "ds1338", .version_id = 2, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_I2C_SLAVE(parent_obj, DS1338State), VMSTATE_INT64(offset, DS1338State), diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index 86f4fcd3e8..015bbaf1bd 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -264,7 +264,6 @@ static const VMStateDescription vmstate_tick_timer = { .name = "exynos4210.mct.tick_timer", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(cnt_run, struct tick_timer), VMSTATE_UINT32(int_run, struct tick_timer), @@ -284,7 +283,6 @@ static const VMStateDescription vmstate_lregs = { .name = "exynos4210.mct.lregs", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(cnt, struct lregs, L_REG_CNT_AMOUNT), VMSTATE_UINT32(tcon, struct lregs), @@ -299,7 +297,6 @@ static const VMStateDescription vmstate_exynos4210_mct_lt = { .name = "exynos4210.mct.lt", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_INT32(id, Exynos4210MCTLT), VMSTATE_STRUCT(tick_timer, Exynos4210MCTLT, 0, @@ -317,7 +314,6 @@ static const VMStateDescription vmstate_gregs = { .name = "exynos4210.mct.lregs", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT64(cnt, struct gregs), VMSTATE_UINT32(cnt_wstat, struct gregs), @@ -336,7 +332,6 @@ static const VMStateDescription vmstate_exynos4210_mct_gt = { .name = "exynos4210.mct.lt", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT(reg, Exynos4210MCTGT, 0, vmstate_gregs, struct gregs), @@ -351,7 +346,6 @@ static const VMStateDescription vmstate_exynos4210_mct_state = { .name = "exynos4210.mct", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(reg_mct_cfg, Exynos4210MCTState), VMSTATE_STRUCT_ARRAY(l_timer, Exynos4210MCTState, 2, 0, @@ -824,14 +818,14 @@ static void exynos4210_ltick_recalc_count(struct tick_timer *s) */ if (s->last_tcnto) { - to_count = s->last_tcnto * s->last_icnto; + to_count = (uint64_t)s->last_tcnto * s->last_icnto; } else { to_count = s->last_icnto; } } else { /* distance is passed, recalculate with tcnto * icnto */ if (s->icntb) { - s->distance = s->tcntb * s->icntb; + s->distance = (uint64_t)s->tcntb * s->icntb; } else { s->distance = s->tcntb; } diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c index 1aa8f4d07a..1c1a2b8ff6 100644 --- a/hw/timer/exynos4210_pwm.c +++ b/hw/timer/exynos4210_pwm.c @@ -120,7 +120,6 @@ static const VMStateDescription vmstate_exynos4210_pwm = { .name = "exynos4210.pwm.pwm", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(id, Exynos4210PWM), VMSTATE_UINT32(freq, Exynos4210PWM), @@ -135,7 +134,6 @@ static const VMStateDescription vmstate_exynos4210_pwm_state = { .name = "exynos4210.pwm", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32_ARRAY(reg_tcfg, Exynos4210PWMState, 2), VMSTATE_UINT32(reg_tcon, Exynos4210PWMState), diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c index 026f81a2e3..bf2ee9f80e 100644 --- a/hw/timer/exynos4210_rtc.c +++ b/hw/timer/exynos4210_rtc.c @@ -118,7 +118,6 @@ static const VMStateDescription vmstate_exynos4210_rtc_state = { .name = "exynos4210.rtc", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(reg_intp, Exynos4210RTCState), VMSTATE_UINT32(reg_rtccon, Exynos4210RTCState), diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c index 0dbe15c99b..c855eba43c 100644 --- a/hw/timer/imx_epit.c +++ b/hw/timer/imx_epit.c @@ -353,8 +353,7 @@ static const VMStateDescription vmstate_imx_timer_epit = { .name = "imx.epit", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(cr, IMXEPITState), VMSTATE_UINT32(sr, IMXEPITState), VMSTATE_UINT32(lr, IMXEPITState), diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index f2d1975e70..56ee4db991 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -146,8 +146,7 @@ static const VMStateDescription vmstate_imx_timer_gpt = { .name = "imx.gpt", .version_id = 3, .minimum_version_id = 3, - .minimum_version_id_old = 3, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_UINT32(cr, IMXGPTState), VMSTATE_UINT32(pr, IMXGPTState), VMSTATE_UINT32(sr, IMXGPTState), diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c index 0f546c4121..130e9dc345 100644 --- a/hw/timer/pxa2xx_timer.c +++ b/hw/timer/pxa2xx_timer.c @@ -476,7 +476,6 @@ static const VMStateDescription vmstate_pxa2xx_timer0_regs = { .name = "pxa2xx_timer0", .version_id = 2, .minimum_version_id = 2, - .minimum_version_id_old = 2, .fields = (VMStateField[]) { VMSTATE_UINT32(value, PXA2xxTimer0), VMSTATE_END_OF_LIST(), @@ -487,7 +486,6 @@ static const VMStateDescription vmstate_pxa2xx_timer4_regs = { .name = "pxa2xx_timer4", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_STRUCT(tm, PXA2xxTimer4, 1, vmstate_pxa2xx_timer0_regs, PXA2xxTimer0), @@ -509,7 +507,6 @@ static const VMStateDescription vmstate_pxa2xx_timer_regs = { .name = "pxa2xx_timer", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .post_load = pxa25x_timer_post_load, .fields = (VMStateField[]) { VMSTATE_INT32(clock, PXA2xxTimerInfo), diff --git a/hw/timer/twl92230.c b/hw/timer/twl92230.c index 85d59909da..7ded4ba2ad 100644 --- a/hw/timer/twl92230.c +++ b/hw/timer/twl92230.c @@ -772,8 +772,7 @@ static const VMStateDescription vmstate_menelaus_tm = { .name = "menelaus_tm", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_UINT16_HACK(tm_sec, struct tm), VMSTATE_UINT16_HACK(tm_min, struct tm), VMSTATE_UINT16_HACK(tm_hour, struct tm), @@ -811,10 +810,9 @@ static const VMStateDescription vmstate_menelaus = { .name = "menelaus", .version_id = 0, .minimum_version_id = 0, - .minimum_version_id_old = 0, .pre_save = menelaus_pre_save, .post_load = menelaus_post_load, - .fields = (VMStateField []) { + .fields = (VMStateField[]) { VMSTATE_INT32(firstbyte, MenelausState), VMSTATE_UINT8(reg, MenelausState), VMSTATE_UINT8_ARRAY(vcore, MenelausState, 5), diff --git a/target-arm/helper.c b/target-arm/helper.c index 3be917c22e..417161e216 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -2081,6 +2081,13 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, { ARMCPU *cpu = arm_env_get_cpu(env); + if (env->cp15.c1_sys == value) { + /* Skip the TLB flush if nothing actually changed; Linux likes + * to do a lot of pointless SCTLR writes. + */ + return; + } + env->cp15.c1_sys = value; /* ??? Lots of these bits are not implemented. */ /* This may enable/disable the MMU, so do a TLB flush. */ diff --git a/target-arm/machine.c b/target-arm/machine.c index 810ba27f40..5092dcda79 100644 --- a/target-arm/machine.c +++ b/target-arm/machine.c @@ -39,7 +39,6 @@ static const VMStateDescription vmstate_vfp = { .name = "cpu/vfp", .version_id = 3, .minimum_version_id = 3, - .minimum_version_id_old = 3, .fields = (VMStateField[]) { VMSTATE_FLOAT64_ARRAY(env.vfp.regs, ARMCPU, 64), /* The xregs array is a little awkward because element 1 (FPSCR) @@ -72,7 +71,6 @@ static const VMStateDescription vmstate_iwmmxt = { .name = "cpu/iwmmxt", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT64_ARRAY(env.iwmmxt.regs, ARMCPU, 16), VMSTATE_UINT32_ARRAY(env.iwmmxt.cregs, ARMCPU, 16), @@ -92,7 +90,6 @@ static const VMStateDescription vmstate_m = { .name = "cpu/m", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(env.v7m.other_sp, ARMCPU), VMSTATE_UINT32(env.v7m.vecbase, ARMCPU), @@ -116,7 +113,6 @@ static const VMStateDescription vmstate_thumb2ee = { .name = "cpu/thumb2ee", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, .fields = (VMStateField[]) { VMSTATE_UINT32(env.teecr, ARMCPU), VMSTATE_UINT32(env.teehbr, ARMCPU), @@ -224,7 +220,6 @@ const VMStateDescription vmstate_arm_cpu = { .name = "cpu", .version_id = 17, .minimum_version_id = 17, - .minimum_version_id_old = 17, .pre_save = cpu_pre_save, .post_load = cpu_post_load, .fields = (VMStateField[]) { diff --git a/util/fifo8.c b/util/fifo8.c index 6a43482c9e..0ea5ad98e3 100644 --- a/util/fifo8.c +++ b/util/fifo8.c @@ -116,8 +116,7 @@ const VMStateDescription vmstate_fifo8 = { .name = "Fifo8", .version_id = 1, .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { + .fields = (VMStateField[]) { VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity), VMSTATE_UINT32(head, Fifo8), VMSTATE_UINT32(num, Fifo8),