#define SYSTEM_REGISTER_FIELDS_LIST(V_, M_) \
/* NZCV */ \
-V_(Flags, 31, 28, Bits) \
-V_(N, 31, 31, Bits) \
-V_(Z, 30, 30, Bits) \
-V_(C, 29, 29, Bits) \
-V_(V, 28, 28, Bits) \
+V_(Flags, 31, 28, Bits, uint32_t) \
+V_(N, 31, 31, Bits, bool) \
+V_(Z, 30, 30, Bits, bool) \
+V_(C, 29, 29, Bits, bool) \
+V_(V, 28, 28, Bits, uint32_t) \
M_(NZCV, Flags_mask) \
\
/* FPCR */ \
-V_(AHP, 26, 26, Bits) \
-V_(DN, 25, 25, Bits) \
-V_(FZ, 24, 24, Bits) \
-V_(RMode, 23, 22, Bits) \
+V_(AHP, 26, 26, Bits, bool) \
+V_(DN, 25, 25, Bits, bool) \
+V_(FZ, 24, 24, Bits, bool) \
+V_(RMode, 23, 22, Bits, FPRounding) \
M_(FPCR, AHP_mask | DN_mask | FZ_mask | RMode_mask)
// Fields offsets.
-#define DECLARE_FIELDS_OFFSETS(Name, HighBit, LowBit, X) \
-const int Name##_offset = LowBit; \
-const int Name##_width = HighBit - LowBit + 1; \
-const uint32_t Name##_mask = ((1 << Name##_width) - 1) << LowBit;
+#define DECLARE_FIELDS_OFFSETS(Name, HighBit, LowBit, unused_1, unused_2) \
+ const int Name##_offset = LowBit; \
+ const int Name##_width = HighBit - LowBit + 1; \
+ const uint32_t Name##_mask = ((1 << Name##_width) - 1) << LowBit;
+#define DECLARE_INSTRUCTION_FIELDS_OFFSETS(Name, HighBit, LowBit, unused_1) \
+ DECLARE_FIELDS_OFFSETS(Name, HighBit, LowBit, unused_1, unused_2)
#define NOTHING(A, B)
-INSTRUCTION_FIELDS_LIST(DECLARE_FIELDS_OFFSETS)
+INSTRUCTION_FIELDS_LIST(DECLARE_INSTRUCTION_FIELDS_OFFSETS)
SYSTEM_REGISTER_FIELDS_LIST(DECLARE_FIELDS_OFFSETS, NOTHING)
#undef NOTHING
-#undef DECLARE_FIELDS_BITS
+#undef DECLARE_FIELDS_OFFSETS
+#undef DECLARE_INSTRUCTION_FIELDS_OFFSETS
// ImmPCRel is a compound field (not present in INSTRUCTION_FIELDS_LIST), formed
// from ImmPCRelLo and ImmPCRelHi.
int64_t result;
int64_t signed_sum = src1 + src2 + carry_in;
- uint32_t N, Z, C, V;
+ bool N, Z, C, V;
if (reg_size == kWRegSizeInBits) {
u1 = static_cast<uint64_t>(src1) & kWRegMask;
fprintf(stream_, "# %sFLAGS: %sN:%d Z:%d C:%d V:%d%s\n",
clr_flag_name,
clr_flag_value,
- N(), Z(), C(), V(),
+ nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
clr_normal);
}
last_nzcv = nzcv();
instr->FlagsUpdate(),
reg(reg_size, instr->Rn()),
op2,
- C());
+ nzcv().C());
set_reg(reg_size, instr->Rd(), new_val);
}
unsigned dst = instr->Rd();
unsigned src = instr->Rn();
- FPRounding round = RMode();
+ FPRounding round = fpcr().RMode();
switch (instr->Mask(FPIntegerConvertMask)) {
case FCVTAS_ws: set_wreg(dst, FPToInt32(sreg(src), FPTieAway)); break;
unsigned src = instr->Rn();
int fbits = 64 - instr->FPScale();
- FPRounding round = RMode();
+ FPRounding round = fpcr().RMode();
switch (instr->Mask(FPFixedPointConvertMask)) {
// A 32-bit input can be handled in the same way as a 64-bit input, since
double Simulator::FPToDouble(float value) {
switch (std::fpclassify(value)) {
case FP_NAN: {
- if (DN()) return kFP64DefaultNaN;
+ if (fpcr().DN()) return kFP64DefaultNaN;
// Convert NaNs as the processor would:
// - The sign is propagated.
switch (std::fpclassify(value)) {
case FP_NAN: {
- if (DN()) return kFP32DefaultNaN;
+ if (fpcr().DN()) return kFP32DefaultNaN;
// Convert NaNs as the processor would:
// - The sign is propagated.
template <typename T>
T Simulator::FPProcessNaN(T op) {
ASSERT(std::isnan(op));
- return DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
+ return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
}
// Default system register values.
static SimSystemRegister DefaultValueFor(SystemRegister id);
-#define DEFINE_GETTER(Name, HighBit, LowBit, Func) \
- uint32_t Name() const { return Func(HighBit, LowBit); } \
- void Set##Name(uint32_t bits) { SetBits(HighBit, LowBit, bits); }
-#define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
+#define DEFINE_GETTER(Name, HighBit, LowBit, Func, Type) \
+ Type Name() const { return static_cast<Type>(Func(HighBit, LowBit)); } \
+ void Set##Name(Type bits) { \
+ SetBits(HighBit, LowBit, static_cast<Type>(bits)); \
+ }
+#define DEFINE_WRITE_IGNORE_MASK(Name, Mask) \
static const uint32_t Name##WriteIgnoreMask = ~static_cast<uint32_t>(Mask);
-
SYSTEM_REGISTER_FIELDS_LIST(DEFINE_GETTER, DEFINE_WRITE_IGNORE_MASK)
-
#undef DEFINE_ZERO_BITS
#undef DEFINE_GETTER
set_fpreg(code, value);
}
- bool N() { return nzcv_.N() != 0; }
- bool Z() { return nzcv_.Z() != 0; }
- bool C() { return nzcv_.C() != 0; }
- bool V() { return nzcv_.V() != 0; }
SimSystemRegister& nzcv() { return nzcv_; }
-
- // TODO(jbramley): Find a way to make the fpcr_ members return the proper
- // types, so these accessors are not necessary.
- FPRounding RMode() { return static_cast<FPRounding>(fpcr_.RMode()); }
- bool DN() { return fpcr_.DN() != 0; }
SimSystemRegister& fpcr() { return fpcr_; }
// Debug helpers
protected:
// Simulation helpers ------------------------------------
bool ConditionPassed(Condition cond) {
+ SimSystemRegister& flags = nzcv();
switch (cond) {
case eq:
- return Z();
+ return flags.Z();
case ne:
- return !Z();
+ return !flags.Z();
case hs:
- return C();
+ return flags.C();
case lo:
- return !C();
+ return !flags.C();
case mi:
- return N();
+ return flags.N();
case pl:
- return !N();
+ return !flags.N();
case vs:
- return V();
+ return flags.V();
case vc:
- return !V();
+ return !flags.V();
case hi:
- return C() && !Z();
+ return flags.C() && !flags.Z();
case ls:
- return !(C() && !Z());
+ return !(flags.C() && !flags.Z());
case ge:
- return N() == V();
+ return flags.N() == flags.V();
case lt:
- return N() != V();
+ return flags.N() != flags.V();
case gt:
- return !Z() && (N() == V());
+ return !flags.Z() && (flags.N() == flags.V());
case le:
- return !(!Z() && (N() == V()));
+ return !(!flags.Z() && (flags.N() == flags.V()));
case nv: // Fall through.
case al:
return true;