Commit 6b7aa99e authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140513' into staging



target-arm queue:
 * update libvixl to 1.4
 * remove version_minimum_id_old from ARM devices
 * stellaris_enet tx/rx/migration overhaul
 * various minor fixes for coverity issues

# gpg: Signature made Tue 13 May 2014 16:25:12 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"

* remotes/pmaydell/tags/pull-target-arm-20140513:
  hw/arm/omap_gpmc: Avoid buffer overrun filling prefetch FIFO
  hw/arm/stellaris: Correct handling of GPTM TAR register
  hw/timer/exynos4210_mct: Avoid overflow in exynos4210_ltick_recalc_count
  hw/dma/omap_dma: Add (uint32_t) casts when shifting uint16_t by 16
  hw/arm/omap1: Avoid unintended sign extension writing omap_rtc YEARS_REG
  hw/net/cadence_gem: Remove dead code
  hw/intc/allwinner-a10-pic: Add missing 'break'
  target-arm/helper.c: Don't flush the TLB if SCTLR is rewritten unchanged
  hw/net/stellaris_enet: Convert to vmstate
  hw/net/stellaris_enet: Get rid of rx_fifo pointer
  hw/net/stellaris_enet: Fix debug format strings
  hw/net/stellaris_enet: Correctly implement the TR and THR registers
  hw/net/stellaris_enet: Rewrite tx fifo handling code
  hw/net/stellaris_enet: Correct handling of packet padding
  hw/net/stellaris_enet: Restructure tx_fifo code to avoid buffer overrun
  savevm: Remove all the unneeded version_minimum_id_old (arm)
  disas/libvixl: Update to libvixl 1.4

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents ef3cb5ca 89f26e6b
Loading
Loading
Loading
Loading
+281 −170

File changed.

Preview size limit exceeded, changes collapsed.

+33 −3
Original line number Diff line number Diff line
@@ -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<Condition>(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.
+18 −18
Original line number Diff line number Diff line
@@ -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 <b28:b27> = 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,7 +444,7 @@ void Decoder::DecodeAddSubImmediate(Instruction* instr) {


void Decoder::DecodeDataProcessing(Instruction* instr) {
  ASSERT((instr->Bits(27, 24) == 0xA) ||
  VIXL_ASSERT((instr->Bits(27, 24) == 0xA) ||
              (instr->Bits(27, 24) == 0xB));

  if (instr->Bit(24) == 0) {
@@ -559,7 +559,7 @@ void Decoder::DecodeDataProcessing(Instruction* instr) {


void Decoder::DecodeFP(Instruction* instr) {
  ASSERT((instr->Bits(27, 24) == 0xE) ||
  VIXL_ASSERT((instr->Bits(27, 24) == 0xE) ||
              (instr->Bits(27, 24) == 0xF));

  if (instr->Bit(28) == 0) {
@@ -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<DecoderVisitor*>::iterator it;                                   \
    for (it = visitors_.begin(); it != visitors_.end(); it++) {                \
      (*it)->Visit##A(instr);                                                  \
+117 −72
Original line number Diff line number Diff line
@@ -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) ||
  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) |
      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;
+1 −0
Original line number Diff line number Diff line
@@ -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);
Loading