From 00d0f4d5ff040ef0fc1def28e9490f159bcfabf1 Mon Sep 17 00:00:00 2001 From: Mat M Date: Fri, 2 Sep 2016 12:32:02 -0400 Subject: [PATCH] load_store: Add correctness checks for STRD variants (#7) STRD doesn't allow the use of the PC in either Rt or Rt2 --- .../translate/translate_arm/load_store.cpp | 42 +++++++++++++++---- .../translate/translate_arm/translate_arm.h | 4 +- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/frontend/translate/translate_arm/load_store.cpp b/src/frontend/translate/translate_arm/load_store.cpp index 58fea0c5..8d9d07ae 100644 --- a/src/frontend/translate/translate_arm/load_store.cpp +++ b/src/frontend/translate/translate_arm/load_store.cpp @@ -589,13 +589,26 @@ bool ArmTranslatorVisitor::arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n return true; } -bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b) { +bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b) { + if (size_t(t) % 2 != 0) + return UnpredictableInstruction(); + + if (!P && W) + return UnpredictableInstruction(); + + const Reg t2 = t + 1; + + if (W && (n == Reg::PC || n == t || n == t2)) + return UnpredictableInstruction(); + + if (t2 == Reg::PC) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.Imm32(imm8a << 4 | imm8b)); const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto value_a = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); - const Reg reg_b = static_cast(std::min(d + 1, Reg::R15)); - const auto value_b = (reg_b == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(reg_b); + const auto value_a = ir.GetRegister(t); + const auto value_b = ir.GetRegister(t2); ir.WriteMemory32(address_a, value_a); ir.WriteMemory32(address_b, value_b); } @@ -603,13 +616,26 @@ bool ArmTranslatorVisitor::arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n return true; } -bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m) { +bool ArmTranslatorVisitor::arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m) { + if (size_t(t) % 2 != 0) + return UnpredictableInstruction(); + + if (!P && W) + return UnpredictableInstruction(); + + const Reg t2 = t + 1; + + if (t2 == Reg::PC || m == Reg::PC) + return UnpredictableInstruction(); + + if (W && (n == Reg::PC || n == t || n == t2)) + return UnpredictableInstruction(); + if (ConditionPassed(cond)) { const auto address_a = GetAddressingMode(ir, P, U, W, n, ir.GetRegister(m)); const auto address_b = ir.Add(address_a, ir.Imm32(4)); - const auto value_a = (d == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(d); - const Reg reg_b = static_cast(std::min(d + 1, Reg::R15)); - const auto value_b = (reg_b == Reg::PC) ? ir.Imm32(ir.PC() - 8) : ir.GetRegister(reg_b); + const auto value_a = ir.GetRegister(t); + const auto value_b = ir.GetRegister(t2); ir.WriteMemory32(address_a, value_a); ir.WriteMemory32(address_b, value_b); } diff --git a/src/frontend/translate/translate_arm/translate_arm.h b/src/frontend/translate/translate_arm/translate_arm.h index 5ab87997..3bf4a014 100644 --- a/src/frontend/translate/translate_arm/translate_arm.h +++ b/src/frontend/translate/translate_arm/translate_arm.h @@ -188,8 +188,8 @@ struct ArmTranslatorVisitor final { bool arm_STR_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); bool arm_STRB_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm12 imm12); bool arm_STRB_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm5 imm5, ShiftType shift, Reg m); - bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b); - bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m); + bool arm_STRD_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Imm4 imm8a, Imm4 imm8b); + bool arm_STRD_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg t, Reg m); bool arm_STRH_imm(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Imm4 imm8a, Imm4 imm8b); bool arm_STRH_reg(Cond cond, bool P, bool U, bool W, Reg n, Reg d, Reg m);