aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/aarch32/assembler-aarch32.cc22
-rw-r--r--src/aarch32/assembler-aarch32.h6
-rw-r--r--test/aarch32/test-disasm-a32.cc36
3 files changed, 54 insertions, 10 deletions
diff --git a/src/aarch32/assembler-aarch32.cc b/src/aarch32/assembler-aarch32.cc
index f3d62753..7e882909 100644
--- a/src/aarch32/assembler-aarch32.cc
+++ b/src/aarch32/assembler-aarch32.cc
@@ -68,8 +68,6 @@ void Assembler::PerformCheckIT(Condition condition) {
VIXL_ASSERT(IsUsingA32() || condition.Is(al));
} else {
VIXL_ASSERT(condition.Is(first_condition_));
- first_condition_ =
- Condition((first_condition_.GetCondition() & 0xe) | (it_mask_ >> 3));
// For A32, AdavanceIT() is not called by the assembler. We must call it
// in order to check that IT instructions are used consistently with
// the following conditional instructions.
@@ -3996,7 +3994,8 @@ void Assembler::crc32b(Condition cond, Register rd, Register rn, Register rm) {
CheckIT(cond);
if (IsUsingT32()) {
// CRC32B{<q>} <Rd>, <Rn>, <Rm> ; T1
- if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
+ if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
+ AllowUnpredictable())) {
EmitT32_32(0xfac0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode());
AdvanceIT();
@@ -4019,7 +4018,8 @@ void Assembler::crc32cb(Condition cond, Register rd, Register rn, Register rm) {
CheckIT(cond);
if (IsUsingT32()) {
// CRC32CB{<q>} <Rd>, <Rn>, <Rm> ; T1
- if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
+ if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
+ AllowUnpredictable())) {
EmitT32_32(0xfad0f080U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode());
AdvanceIT();
@@ -4042,7 +4042,8 @@ void Assembler::crc32ch(Condition cond, Register rd, Register rn, Register rm) {
CheckIT(cond);
if (IsUsingT32()) {
// CRC32CH{<q>} <Rd>, <Rn>, <Rm> ; T1
- if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
+ if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
+ AllowUnpredictable())) {
EmitT32_32(0xfad0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode());
AdvanceIT();
@@ -4065,7 +4066,8 @@ void Assembler::crc32cw(Condition cond, Register rd, Register rn, Register rm) {
CheckIT(cond);
if (IsUsingT32()) {
// CRC32CW{<q>} <Rd>, <Rn>, <Rm> ; T1
- if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
+ if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
+ AllowUnpredictable())) {
EmitT32_32(0xfad0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode());
AdvanceIT();
@@ -4088,7 +4090,8 @@ void Assembler::crc32h(Condition cond, Register rd, Register rn, Register rm) {
CheckIT(cond);
if (IsUsingT32()) {
// CRC32H{<q>} <Rd>, <Rn>, <Rm> ; T1
- if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
+ if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
+ AllowUnpredictable())) {
EmitT32_32(0xfac0f090U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode());
AdvanceIT();
@@ -4111,7 +4114,8 @@ void Assembler::crc32w(Condition cond, Register rd, Register rn, Register rm) {
CheckIT(cond);
if (IsUsingT32()) {
// CRC32W{<q>} <Rd>, <Rn>, <Rm> ; T1
- if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC()) || AllowUnpredictable())) {
+ if (((!rd.IsPC() && !rn.IsPC() && !rm.IsPC() && OutsideITBlock()) ||
+ AllowUnpredictable())) {
EmitT32_32(0xfac0f0a0U | (rd.GetCode() << 8) | (rn.GetCode() << 16) |
rm.GetCode());
AdvanceIT();
@@ -4509,7 +4513,7 @@ void Assembler::hvc(Condition cond, uint32_t imm) {
CheckIT(cond);
if (IsUsingT32()) {
// HVC{<q>} {#}<imm16> ; T1
- if ((imm <= 65535)) {
+ if ((imm <= 65535) && (OutsideITBlock() || AllowUnpredictable())) {
EmitT32_32(0xf7e08000U | (imm & 0xfff) | ((imm & 0xf000) << 4));
AdvanceIT();
return;
diff --git a/src/aarch32/assembler-aarch32.h b/src/aarch32/assembler-aarch32.h
index 9644a882..b748086f 100644
--- a/src/aarch32/assembler-aarch32.h
+++ b/src/aarch32/assembler-aarch32.h
@@ -59,7 +59,11 @@ class Assembler : public internal::AssemblerBase {
#ifdef VIXL_DEBUG
void PerformCheckIT(Condition condition);
#endif
- void AdvanceIT() { it_mask_ = (it_mask_ << 1) & 0xf; }
+ void AdvanceIT() {
+ first_condition_ =
+ Condition((first_condition_.GetCondition() & 0xe) | (it_mask_ >> 3));
+ it_mask_ = (it_mask_ << 1) & 0xf;
+ }
// Virtual, in order to be overridden by the MacroAssembler, which needs to
// notify the pool manager.
virtual void BindHelper(Label* label);
diff --git a/test/aarch32/test-disasm-a32.cc b/test/aarch32/test-disasm-a32.cc
index 99ebe245..2bb22aab 100644
--- a/test/aarch32/test-disasm-a32.cc
+++ b/test/aarch32/test-disasm-a32.cc
@@ -1632,6 +1632,7 @@ TEST(macro_assembler_too_large_immediate) {
CLEANUP();
}
+
TEST(macro_assembler_Cbz) {
SETUP();
@@ -1698,6 +1699,41 @@ TEST(macro_assembler_Cbz) {
}
+#ifdef VIXL_NEGATIVE_TESTING
+TEST(assembler_crc_negative) {
+ SETUP();
+
+ ExactAssemblyScope scope(&masm, 2, CodeBufferCheckScope::kMaximumSize);
+
+ masm.it(eq);
+
+ MUST_FAIL_TEST_T32(crc32b(eq, r0, r1, r2), "Unpredictable instruction.\n");
+ MUST_FAIL_TEST_T32(crc32cb(eq, r0, r1, r2), "Unpredictable instruction.\n");
+ MUST_FAIL_TEST_T32(crc32ch(eq, r0, r1, r2), "Unpredictable instruction.\n");
+ MUST_FAIL_TEST_T32(crc32cw(eq, r0, r1, r2), "Unpredictable instruction.\n");
+ MUST_FAIL_TEST_T32(crc32h(eq, r0, r1, r2), "Unpredictable instruction.\n");
+ MUST_FAIL_TEST_T32(crc32w(eq, r0, r1, r2), "Unpredictable instruction.\n");
+
+ CLEANUP();
+}
+#endif
+
+
+#ifdef VIXL_NEGATIVE_TESTING
+TEST(assembler_hvc_negative) {
+ SETUP();
+
+ ExactAssemblyScope scope(&masm, 2, CodeBufferCheckScope::kMaximumSize);
+
+ masm.it(eq);
+
+ MUST_FAIL_TEST_T32(hvc(eq, 0), "Unpredictable instruction.\n");
+
+ CLEANUP();
+}
+#endif
+
+
TEST(assembler_vldm_vstm_negative) {
SETUP();