tests: complete disassembler tests
Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
		@@ -116,7 +116,7 @@ Cpu::chg_mode(const Mode to) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
Cpu::exec_arm(const arm::ArmInstruction instruction) {
 | 
			
		||||
Cpu::exec_arm(const arm::Instruction instruction) {
 | 
			
		||||
    auto cond = instruction.condition;
 | 
			
		||||
    auto data = instruction.data;
 | 
			
		||||
 | 
			
		||||
@@ -470,8 +470,8 @@ Cpu::exec_arm(const arm::ArmInstruction instruction) {
 | 
			
		||||
 | 
			
		||||
                    if (cpsr.mode() != Mode::User) {
 | 
			
		||||
                        psr.set_all(gpr[data.operand]);
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case PsrTransfer::Type::Msr_flg:
 | 
			
		||||
                    psr.set_n(get_bit(data.operand, 31));
 | 
			
		||||
                    psr.set_z(get_bit(data.operand, 30));
 | 
			
		||||
@@ -648,7 +648,7 @@ Cpu::exec_arm(const arm::ArmInstruction instruction) {
 | 
			
		||||
            debug(zero);
 | 
			
		||||
            debug(negative);
 | 
			
		||||
 | 
			
		||||
            auto set_conditions = [=]() {
 | 
			
		||||
            auto set_conditions = [this, carry, overflow, negative, zero]() {
 | 
			
		||||
                cpsr.set_c(carry);
 | 
			
		||||
                cpsr.set_v(overflow);
 | 
			
		||||
                cpsr.set_n(negative);
 | 
			
		||||
@@ -693,7 +693,7 @@ Cpu::step() {
 | 
			
		||||
    if (cpsr.state() == State::Arm) {
 | 
			
		||||
        debug(cur_pc);
 | 
			
		||||
        uint32_t x = bus->read_word(cur_pc);
 | 
			
		||||
        arm::ArmInstruction instruction(x);
 | 
			
		||||
        arm::Instruction instruction(x);
 | 
			
		||||
        log_info("{:#034b}", x);
 | 
			
		||||
 | 
			
		||||
        exec_arm(instruction);
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
 | 
			
		||||
using namespace arm;
 | 
			
		||||
 | 
			
		||||
ArmInstruction::ArmInstruction(uint32_t insn)
 | 
			
		||||
Instruction::Instruction(uint32_t insn)
 | 
			
		||||
  : condition(static_cast<Condition>(bit_range(insn, 28, 31))) {
 | 
			
		||||
    // Branch and exhcange
 | 
			
		||||
    if ((insn & 0x0FFFFFF0) == 0x012FFF10) {
 | 
			
		||||
@@ -164,10 +164,9 @@ ArmInstruction::ArmInstruction(uint32_t insn)
 | 
			
		||||
                                .type    = PsrTransfer::Type::Mrs,
 | 
			
		||||
                                .imm     = 0 };
 | 
			
		||||
        } else if ((opcode == OpCode::TEQ || opcode == OpCode::CMN) && !set) {
 | 
			
		||||
            bool imm         = get_bit(insn, 25);
 | 
			
		||||
            uint32_t operand = 0;
 | 
			
		||||
 | 
			
		||||
            if (imm) {
 | 
			
		||||
            if (!imm) {
 | 
			
		||||
                operand = bit_range(insn, 0, 3);
 | 
			
		||||
            } else {
 | 
			
		||||
                uint32_t immediate = bit_range(insn, 0, 7);
 | 
			
		||||
@@ -185,12 +184,11 @@ ArmInstruction::ArmInstruction(uint32_t insn)
 | 
			
		||||
        } else {
 | 
			
		||||
            std::variant<Shift, uint32_t> operand;
 | 
			
		||||
 | 
			
		||||
            if (imm) {
 | 
			
		||||
            if (!imm) {
 | 
			
		||||
                uint32_t immediate = bit_range(insn, 0, 7);
 | 
			
		||||
                uint8_t rotate     = bit_range(insn, 8, 11);
 | 
			
		||||
 | 
			
		||||
                operand = std::rotr(immediate, rotate * 2);
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                uint8_t rm = bit_range(insn, 0, 3);
 | 
			
		||||
                bool reg   = get_bit(insn, 4);
 | 
			
		||||
@@ -240,7 +238,7 @@ ArmInstruction::ArmInstruction(uint32_t insn)
 | 
			
		||||
 | 
			
		||||
        // Coprocessor data operation
 | 
			
		||||
    } else if ((insn & 0x0F000010) == 0x0E000000) {
 | 
			
		||||
        uint8_t crm    = bit_range(insn, 0, 4);
 | 
			
		||||
        uint8_t crm    = bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t cp     = bit_range(insn, 5, 7);
 | 
			
		||||
        uint8_t cpn    = bit_range(insn, 8, 11);
 | 
			
		||||
        uint8_t crd    = bit_range(insn, 12, 15);
 | 
			
		||||
@@ -256,7 +254,7 @@ ArmInstruction::ArmInstruction(uint32_t insn)
 | 
			
		||||
 | 
			
		||||
        // Coprocessor register transfer
 | 
			
		||||
    } else if ((insn & 0x0F000010) == 0x0E000010) {
 | 
			
		||||
        uint8_t crm    = bit_range(insn, 0, 4);
 | 
			
		||||
        uint8_t crm    = bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t cp     = bit_range(insn, 5, 7);
 | 
			
		||||
        uint8_t cpn    = bit_range(insn, 8, 11);
 | 
			
		||||
        uint8_t rd     = bit_range(insn, 12, 15);
 | 
			
		||||
@@ -277,8 +275,7 @@ ArmInstruction::ArmInstruction(uint32_t insn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
ArmInstruction::disassemble() {
 | 
			
		||||
    static const std::string undefined = "UNDEFINED";
 | 
			
		||||
Instruction::disassemble() {
 | 
			
		||||
    // goddamn this is gore
 | 
			
		||||
    // TODO: make this less ugly
 | 
			
		||||
    return std::visit(
 | 
			
		||||
@@ -319,7 +316,7 @@ ArmInstruction::disassemble() {
 | 
			
		||||
                               data.rm,
 | 
			
		||||
                               data.rs);
 | 
			
		||||
        },
 | 
			
		||||
        [](Undefined) { return undefined; },
 | 
			
		||||
        [](Undefined) { return std::string("UND"); },
 | 
			
		||||
        [this](SingleDataSwap& data) {
 | 
			
		||||
            return fmt::format("SWP{}{} R{:d},R{:d},[R{:d}]",
 | 
			
		||||
                               condition,
 | 
			
		||||
@@ -485,7 +482,7 @@ ArmInstruction::disassemble() {
 | 
			
		||||
                               data.cp);
 | 
			
		||||
        },
 | 
			
		||||
        [this](CoprocessorRegisterTransfer& data) {
 | 
			
		||||
            return fmt::format("{}{} p{},{},c{},c{},c{},{}",
 | 
			
		||||
            return fmt::format("{}{} p{},{},R{},c{},c{},{}",
 | 
			
		||||
                               (data.load ? "MRC" : "MCR"),
 | 
			
		||||
                               condition,
 | 
			
		||||
                               data.cpn,
 | 
			
		||||
@@ -495,6 +492,6 @@ ArmInstruction::disassemble() {
 | 
			
		||||
                               data.crm,
 | 
			
		||||
                               data.cp);
 | 
			
		||||
        },
 | 
			
		||||
        [](auto) { return undefined; } },
 | 
			
		||||
        [](auto) { return std::string("unknown instruction"); } },
 | 
			
		||||
      data);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -92,4 +92,6 @@ Psr::condition(Condition cond) const {
 | 
			
		||||
        case Condition::AL:
 | 
			
		||||
            return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -69,6 +69,8 @@ operator<<(std::ostream& os, const OpCode opcode) {
 | 
			
		||||
 | 
			
		||||
uint32_t
 | 
			
		||||
eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry) {
 | 
			
		||||
    uint32_t eval = 0;
 | 
			
		||||
 | 
			
		||||
    switch (shift_type) {
 | 
			
		||||
        case ShiftType::LSL:
 | 
			
		||||
 | 
			
		||||
@@ -77,7 +79,8 @@ eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry) {
 | 
			
		||||
            else if (amount > 32)
 | 
			
		||||
                carry = 0;
 | 
			
		||||
 | 
			
		||||
            return value << amount;
 | 
			
		||||
            eval = value << amount;
 | 
			
		||||
            break;
 | 
			
		||||
        case ShiftType::LSR:
 | 
			
		||||
 | 
			
		||||
            if (amount > 0 && amount <= 32)
 | 
			
		||||
@@ -87,7 +90,8 @@ eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry) {
 | 
			
		||||
            else
 | 
			
		||||
                carry = get_bit(value, 31);
 | 
			
		||||
 | 
			
		||||
            return value >> amount;
 | 
			
		||||
            eval = value >> amount;
 | 
			
		||||
            break;
 | 
			
		||||
        case ShiftType::ASR:
 | 
			
		||||
            if (amount > 0 && amount <= 32)
 | 
			
		||||
                carry = get_bit(value, amount - 1);
 | 
			
		||||
@@ -95,17 +99,21 @@ eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry) {
 | 
			
		||||
                carry = get_bit(value, 31);
 | 
			
		||||
 | 
			
		||||
            return static_cast<int32_t>(value) >> amount;
 | 
			
		||||
            break;
 | 
			
		||||
        case ShiftType::ROR:
 | 
			
		||||
            if (amount == 0) {
 | 
			
		||||
                bool old_carry = carry;
 | 
			
		||||
 | 
			
		||||
                carry = get_bit(value, 0);
 | 
			
		||||
                return (value >> 1) | (old_carry << 31);
 | 
			
		||||
                eval  = (value >> 1) | (old_carry << 31);
 | 
			
		||||
            } else {
 | 
			
		||||
                carry = get_bit(value, (amount % 32 + 31) % 32);
 | 
			
		||||
                return std::rotr(value, amount);
 | 
			
		||||
                eval  = std::rotr(value, amount);
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return eval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::ostream&
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,7 @@ Memory::read(size_t address) const {
 | 
			
		||||
        return rom[address - ROM_2_START];
 | 
			
		||||
    } else {
 | 
			
		||||
        log_error("Invalid memory region accessed");
 | 
			
		||||
        return 0;
 | 
			
		||||
        return 0xFF;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,8 +11,7 @@ lib = library(
 | 
			
		||||
  lib_sources,
 | 
			
		||||
  dependencies: [fmt],
 | 
			
		||||
  include_directories: inc,
 | 
			
		||||
  install: true,
 | 
			
		||||
  cpp_args: '-DFMT_HEADER_ONLY'
 | 
			
		||||
  install: true
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
import('pkgconfig').generate(lib)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user