From 09319b30411357afcd2bf75a78acd705ea704131 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:35 +0100 Subject: [PATCH 01/17] disas/libvixl: Update to libvixl 1.4 Update our copy of libvixl to upstream's 1.4 release. Note that we no longer need any local fixes for compilation on 32 bit hosts -- they have all been integrated upstream. Signed-off-by: Peter Maydell Message-id: 1399040419-9227-1-git-send-email-peter.maydell@linaro.org Acked-by: Richard Henderson --- disas/libvixl/a64/assembler-a64.h | 451 ++++++++++++++++---------- disas/libvixl/a64/constants-a64.h | 36 +- disas/libvixl/a64/decoder-a64.cc | 36 +- disas/libvixl/a64/disasm-a64.cc | 189 +++++++---- disas/libvixl/a64/disasm-a64.h | 1 + disas/libvixl/a64/instructions-a64.cc | 32 +- disas/libvixl/a64/instructions-a64.h | 56 ++-- disas/libvixl/globals.h | 42 ++- disas/libvixl/platform.h | 4 +- disas/libvixl/utils.cc | 37 ++- disas/libvixl/utils.h | 86 ++++- 11 files changed, 628 insertions(+), 342 deletions(-) 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 From 8f1e884b38f6e947f7edd22aad1b3f0058f054da Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 13 May 2014 16:09:35 +0100 Subject: [PATCH 02/17] savevm: Remove all the unneeded version_minimum_id_old (arm) After commit 767adce2d, they are redundant. This way we don't assign them except when needed. Once there, there were lots of cases where the ".fields" indentation was wrong: .fields = (VMStateField []) { and .fields = (VMStateField []) { Change all the combinations to: .fields = (VMStateField[]){ The biggest problem (apart from aesthetics) was that checkpatch complained when we copy&pasted the code from one place to another. Signed-off-by: Juan Quintela [PMM: fixed minor conflict, corrected commit message typos] Signed-off-by: Peter Maydell --- hw/arm/highbank.c | 1 - hw/arm/musicpal.c | 8 -------- hw/arm/pxa2xx.c | 19 ++++++------------- hw/arm/pxa2xx_gpio.c | 3 +-- hw/arm/pxa2xx_pic.c | 1 - hw/arm/spitz.c | 12 ++++-------- hw/arm/stellaris.c | 12 ++++-------- hw/arm/strongarm.c | 6 ------ hw/arm/z2.c | 2 -- hw/audio/lm4549.c | 5 ++--- hw/audio/marvell_88w8618.c | 1 - hw/audio/pl041.c | 9 +++------ hw/audio/wm8750.c | 3 +-- hw/block/ecc.c | 3 +-- hw/block/nand.c | 3 +-- hw/block/onenand.c | 1 - hw/char/cadence_uart.c | 1 - hw/char/digic-uart.c | 1 - hw/char/exynos4210_uart.c | 2 -- hw/char/imx_serial.c | 1 - hw/char/pl011.c | 3 +-- hw/display/ads7846.c | 3 +-- hw/display/exynos4210_fimd.c | 4 ++-- hw/display/pxa2xx_lcd.c | 6 ++---- hw/display/ssd0303.c | 3 +-- hw/dma/pl330.c | 5 ----- hw/dma/pxa2xx_dma.c | 2 -- hw/gpio/max7310.c | 3 +-- hw/gpio/zaurus.c | 3 +-- hw/input/lm832x.c | 3 +-- hw/input/pxa2xx_keypad.c | 3 +-- hw/input/stellaris_input.c | 6 ++---- hw/intc/allwinner-a10-pic.c | 1 - hw/intc/armv7m_nvic.c | 3 +-- hw/intc/exynos4210_combiner.c | 2 -- hw/intc/exynos4210_gic.c | 1 - hw/intc/imx_avic.c | 1 - hw/misc/exynos4210_pmu.c | 2 +- hw/misc/imx_ccm.c | 1 - hw/misc/max111x.c | 3 +-- hw/misc/mst_fpga.c | 11 +++++------ hw/misc/tmp105.c | 3 +-- hw/misc/zynq_slcr.c | 3 +-- hw/net/cadence_gem.c | 3 +-- hw/net/smc91c111.c | 2 +- hw/net/xgmac.c | 2 +- hw/ssi/pl022.c | 3 +-- hw/ssi/ssi.c | 3 +-- hw/ssi/xilinx_spi.c | 1 - hw/ssi/xilinx_spips.c | 1 - hw/timer/allwinner-a10-pit.c | 1 - hw/timer/arm_timer.c | 6 ++---- hw/timer/cadence_ttc.c | 2 -- hw/timer/digic-timer.c | 1 - hw/timer/ds1338.c | 1 - hw/timer/exynos4210_mct.c | 6 ------ hw/timer/exynos4210_pwm.c | 2 -- hw/timer/exynos4210_rtc.c | 1 - hw/timer/imx_epit.c | 3 +-- hw/timer/imx_gpt.c | 3 +-- hw/timer/pxa2xx_timer.c | 3 --- hw/timer/twl92230.c | 6 ++---- target-arm/machine.c | 5 ----- util/fifo8.c | 3 +-- 64 files changed, 58 insertions(+), 169 deletions(-) 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/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..c7de9cf177 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -286,8 +286,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 +642,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 +849,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 +1118,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/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..bd29322609 100644 --- a/hw/intc/allwinner-a10-pic.c +++ b/hw/intc/allwinner-a10-pic.c @@ -141,7 +141,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/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..a779658314 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1257,8 +1257,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/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..01e750e131 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, 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/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), From 5c10495ab1546d5d12b51a97817051e9ec98d0f6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:36 +0100 Subject: [PATCH 03/17] hw/net/stellaris_enet: Restructure tx_fifo code to avoid buffer overrun The current tx_fifo code has a corner case where the guest can overrun the fifo buffer: if automatic CRCs are disabled we allow the guest to write the CRC word even if there isn't actually space for it in the FIFO. The datasheet is unclear about exactly how the hardware deals with this situation; the most plausible answer seems to be that the CRC word is just lost. Implement this fix by separating the "can we stuff another word in the FIFO" logic from the "should we transmit the packet now" check. This also moves us closer to the real hardware, which has a number of ways it can be configured to trigger sending the packet, some of which we don't implement. Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert Cc: qemu-stable@nongnu.org --- hw/net/stellaris_enet.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index d04e6a46f8..bd844cdc38 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -253,10 +253,12 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, s->tx_fifo[s->tx_fifo_len++] = value >> 24; } } else { - 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 + 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) From 7fd5f064d1c1a827a95ffe678418b3d5b8d2f108 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:36 +0100 Subject: [PATCH 04/17] hw/net/stellaris_enet: Correct handling of packet padding The PADEN bit in the transmit control register enables padding of short data packets out to the required minimum length. However a typo here meant we were adjusting tx_fifo_len rather than tx_frame_len, so the padding didn't actually happen. Fix this bug. Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert Cc: qemu-stable@nongnu.org --- hw/net/stellaris_enet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index bd844cdc38..d0da819616 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -265,7 +265,7 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, 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; + s->tx_frame_len = 60; } qemu_send_packet(qemu_get_queue(s->nic), s->tx_fifo, s->tx_frame_len); From c6fa443b3dab9f49fb157b0164f5852fde68ed3b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:36 +0100 Subject: [PATCH 05/17] hw/net/stellaris_enet: Rewrite tx fifo handling code The datasheet is clear that the frame length written to the DATA register is actually stored in the TX FIFO; this means we don't need to keep both tx_frame_len and tx_fifo_len state separately. Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert --- hw/net/stellaris_enet.c | 119 ++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 42 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index d0da819616..b99f93e732 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -59,7 +59,6 @@ typedef struct { uint32_t mtxd; uint32_t mrxd; uint32_t np; - int tx_frame_len; int tx_fifo_len; uint8_t tx_fifo[2048]; /* Real hardware has a 2k fifo, which works out to be at most 31 packets. @@ -82,6 +81,62 @@ 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; +} + +/* 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) { @@ -215,8 +270,9 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, DPRINTF("IRQ ack %02x/%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); @@ -235,46 +291,27 @@ 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; - } - } 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_frame_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"); + break; } } + + 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 (stellaris_txpacket_complete(s)) { + stellaris_enet_send(s); + } break; case 0x14: /* IA0 */ s->conf.macaddr.a[0] = value; @@ -326,7 +363,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; + s->tx_fifo_len = 0; } static void stellaris_enet_save(QEMUFile *f, void *opaque) @@ -344,7 +381,6 @@ static void stellaris_enet_save(QEMUFile *f, void *opaque) 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++) { @@ -375,7 +411,6 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) 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++) { From a9171c4fb570b9c6f65955de03d3e38d2e9b0fdf Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:37 +0100 Subject: [PATCH 06/17] hw/net/stellaris_enet: Correctly implement the TR and THR registers Packet transmission for the stellaris ethernet controller can be triggered in one of two ways: * by setting a threshold value in the THR register; when the FIFO fill level reaches the threshold, the h/w starts transmitting. Software has to finish filling the FIFO before the transmit process completes to avoid a (silent) underrun * by software writing to the TR register to explicitly trigger transmission Since QEMU transmits packets instantaneously (from the guest's point of view), implement "transmit based on threshold" with our existing mechanism of "transmit as soon as we have the whole packet", with the additional wrinkle that we don't transmit if the packet size is below the specified threshold, and implement "transmit by specific request" properly. Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert --- hw/net/stellaris_enet.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index b99f93e732..2079fc691f 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -109,6 +109,15 @@ static inline bool stellaris_txpacket_complete(stellaris_enet_state *s) 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) { @@ -309,7 +318,7 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, s->tx_fifo[s->tx_fifo_len++] = value >> 24; } - if (stellaris_txpacket_complete(s)) { + if (stellaris_tx_thr_reached(s) && stellaris_txpacket_complete(s)) { stellaris_enet_send(s); } break; @@ -338,9 +347,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. */ From eacd606ca726b15ce9a5f0871f0c6598dbc8d6ae Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:37 +0100 Subject: [PATCH 07/17] hw/net/stellaris_enet: Fix debug format strings Fix various debug format strings which were incorrect for the data type, so that building with debug enabled is possible. Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert --- hw/net/stellaris_enet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 2079fc691f..1cb95e012f 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -161,7 +161,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; @@ -276,7 +276,7 @@ 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) { @@ -284,7 +284,7 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, } 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; From 889ac2a32fd803f7222524d8f56aded1c3cbad3c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:37 +0100 Subject: [PATCH 08/17] hw/net/stellaris_enet: Get rid of rx_fifo pointer The rx_fifo pointer is awkward to migrate, and is actually redundant since it is always possible to determine it from the current rx[].len/.data and rx_fifo_len. Remove both rx_fifo and rx_fifo_len from the state, replacing them with a simple rx_fifo_offset which points at the current location in the RX fifo. Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert --- hw/net/stellaris_enet.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 1cb95e012f..9e8f143ea5 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -67,8 +67,7 @@ typedef struct { uint8_t data[2048]; int len; } rx[31]; - uint8_t *rx_fifo; - int rx_fifo_len; + int rx_fifo_offset; int next_packet; NICState *nic; NICConf conf; @@ -216,21 +215,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; @@ -238,6 +237,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) @@ -291,8 +291,8 @@ static void stellaris_enet_write(void *opaque, hwaddr offset, 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; @@ -402,8 +402,7 @@ static void stellaris_enet_save(QEMUFile *f, void *opaque) } 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); + qemu_put_be32(f, s->rx_fifo_offset); } static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) @@ -432,8 +431,7 @@ static int stellaris_enet_load(QEMUFile *f, void *opaque, int version_id) } 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); + s->rx_fifo_offset = qemu_get_be32(f); return 0; } From 2e1198672759eda6e122ff38fcf6df06f27e0fe2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:38 +0100 Subject: [PATCH 09/17] hw/net/stellaris_enet: Convert to vmstate Convert this device to use vmstate for its save/load, including providing a post_load function that sanitizes inbound data to avoid possible buffer overflows if it is malicious. The sanitizing fixes CVE-2013-4532 (though nobody should be relying on the security properties of most of the unmaintained ARM board models anyway, and migration doesn't actually work on this board due to issues in other device models). Signed-off-by: Peter Maydell Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Michael S. Tsirkin --- hw/net/stellaris_enet.c | 148 ++++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 68 deletions(-) diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 9e8f143ea5..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,22 +64,89 @@ typedef struct { uint32_t mtxd; uint32_t mrxd; uint32_t np; - 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]; - int rx_fifo_offset; - 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); @@ -379,63 +451,6 @@ static void stellaris_enet_reset(stellaris_enet_state *s) s->tx_fifo_len = 0; } -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_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_offset); -} - -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_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_offset = qemu_get_be32(f); - - return 0; -} - static void stellaris_enet_cleanup(NetClientState *nc) { stellaris_enet_state *s = qemu_get_nic_opaque(nc); @@ -467,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; } @@ -476,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); } @@ -494,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 = { From 2f0d8631b74c873c8867a7b509335bc2bf8d8886 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:38 +0100 Subject: [PATCH 10/17] target-arm/helper.c: Don't flush the TLB if SCTLR is rewritten unchanged Linux makes a habit of writing the same value to the SCTLR that it already holds. In a sample boot of the kernel to a shell prompt it wrote the SCTLR with the value it already held 325465 times, and wrote different values just 3 times. Skip flushing the TLB if the SCTLR value isn't actually being changed; this speeds up my sample boot by 3-5%. Reported-by: Laurent Desnogues Reviewed-by: Laurent Desnogues Signed-off-by: Peter Maydell Message-id: 1399560029-19007-1-git-send-email-peter.maydell@linaro.org --- target-arm/helper.c | 7 +++++++ 1 file changed, 7 insertions(+) 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. */ From 654039b42a7f0e7d1b719a17d5c388662950b9ab Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:38 +0100 Subject: [PATCH 11/17] hw/intc/allwinner-a10-pic: Add missing 'break' Add missing 'break' after handling of AW_A10_PIC_BASE_ADDR write. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/intc/allwinner-a10-pic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/intc/allwinner-a10-pic.c b/hw/intc/allwinner-a10-pic.c index bd29322609..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; From c94239fe5633fb9816b5bbc61ccc134ce7171b2b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:38 +0100 Subject: [PATCH 12/17] hw/net/cadence_gem: Remove dead code Commit 191946c moved the code to handle padding to minimum length from after the handling of the CRC to before it. This means that the CRC code doesn't need to cope with the possibility that the size is less than 60; remove this dead code. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/net/cadence_gem.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index a779658314..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; From 7e7e5858f83ae711b08d11e2268c6fc6f8385fb7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:39 +0100 Subject: [PATCH 13/17] hw/arm/omap1: Avoid unintended sign extension writing omap_rtc YEARS_REG When writing to the YEARS_REG register, if the year value is 99 then the multiplication by 31536000 will overflow into the sign bit of a 32 bit value and then be erroneously sign-extended if time_t is 64 bits. Add a cast to avoid this. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/arm/omap1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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; From 2a41c92854385eb1ae677e79257e136886200ace Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:39 +0100 Subject: [PATCH 14/17] hw/dma/omap_dma: Add (uint32_t) casts when shifting uint16_t by 16 Add missing (uint32_t) casts in cases where we're trying to put a uint16_t value into the top half of a 32-bit field. These were already present in some but not all places. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/dma/omap_dma.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) 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: From c3a699be3c63f75b6ea5877080ea9b96b37524c4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:39 +0100 Subject: [PATCH 15/17] hw/timer/exynos4210_mct: Avoid overflow in exynos4210_ltick_recalc_count Add casts to avoid potentially overflowing the multiplications of 32 bit quantities in exynos4210_ltick_recalc_count(). Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/timer/exynos4210_mct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index 01e750e131..015bbaf1bd 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -818,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; } From 1a7917210bd2fc8bd792f4dd36d3d44bd2244104 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:39 +0100 Subject: [PATCH 16/17] hw/arm/stellaris: Correct handling of GPTM TAR register We don't implement very much of the GPTM TAR register, and what we do is wrong. The "are we in RT mode?" field is in s->config, not s->control. Correct this, use LOG_UNIMP rather than hw_error() for the cases we don't support, and avoid an unlabelled fallthrough that makes Coverity complain. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/arm/stellaris.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index c7de9cf177..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; } } From 89f26e6b7b5e5c9657f2abd6ef5a336bea11add2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 13 May 2014 16:09:39 +0100 Subject: [PATCH 17/17] hw/arm/omap_gpmc: Avoid buffer overrun filling prefetch FIFO In fill_prefetch_fifo(), if the device we are reading from is 16 bit, then we must not try to transfer an odd number of bytes into the FIFO. This could otherwise have resulted in our overrunning the prefetch.fifo array by one byte. Signed-off-by: Peter Maydell Reviewed-by: Peter Crosthwaite --- hw/misc/omap_gpmc.c | 4 ++++ 1 file changed, 4 insertions(+) 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;