Add unpredictable conditions for ADC_i, ADC_r, ADC_rr, ADD_ADR, ADD_i, ADD_r, ADD_rr, ADD_SP_i, ADD_SP_r, ADR and MOV_i.
Change-Id: I2d0255c352881d855b375db65794ee7f282b1cfe
diff --git a/src/aarch32/assembler-aarch32.cc b/src/aarch32/assembler-aarch32.cc
index 43945af..a1c2630 100644
--- a/src/aarch32/assembler-aarch32.cc
+++ b/src/aarch32/assembler-aarch32.cc
@@ -1806,7 +1806,8 @@
if (IsUsingT32()) {
ImmediateT32 immediate_t32(imm);
// ADC{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
- if (!size.IsNarrow() && immediate_t32.IsValid()) {
+ if (!size.IsNarrow() && immediate_t32.IsValid() &&
+ ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf1400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -1842,7 +1843,8 @@
uint32_t amount = operand.GetShiftAmount();
if (IsUsingT32()) {
// ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
- if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
+ if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
+ ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
uint32_t amount_ = amount % 32;
EmitT32_32(0xeb400000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
@@ -1866,7 +1868,9 @@
Shift shift = operand.GetShift();
if (IsUsingA32()) {
// ADC{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
- if (cond.IsNotNever()) {
+ if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
+ !operand.GetShiftRegister().IsPC()) ||
+ AllowUnpredictable())) {
EmitA32(0x00a00010U | (cond.GetCondition() << 28) |
(rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
(shift.GetType() << 5) |
@@ -1890,7 +1894,8 @@
if (IsUsingT32()) {
ImmediateT32 immediate_t32(imm);
// ADCS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T1
- if (!size.IsNarrow() && immediate_t32.IsValid()) {
+ if (!size.IsNarrow() && immediate_t32.IsValid() &&
+ ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf1500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -1926,7 +1931,8 @@
uint32_t amount = operand.GetShiftAmount();
if (IsUsingT32()) {
// ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T2
- if (!size.IsNarrow() && shift.IsValidAmount(amount)) {
+ if (!size.IsNarrow() && shift.IsValidAmount(amount) &&
+ ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
uint32_t amount_ = amount % 32;
EmitT32_32(0xeb500000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
@@ -1950,7 +1956,9 @@
Shift shift = operand.GetShift();
if (IsUsingA32()) {
// ADCS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
- if (cond.IsNotNever()) {
+ if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
+ !operand.GetShiftRegister().IsPC()) ||
+ AllowUnpredictable())) {
EmitA32(0x00b00010U | (cond.GetCondition() << 28) |
(rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
(shift.GetType() << 5) |
@@ -2012,14 +2020,16 @@
return;
}
// ADD{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
- if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) {
+ if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
((imm & 0x700) << 4) | ((imm & 0x800) << 15));
AdvanceIT();
return;
}
// ADD{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
- if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp)) {
+ if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
+ ((!rd.IsPC() && !rn.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf1000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -2028,14 +2038,16 @@
return;
}
// ADD{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
- if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
+ if (!size.IsNarrow() && (imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
(imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
AdvanceIT();
return;
}
// ADD{<c>}{<q>} {<Rd>}, SP, #<const> ; T3
- if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid()) {
+ if (!size.IsNarrow() && rn.Is(sp) && immediate_t32.IsValid() &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf10d0000U | (rd.GetCode() << 8) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -2044,7 +2056,8 @@
return;
}
// ADD{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
- if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095)) {
+ if (!size.IsNarrow() && rn.Is(sp) && (imm <= 4095) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
((imm & 0x700) << 4) | ((imm & 0x800) << 15));
AdvanceIT();
@@ -2087,14 +2100,19 @@
return;
}
// ADD{<c>}{<q>} {<Rdn>}, <Rdn>, <Rm> ; T2
- if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp)) {
+ if (!size.IsWide() && rd.Is(rn) && !rm.Is(sp) &&
+ (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
+ (!rd.IsPC() || !rm.IsPC())) ||
+ AllowUnpredictable())) {
EmitT32_16(0x4400 | (rd.GetCode() & 0x7) |
((rd.GetCode() & 0x8) << 4) | (rm.GetCode() << 3));
AdvanceIT();
return;
}
// ADD{<c>}{<q>} {<Rdm>}, SP, <Rdm> ; T1
- if (!size.IsWide() && rd.Is(rm) && rn.Is(sp)) {
+ if (!size.IsWide() && rd.Is(rm) && rn.Is(sp) &&
+ (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond))) ||
+ AllowUnpredictable())) {
EmitT32_16(0x4468 | (rd.GetCode() & 0x7) |
((rd.GetCode() & 0x8) << 4));
AdvanceIT();
@@ -2112,7 +2130,8 @@
uint32_t amount = operand.GetShiftAmount();
if (IsUsingT32()) {
// ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
- if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp)) {
+ if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
+ ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
uint32_t amount_ = amount % 32;
EmitT32_32(0xeb000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
@@ -2121,7 +2140,8 @@
return;
}
// ADD{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
- if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount)) {
+ if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
+ ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
uint32_t amount_ = amount % 32;
EmitT32_32(0xeb0d0000U | (rd.GetCode() << 8) | rm.GetCode() |
(operand.GetTypeEncodingValue() << 4) |
@@ -2153,7 +2173,9 @@
Shift shift = operand.GetShift();
if (IsUsingA32()) {
// ADD{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
- if (cond.IsNotNever()) {
+ if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
+ !operand.GetShiftRegister().IsPC()) ||
+ AllowUnpredictable())) {
EmitA32(0x00800010U | (cond.GetCondition() << 28) |
(rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
(shift.GetType() << 5) |
@@ -2183,7 +2205,10 @@
Register rm = operand.GetBaseRegister();
if (IsUsingT32()) {
// ADD<c>{<q>} <Rdn>, <Rm> ; T2
- if (InITBlock() && !rm.Is(sp)) {
+ if (InITBlock() && !rm.Is(sp) &&
+ (((!rd.IsPC() || OutsideITBlockAndAlOrLast(cond)) &&
+ (!rd.IsPC() || !rm.IsPC())) ||
+ AllowUnpredictable())) {
EmitT32_16(0x4400 | (rd.GetCode() & 0x7) | ((rd.GetCode() & 0x8) << 4) |
(rm.GetCode() << 3));
AdvanceIT();
@@ -2221,7 +2246,7 @@
}
// ADDS{<c>}{<q>} {<Rd>}, <Rn>, #<const> ; T3
if (!size.IsNarrow() && immediate_t32.IsValid() && !rn.Is(sp) &&
- !rd.Is(pc)) {
+ !rd.Is(pc) && ((!rn.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf1100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -2275,7 +2300,7 @@
if (IsUsingT32()) {
// ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm> {, <shift> #<amount> } ; T3
if (!size.IsNarrow() && shift.IsValidAmount(amount) && !rn.Is(sp) &&
- !rd.Is(pc)) {
+ !rd.Is(pc) && ((!rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
uint32_t amount_ = amount % 32;
EmitT32_32(0xeb100000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode() | (operand.GetTypeEncodingValue() << 4) |
@@ -2285,7 +2310,7 @@
}
// ADDS{<c>}{<q>} {<Rd>}, SP, <Rm> {, <shift> #<amount> } ; T3
if (!size.IsNarrow() && rn.Is(sp) && shift.IsValidAmount(amount) &&
- !rd.Is(pc)) {
+ !rd.Is(pc) && ((!rm.IsPC()) || AllowUnpredictable())) {
uint32_t amount_ = amount % 32;
EmitT32_32(0xeb1d0000U | (rd.GetCode() << 8) | rm.GetCode() |
(operand.GetTypeEncodingValue() << 4) |
@@ -2317,7 +2342,9 @@
Shift shift = operand.GetShift();
if (IsUsingA32()) {
// ADDS{<c>}{<q>} {<Rd>}, <Rn>, <Rm>, <shift> <Rs> ; A1
- if (cond.IsNotNever()) {
+ if (cond.IsNotNever() && ((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() &&
+ !operand.GetShiftRegister().IsPC()) ||
+ AllowUnpredictable())) {
EmitA32(0x00900010U | (cond.GetCondition() << 28) |
(rd.GetCode() << 12) | (rn.GetCode() << 16) | rm.GetCode() |
(shift.GetType() << 5) |
@@ -2356,21 +2383,24 @@
uint32_t imm = operand.GetImmediate();
if (IsUsingT32()) {
// ADDW{<c>}{<q>} <Rd>, PC, #<imm12> ; T3
- if (rn.Is(pc) && (imm <= 4095)) {
+ if (rn.Is(pc) && (imm <= 4095) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf20f0000U | (rd.GetCode() << 8) | (imm & 0xff) |
((imm & 0x700) << 4) | ((imm & 0x800) << 15));
AdvanceIT();
return;
}
// ADDW{<c>}{<q>} {<Rd>}, <Rn>, #<imm12> ; T4
- if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd)) {
+ if ((imm <= 4095) && ((rn.GetCode() & 0xd) != 0xd) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf2000000U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
(imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15));
AdvanceIT();
return;
}
// ADDW{<c>}{<q>} {<Rd>}, SP, #<imm12> ; T4
- if (rn.Is(sp) && (imm <= 4095)) {
+ if (rn.Is(sp) && (imm <= 4095) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf20d0000U | (rd.GetCode() << 8) | (imm & 0xff) |
((imm & 0x700) << 4) | ((imm & 0x800) << 15));
AdvanceIT();
@@ -2418,7 +2448,7 @@
}
// ADR{<c>}{<q>} <Rd>, <label> ; T2
if (!size.IsNarrow() && label->IsBound() && (neg_offset > 0) &&
- (neg_offset <= 4095)) {
+ (neg_offset <= 4095) && ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (neg_offset & 0xff) |
((neg_offset & 0x700) << 4) | ((neg_offset & 0x800) << 15));
AdvanceIT();
@@ -2426,7 +2456,8 @@
}
// ADR{<c>}{<q>} <Rd>, <label> ; T3
if (!size.IsNarrow() &&
- (!label->IsBound() || ((offset >= 0) && (offset <= 4095)))) {
+ (!label->IsBound() || ((offset >= 0) && (offset <= 4095))) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
static class EmitOp : public Label::LabelEmitOperator {
public:
EmitOp() : Label::LabelEmitOperator(0, 4095) {}
@@ -6479,7 +6510,8 @@
return;
}
// MOV{<c>}{<q>} <Rd>, #<const> ; T2
- if (!size.IsNarrow() && immediate_t32.IsValid()) {
+ if (!size.IsNarrow() && immediate_t32.IsValid() &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf04f0000U | (rd.GetCode() << 8) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -6488,7 +6520,8 @@
return;
}
// MOV{<c>}{<q>} <Rd>, #<imm16> ; T3
- if (!size.IsNarrow() && (imm <= 65535)) {
+ if (!size.IsNarrow() && (imm <= 65535) &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
((imm & 0xf000) << 4));
@@ -6504,7 +6537,8 @@
return;
}
// MOV{<c>}{<q>} <Rd>, #<imm16> ; A2
- if ((imm <= 65535) && cond.IsNotNever()) {
+ if ((imm <= 65535) && cond.IsNotNever() &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitA32(0x03000000U | (cond.GetCondition() << 28) |
(rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
return;
@@ -6620,7 +6654,8 @@
return;
}
// MOVS{<c>}{<q>} <Rd>, #<const> ; T2
- if (!size.IsNarrow() && immediate_t32.IsValid()) {
+ if (!size.IsNarrow() && immediate_t32.IsValid() &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf05f0000U | (rd.GetCode() << 8) |
(immediate_t32.GetEncodingValue() & 0xff) |
((immediate_t32.GetEncodingValue() & 0x700) << 4) |
@@ -6674,7 +6709,7 @@
uint32_t imm = operand.GetImmediate();
if (IsUsingT32()) {
// MOVW{<c>}{<q>} <Rd>, #<imm16> ; T3
- if ((imm <= 65535)) {
+ if ((imm <= 65535) && ((!rd.IsPC()) || AllowUnpredictable())) {
EmitT32_32(0xf2400000U | (rd.GetCode() << 8) | (imm & 0xff) |
((imm & 0x700) << 4) | ((imm & 0x800) << 15) |
((imm & 0xf000) << 4));
@@ -6683,7 +6718,8 @@
}
} else {
// MOVW{<c>}{<q>} <Rd>, #<imm16> ; A2
- if ((imm <= 65535) && cond.IsNotNever()) {
+ if ((imm <= 65535) && cond.IsNotNever() &&
+ ((!rd.IsPC()) || AllowUnpredictable())) {
EmitA32(0x03000000U | (cond.GetCondition() << 28) |
(rd.GetCode() << 12) | (imm & 0xfff) | ((imm & 0xf000) << 4));
return;
diff --git a/src/aarch32/assembler-aarch32.h b/src/aarch32/assembler-aarch32.h
index 6f5c5e5..87bcad1 100644
--- a/src/aarch32/assembler-aarch32.h
+++ b/src/aarch32/assembler-aarch32.h
@@ -42,6 +42,8 @@
bool has_32_dregs_;
// True if we can use the assembler instructions.
bool allow_assembler_;
+ bool allow_unpredictable_;
+ bool allow_strongly_discouraged_;
protected:
void EmitT32_16(uint16_t instr);
@@ -70,26 +72,57 @@
const Label::LabelEmitOperator& op);
public:
+ class AllowUnpredictableScope {
+ Assembler* assembler_;
+ bool old_;
+
+ public:
+ explicit AllowUnpredictableScope(Assembler* assembler)
+ : assembler_(assembler), old_(assembler->allow_unpredictable_) {
+ assembler_->allow_unpredictable_ = true;
+ }
+ ~AllowUnpredictableScope() { assembler_->allow_unpredictable_ = old_; }
+ };
+ class AllowStronglyDiscouragedScope {
+ Assembler* assembler_;
+ bool old_;
+
+ public:
+ explicit AllowStronglyDiscouragedScope(Assembler* assembler)
+ : assembler_(assembler), old_(assembler->allow_strongly_discouraged_) {
+ assembler_->allow_strongly_discouraged_ = true;
+ }
+ ~AllowStronglyDiscouragedScope() {
+ assembler_->allow_strongly_discouraged_ = old_;
+ }
+ };
+
explicit Assembler(InstructionSet isa = A32)
: isa_(isa),
first_condition_(al),
it_mask_(0),
has_32_dregs_(true),
- allow_assembler_(true) {}
+ allow_assembler_(true),
+ allow_unpredictable_(false),
+ allow_strongly_discouraged_(false) {}
explicit Assembler(size_t capacity, InstructionSet isa = A32)
: AssemblerBase(capacity),
isa_(isa),
first_condition_(al),
it_mask_(0),
has_32_dregs_(true),
- allow_assembler_(true) {}
+ allow_assembler_(true),
+ allow_unpredictable_(false),
+ allow_strongly_discouraged_(false) {}
Assembler(byte* buffer, size_t capacity, InstructionSet isa = A32)
: AssemblerBase(buffer, capacity),
isa_(isa),
first_condition_(al),
it_mask_(0),
has_32_dregs_(true),
- allow_assembler_(true) {}
+ allow_assembler_(true),
+ allow_unpredictable_(false),
+ allow_strongly_discouraged_(false) {}
virtual ~Assembler() {}
void UseInstructionSet(InstructionSet isa) {
VIXL_ASSERT((isa_ == isa) || (GetCursorOffset() == 0));
@@ -5641,14 +5674,9 @@
std::string("' instruction.\n"));
VIXL_ABORT_WITH_MSG(error_message.c_str());
}
- virtual bool AllowUnpredictable() {
- VIXL_ABORT_WITH_MSG("Unpredictable instruction.\n");
- return false;
- }
+ virtual bool AllowUnpredictable() { return allow_unpredictable_; }
virtual bool AllowStronglyDiscouraged() {
- VIXL_ABORT_WITH_MSG(
- "ARM strongly recommends to not use this instruction.\n");
- return false;
+ return allow_strongly_discouraged_;
}
};
diff --git a/src/aarch32/macro-assembler-aarch32.cc b/src/aarch32/macro-assembler-aarch32.cc
index c0c8bfb..eb7843a 100644
--- a/src/aarch32/macro-assembler-aarch32.cc
+++ b/src/aarch32/macro-assembler-aarch32.cc
@@ -1854,10 +1854,18 @@
"The MacroAssembler does not convert loads and stores with a PC "
"offset register.\n");
}
- if (rn.IsPC() && addrmode != Offset) {
- VIXL_ABORT_WITH_MSG(
- "The MacroAssembler does not convert loads and stores with a PC "
- "base register in pre-index or post-index mode.\n");
+ if (rn.IsPC()) {
+ if (addrmode == Offset) {
+ if (IsUsingT32()) {
+ VIXL_ABORT_WITH_MSG(
+ "The MacroAssembler does not convert loads and stores with a PC "
+ "base register for T32.\n");
+ }
+ } else {
+ VIXL_ABORT_WITH_MSG(
+ "The MacroAssembler does not convert loads and stores with a PC "
+ "base register in pre-index or post-index mode.\n");
+ }
}
switch (addrmode) {
case PreIndex:
diff --git a/src/aarch32/macro-assembler-aarch32.h b/src/aarch32/macro-assembler-aarch32.h
index 5312928..e0add29 100644
--- a/src/aarch32/macro-assembler-aarch32.h
+++ b/src/aarch32/macro-assembler-aarch32.h
@@ -10666,6 +10666,17 @@
}
void Vsub(VRegister rd, VRegister rn, VRegister rm) { Vsub(al, rd, rn, rm); }
// End of generated code.
+
+ virtual bool AllowUnpredictable() VIXL_OVERRIDE {
+ VIXL_ABORT_WITH_MSG("Unpredictable instruction.\n");
+ return false;
+ }
+ virtual bool AllowStronglyDiscouraged() VIXL_OVERRIDE {
+ VIXL_ABORT_WITH_MSG(
+ "ARM strongly recommends to not use this instruction.\n");
+ return false;
+ }
+
private:
RegisterList available_;
VRegisterList available_vfp_;