Skip to content

Commit

Permalink
Added branch_taken_pc and branch_not_taken_pc to BX (#520)
Browse files Browse the repository at this point in the history
* Added branch_taken_pc and branch_not_taken_pc

* Corrected comment

* Added t system reg flag. Still need to check inst.category

* Fixed inst.category in TryDecodeBX
  • Loading branch information
sschriner authored Jun 2, 2021
1 parent e768d25 commit c3d76de
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 10 deletions.
4 changes: 3 additions & 1 deletion include/remill/Arch/AArch32/Runtime/State.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ struct alignas(8) SR final {
uint8_t ioc; // Invalid operation (cumulative).
uint8_t _11;
uint8_t q; // Sticky overflow bit.
uint8_t _12;
uint8_t t; // PSTATE.T = if iset == InstrSet_A32 then '0' else '1'

uint8_t _padding[4];
uint8_t _padding[2];
} __attribute__((packed));

struct alignas(16) State final : public ArchState {
Expand Down
15 changes: 10 additions & 5 deletions lib/Arch/AArch32/Decode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2676,20 +2676,25 @@ static bool TryDecodeBX(Instruction &inst, uint32_t bits) {
AddAddrRegOp(inst, kIntRegName[enc.Rm], kAddressSize, Operand::kActionRead,
0);

inst.branch_not_taken_pc = inst.pc + 4;
if (enc.op1 == 0b01) {
if (is_cond && (enc.Rm == kLRRegNum)) {
inst.category = Instruction::kCategoryConditionalFunctionReturn;
} else if (enc.Rm == kLRRegNum) {
inst.category = Instruction::kCategoryFunctionReturn;
} else if (is_cond) {
inst.category = Instruction::kCategoryConditionalIndirectJump;
} else if (enc.op1 == 0b01) {
} else {
inst.category = Instruction::kCategoryIndirectJump;
}
// BX destination is allowed to be the PC
if (enc.Rm == kPCRegNum) {
inst.branch_taken_pc = inst.pc + 4;
}
} else if (is_cond) {
inst.category = Instruction::kCategoryConditionalDirectFunctionCall;
inst.category = Instruction::kCategoryConditionalIndirectFunctionCall;
} else {
inst.category = Instruction::kCategoryDirectFunctionCall;
inst.category = Instruction::kCategoryIndirectFunctionCall;
}

AddAddrRegOp(inst, kNextPCVariableName.data(), kAddressSize,
Expand Down Expand Up @@ -3460,11 +3465,11 @@ bool AArch32Arch::DecodeInstruction(uint64_t address,
inst.arch = this;
inst.category = Instruction::kCategoryInvalid;
inst.operands.clear();

if (4ull > inst_bytes.size()) {
return false;
}

if (!inst.bytes.empty() && inst.bytes.data() == inst_bytes.data()) {
inst.bytes.resize(inst_bytes.size());
} else {
Expand Down
63 changes: 59 additions & 4 deletions lib/Arch/AArch32/Semantics/BRANCH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,68 @@ DEF_SEM(BLCOND, R8 cond, R8W branch_taken, PC target_addr, PC ret_addr,
Write(branch_taken, c);
return memory;
}

DEF_SEM(BX, R8, R8W, I32 taken_pc, PC next_pc_src, R32W next_pc_dst) {
auto new_pc = Read(taken_pc);
state.sr.t = 1u;
Write(REG_PC, new_pc);
Write(next_pc_dst, new_pc);
(void) next_pc_src;
return memory;
}

DEF_SEM(BXCOND, R8 cond, R8W branch_taken, I32 taken_pc, I32 not_taken_pc,
R32W next_pc_dst) {
auto c = Read(cond);
auto new_pc = Select(c, Read(taken_pc), Read(not_taken_pc));
if (c) {
state.sr.t = 1u;
}
Write(REG_PC, new_pc);
Write(next_pc_dst, new_pc);
Write(branch_taken, c);
return memory;
}

DEF_SEM(BLX, R8, R8W, PC target_addr, PC ret_addr, R32W next_pc_dst,
R32W return_pc_dst) {
const auto return_pc = Read(ret_addr);
const auto new_pc = Read(target_addr);
state.sr.t = 1u;
Write(REG_LR, return_pc);
Write(REG_PC, new_pc);
Write(next_pc_dst, new_pc);
Write(return_pc_dst, return_pc);
return memory;
}

DEF_SEM(BLXCOND, R8 cond, R8W branch_taken, PC target_addr, PC ret_addr,
R32W next_pc_dst, R32W return_pc_dst) {
auto c = Read(cond);
const auto return_pc = Read(ret_addr);
if (c) {
state.sr.t = 1u;
const auto target_pc = Read(target_addr);
Write(REG_LR, return_pc);
Write(REG_PC, target_pc);
Write(next_pc_dst, target_pc);
} else {
Write(REG_PC, return_pc);
Write(next_pc_dst, return_pc);
}
Write(return_pc_dst, return_pc);
Write(branch_taken, c);
return memory;
}


} // namespace

DEF_ISEL(B) = B;
DEF_ISEL(BCOND) = BCOND;
DEF_ISEL(BL) = BL;
DEF_ISEL(BLCOND) = BLCOND;
DEF_ISEL(BLX) = BL;
DEF_ISEL(BLXCOND) = BLCOND;
DEF_ISEL(BX) = B;
DEF_ISEL(BXCOND) = BCOND;
DEF_ISEL(BLX) = BLX;
DEF_ISEL(BLXCOND) = BLXCOND;
DEF_ISEL(BX) = BX;
DEF_ISEL(BXCOND) = BXCOND;

0 comments on commit c3d76de

Please sign in to comment.