From 6bf388ddc1e1050141b7163df9d7e5ccde4959c8 Mon Sep 17 00:00:00 2001 From: Pierre Langlois Date: Wed, 15 Feb 2017 13:34:38 +0000 Subject: Add unpredictable checks mis-uses of PC in aliases Add checks for mis-use of PC in the following alias instructions: - ASR{S} - LSL{S} - LSR{S} - ROR{S} - RRX{S} - POP - PUSH - SUB (alias ADR) Change-Id: Ibfd8d1be6841e9e8a12ffd5cf015b6de6bc9eacd --- src/aarch32/assembler-aarch32.cc | 96 ++++++++++++++++++++++++++-------------- test/aarch32/test-disasm-a32.cc | 9 +--- 2 files changed, 65 insertions(+), 40 deletions(-) diff --git a/src/aarch32/assembler-aarch32.cc b/src/aarch32/assembler-aarch32.cc index 14f4bcbf..93b5c037 100644 --- a/src/aarch32/assembler-aarch32.cc +++ b/src/aarch32/assembler-aarch32.cc @@ -2721,7 +2721,8 @@ void Assembler::asr(Condition cond, return; } // ASR{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { uint32_t amount_ = imm % 32; EmitT32_32(0xea4f0020U | (rd.GetCode() << 8) | rm.GetCode() | ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10)); @@ -2749,7 +2750,8 @@ void Assembler::asr(Condition cond, return; } // ASR{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa40f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -2757,7 +2759,8 @@ void Assembler::asr(Condition cond, } } else { // ASR{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01a00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -2787,7 +2790,8 @@ void Assembler::asrs(Condition cond, return; } // ASRS{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { uint32_t amount_ = imm % 32; EmitT32_32(0xea5f0020U | (rd.GetCode() << 8) | rm.GetCode() | ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10)); @@ -2815,7 +2819,8 @@ void Assembler::asrs(Condition cond, return; } // ASRS{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa50f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -2823,7 +2828,8 @@ void Assembler::asrs(Condition cond, } } else { // ASRS{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01b00050U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -6226,7 +6232,8 @@ void Assembler::lsl(Condition cond, return; } // LSL{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xea4f0000U | (rd.GetCode() << 8) | rm.GetCode() | ((imm & 0x3) << 6) | ((imm & 0x1c) << 10)); AdvanceIT(); @@ -6252,7 +6259,8 @@ void Assembler::lsl(Condition cond, return; } // LSL{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa00f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -6260,7 +6268,8 @@ void Assembler::lsl(Condition cond, } } else { // LSL{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01a00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -6288,7 +6297,8 @@ void Assembler::lsls(Condition cond, return; } // LSLS{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xea5f0000U | (rd.GetCode() << 8) | rm.GetCode() | ((imm & 0x3) << 6) | ((imm & 0x1c) << 10)); AdvanceIT(); @@ -6314,7 +6324,8 @@ void Assembler::lsls(Condition cond, return; } // LSLS{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa10f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -6322,7 +6333,8 @@ void Assembler::lsls(Condition cond, } } else { // LSLS{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01b00010U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -6352,7 +6364,8 @@ void Assembler::lsr(Condition cond, return; } // LSR{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { uint32_t amount_ = imm % 32; EmitT32_32(0xea4f0010U | (rd.GetCode() << 8) | rm.GetCode() | ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10)); @@ -6380,7 +6393,8 @@ void Assembler::lsr(Condition cond, return; } // LSR{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa20f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -6388,7 +6402,8 @@ void Assembler::lsr(Condition cond, } } else { // LSR{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01a00030U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -6418,7 +6433,8 @@ void Assembler::lsrs(Condition cond, return; } // LSRS{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 32)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 32) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { uint32_t amount_ = imm % 32; EmitT32_32(0xea5f0010U | (rd.GetCode() << 8) | rm.GetCode() | ((amount_ & 0x3) << 6) | ((amount_ & 0x1c) << 10)); @@ -6446,7 +6462,8 @@ void Assembler::lsrs(Condition cond, return; } // LSRS{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa30f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -6454,7 +6471,8 @@ void Assembler::lsrs(Condition cond, } } else { // LSRS{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01b00030U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -7943,7 +7961,8 @@ void Assembler::pop(Condition cond, EncodingSize size, Register rt) { CheckIT(cond); if (IsUsingT32()) { // POP{}{} ; T4 - if (!size.IsNarrow() && (!rt.IsPC() || OutsideITBlockAndAlOrLast(cond))) { + if (!size.IsNarrow() && ((!rt.IsPC() || OutsideITBlockAndAlOrLast(cond)) || + AllowUnpredictable())) { EmitT32_32(0xf85d0b04U | (rt.GetCode() << 12)); AdvanceIT(); return; @@ -7995,7 +8014,7 @@ void Assembler::push(Condition cond, EncodingSize size, Register rt) { CheckIT(cond); if (IsUsingT32()) { // PUSH{}{} ; T4 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && (!rt.IsPC() || AllowUnpredictable())) { EmitT32_32(0xf84d0d04U | (rt.GetCode() << 12)); AdvanceIT(); return; @@ -8373,7 +8392,8 @@ void Assembler::ror(Condition cond, uint32_t imm = operand.GetImmediate(); if (IsUsingT32()) { // ROR{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode() | ((imm & 0x3) << 6) | ((imm & 0x1c) << 10)); AdvanceIT(); @@ -8399,7 +8419,8 @@ void Assembler::ror(Condition cond, return; } // ROR{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa60f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -8407,7 +8428,8 @@ void Assembler::ror(Condition cond, } } else { // ROR{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01a00070U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -8428,7 +8450,8 @@ void Assembler::rors(Condition cond, uint32_t imm = operand.GetImmediate(); if (IsUsingT32()) { // RORS{}{} {}, , # ; T3 - if (!size.IsNarrow() && (imm >= 1) && (imm <= 31)) { + if (!size.IsNarrow() && (imm >= 1) && (imm <= 31) && + ((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode() | ((imm & 0x3) << 6) | ((imm & 0x1c) << 10)); AdvanceIT(); @@ -8454,7 +8477,8 @@ void Assembler::rors(Condition cond, return; } // RORS{}{} {}, , ; T2 - if (!size.IsNarrow()) { + if (!size.IsNarrow() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitT32_32(0xfa70f000U | (rd.GetCode() << 8) | (rm.GetCode() << 16) | rs.GetCode()); AdvanceIT(); @@ -8462,7 +8486,8 @@ void Assembler::rors(Condition cond, } } else { // RORS{}{} {}, , ; A1 - if (cond.IsNotNever()) { + if (cond.IsNotNever() && + ((!rd.IsPC() && !rm.IsPC() && !rs.IsPC()) || AllowUnpredictable())) { EmitA32(0x01b00070U | (cond.GetCondition() << 28) | (rd.GetCode() << 12) | rm.GetCode() | (rs.GetCode() << 8)); return; @@ -8477,9 +8502,11 @@ void Assembler::rrx(Condition cond, Register rd, Register rm) { CheckIT(cond); if (IsUsingT32()) { // RRX{}{} {}, ; T3 - EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode()); - AdvanceIT(); - return; + if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { + EmitT32_32(0xea4f0030U | (rd.GetCode() << 8) | rm.GetCode()); + AdvanceIT(); + return; + } } else { // RRX{}{} {}, ; A1 if (cond.IsNotNever()) { @@ -8496,9 +8523,11 @@ void Assembler::rrxs(Condition cond, Register rd, Register rm) { CheckIT(cond); if (IsUsingT32()) { // RRXS{}{} {}, ; T3 - EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode()); - AdvanceIT(); - return; + if (((!rd.IsPC() && !rm.IsPC()) || AllowUnpredictable())) { + EmitT32_32(0xea5f0030U | (rd.GetCode() << 8) | rm.GetCode()); + AdvanceIT(); + return; + } } else { // RRXS{}{} {}, ; A1 if (cond.IsNotNever()) { @@ -11545,7 +11574,8 @@ void Assembler::sub(Condition cond, return; } // SUB{}{} , PC, # ; T2 - if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095)) { + if (!size.IsNarrow() && rn.Is(pc) && (imm <= 4095) && + (!rd.IsPC() || AllowUnpredictable())) { EmitT32_32(0xf2af0000U | (rd.GetCode() << 8) | (imm & 0xff) | ((imm & 0x700) << 4) | ((imm & 0x800) << 15)); AdvanceIT(); diff --git a/test/aarch32/test-disasm-a32.cc b/test/aarch32/test-disasm-a32.cc index a40029cd..b5b41ce5 100644 --- a/test/aarch32/test-disasm-a32.cc +++ b/test/aarch32/test-disasm-a32.cc @@ -2137,10 +2137,7 @@ TEST(macro_assembler_PushRegisterList) { // Deprecated, but accepted: SHOULD_FAIL_TEST_A32(Push(RegisterList(pc))); // Whereas we don't accept the single-register version: - MUST_FAIL_TEST_A32(Push(pc), "Unpredictable instruction.\n"); - - // For T32, pushing the PC is allowed: - COMPARE_T32(Push(pc), "push {pc}\n"); + MUST_FAIL_TEST_BOTH(Push(pc), "Unpredictable instruction.\n"); // Accepted, but stores UNKNOWN value for the SP: SHOULD_FAIL_TEST_A32(Push(RegisterList(r0, sp))); @@ -3292,9 +3289,7 @@ TEST(macro_assembler_T32_IT) { "bne 0x00000006\n" "sub r7, sp, #1\n"); - COMPARE_T32(Sub(eq, pc, pc, 0), - "bne 0x00000006\n" - "sub pc, #0\n"); + MUST_FAIL_TEST_T32(Sub(eq, pc, pc, 0), "Unpredictable instruction.\n"); // TST (register) T1 COMPARE_T32(Tst(eq, r0, r1), -- cgit v1.2.3