cpu/{arm|thumb}(chore): change how branch disassembly happens

Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
2024-06-11 23:03:44 +05:30
parent 0062ad424b
commit 15c4802838
10 changed files with 38 additions and 33 deletions

View File

@@ -1,7 +1,6 @@
#include "cpu/arm/instruction.hh"
#include "util/bits.hh"
#include <format>
#include <string>
namespace matar::arm {
std::string
@@ -15,7 +14,10 @@ Instruction::disassemble() {
},
[condition](Branch& data) {
return std::format(
"B{}{} 0x{:06X}", (data.link ? "L" : ""), condition, data.offset);
"B{}{} {:#06x}",
(data.link ? "L" : ""),
condition,
static_cast<int32_t>(data.offset + 2 * INSTRUCTION_SIZE));
},
[condition](Multiply& data) {
if (data.acc) {

View File

@@ -40,17 +40,14 @@ Instruction::exec(Cpu& cpu) {
if (state == State::Arm)
rst_bit(cpu.pc, 1);
// pc is affected so flush the pipeline
// PC is affected so flush the pipeline
cpu.is_flushed = true;
},
[&cpu](Branch& data) {
if (data.link)
cpu.gpr[14] = cpu.pc - INSTRUCTION_SIZE;
// data.offset accounts for two instructions ahead when
// disassembling, so need to adjust
cpu.pc =
static_cast<int32_t>(cpu.pc) - 2 * INSTRUCTION_SIZE + data.offset;
cpu.pc += data.offset;
// pc is affected so flush the pipeline
cpu.is_flushed = true;

View File

@@ -1,6 +1,5 @@
#include "cpu/arm/instruction.hh"
#include "util/bits.hh"
#include <iterator>
namespace matar::arm {
Instruction::Instruction(uint32_t insn)
@@ -13,13 +12,11 @@ Instruction::Instruction(uint32_t insn)
// Branch
} else if ((insn & 0x0E000000) == 0x0A000000) {
bool link = get_bit(insn, 24);
uint32_t offset = bit_range(insn, 0, 23);
bool link = get_bit(insn, 24);
int32_t offset = static_cast<int32_t>(bit_range(insn, 0, 23));
// lsh 2 and sign extend the 26 bit offset to 32 bits
offset = (static_cast<int32_t>(offset) << 8) >> 6;
offset += 2 * INSTRUCTION_SIZE;
offset = (offset << 8) >> 6;
data = Branch{ .link = link, .offset = offset };

View File

@@ -119,9 +119,8 @@ Cpu::chg_mode(const Mode to) {
void
Cpu::step() {
// Current instruction is two instructions behind PC
uint32_t cur_pc = pc - 2 * arm::INSTRUCTION_SIZE;
if (cpsr.state() == State::Arm) {
uint32_t cur_pc = pc - 2 * arm::INSTRUCTION_SIZE;
arm::Instruction instruction(bus->read_word(cur_pc));
#ifdef DISASSEMBLER
@@ -129,12 +128,12 @@ Cpu::step() {
#endif
instruction.exec(*this);
} else {
uint32_t cur_pc = pc - 2 * thumb::INSTRUCTION_SIZE;
thumb::Instruction instruction(bus->read_halfword(cur_pc));
#ifdef DISASSEMBLER
glogger.info("0x{:08X} : {}", cur_pc, instruction.disassemble(cur_pc));
glogger.info("0x{:08X} : {}", cur_pc, instruction.disassemble());
#endif
instruction.exec(*this);

View File

@@ -4,7 +4,7 @@
namespace matar::thumb {
std::string
Instruction::disassemble(uint32_t pc) {
Instruction::disassemble() {
return std::visit(
overloaded{
[](MoveShiftedRegister& data) {
@@ -133,16 +133,16 @@ Instruction::disassemble(uint32_t pc) {
[](SoftwareInterrupt& data) {
return std::format("SWI {:d}", data.vector);
},
[pc](ConditionalBranch& data) {
[](ConditionalBranch& data) {
return std::format(
"B{} #{:d}",
stringify(data.condition),
static_cast<int32_t>(data.offset + pc + 2 * INSTRUCTION_SIZE));
static_cast<int32_t>(data.offset + 2 * INSTRUCTION_SIZE));
},
[pc](UnconditionalBranch& data) {
[](UnconditionalBranch& data) {
return std::format(
"B #{:d}",
static_cast<int32_t>(data.offset + pc + 2 * INSTRUCTION_SIZE));
static_cast<int32_t>(data.offset + 2 * INSTRUCTION_SIZE));
},
[](LongBranchWithLink& data) {
// duh this manual be empty for H = 0