refactor: make linter happy
also add a few unused coprocessor instructions Signed-off-by: Amneesh Singh <natto@weirdnatto.in>
This commit is contained in:
		@@ -7,10 +7,10 @@
 | 
			
		||||
using namespace logger;
 | 
			
		||||
 | 
			
		||||
Cpu::Cpu(Bus& bus)
 | 
			
		||||
  : gpr(0)
 | 
			
		||||
  : bus(std::make_shared<Bus>(bus))
 | 
			
		||||
  , gpr({ 0 })
 | 
			
		||||
  , cpsr(0)
 | 
			
		||||
  , spsr(0)
 | 
			
		||||
  , bus(std::make_shared<Bus>(bus))
 | 
			
		||||
  , gpr_banked({ { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 } })
 | 
			
		||||
  , spsr_banked({ 0, 0, 0, 0, 0 }) {
 | 
			
		||||
    cpsr.set_mode(Mode::System);
 | 
			
		||||
@@ -18,20 +18,25 @@ Cpu::Cpu(Bus& bus)
 | 
			
		||||
    cpsr.set_fiq_disabled(true);
 | 
			
		||||
    cpsr.set_state(State::Arm);
 | 
			
		||||
    log_info("CPU successfully initialised");
 | 
			
		||||
 | 
			
		||||
    // PC is always two instructions ahead in the pipeline
 | 
			
		||||
    pc += 2 * ARM_INSTRUCTION_SIZE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* change modes */
 | 
			
		||||
void
 | 
			
		||||
Cpu::chg_mode(Mode from, Mode to) {
 | 
			
		||||
Cpu::chg_mode(const Mode to) {
 | 
			
		||||
    Mode from = cpsr.mode();
 | 
			
		||||
 | 
			
		||||
    if (from == to)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
/* TODO: replace visible registers with view once I understand how to
 | 
			
		||||
 * concatenate views */
 | 
			
		||||
#define STORE_BANKED(mode, MODE)                                               \
 | 
			
		||||
    std::copy(gpr + GPR_##MODE##_BANKED_FIRST,                                 \
 | 
			
		||||
              gpr + GPR_##MODE##_BANKED_FIRST + GPR_##MODE##_BANKED_COUNT,     \
 | 
			
		||||
              gpr_banked.mode)
 | 
			
		||||
    std::copy(gpr.begin() + GPR_##MODE##_FIRST,                                \
 | 
			
		||||
              gpr.begin() + GPR_COUNT - 1,                                     \
 | 
			
		||||
              gpr_banked.mode.begin())
 | 
			
		||||
 | 
			
		||||
    switch (from) {
 | 
			
		||||
        case Mode::Fiq:
 | 
			
		||||
@@ -66,9 +71,9 @@ Cpu::chg_mode(Mode from, Mode to) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define RESTORE_BANKED(mode, MODE)                                             \
 | 
			
		||||
    std::copy(gpr_banked.mode,                                                 \
 | 
			
		||||
              gpr_banked.mode + GPR_##MODE##_BANKED_COUNT,                     \
 | 
			
		||||
              gpr + GPR_##MODE##_BANKED_FIRST)
 | 
			
		||||
    std::copy(gpr_banked.mode.begin(),                                         \
 | 
			
		||||
              gpr_banked.mode.end(),                                           \
 | 
			
		||||
              gpr.begin() + GPR_##MODE##_FIRST)
 | 
			
		||||
 | 
			
		||||
    switch (to) {
 | 
			
		||||
        case Mode::Fiq:
 | 
			
		||||
@@ -109,11 +114,15 @@ Cpu::chg_mode(Mode from, Mode to) {
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
Cpu::step() {
 | 
			
		||||
    uint32_t insn = 0xffffffff;
 | 
			
		||||
    uint32_t cur_pc = pc - 2 * ARM_INSTRUCTION_SIZE;
 | 
			
		||||
 | 
			
		||||
    if (cpsr.state() == State::Arm) {
 | 
			
		||||
        std::string disassembled = exec_arm(insn);
 | 
			
		||||
        log_info("{:#010X} : {}", gpr[15], disassembled);
 | 
			
		||||
        gpr[15] += ARM_INSTRUCTION_SIZE;
 | 
			
		||||
        log_info("{:#034b}", bus->read_word(cur_pc));
 | 
			
		||||
 | 
			
		||||
        std::string disassembled = exec_arm(bus->read_word(cur_pc));
 | 
			
		||||
 | 
			
		||||
        log_info("{:#010X} : {}", cur_pc, disassembled);
 | 
			
		||||
 | 
			
		||||
        pc += ARM_INSTRUCTION_SIZE;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,40 +13,32 @@ class Cpu {
 | 
			
		||||
    void step();
 | 
			
		||||
 | 
			
		||||
  private:
 | 
			
		||||
    static constexpr size_t GPR_FIQ_BANKED_FIRST = 8;
 | 
			
		||||
    static constexpr size_t GPR_FIQ_BANKED_COUNT = 7;
 | 
			
		||||
    static constexpr size_t GPR_COUNT = 16;
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t GPR_SVC_BANKED_FIRST = 13;
 | 
			
		||||
    static constexpr size_t GPR_SVC_BANKED_COUNT = 2;
 | 
			
		||||
    static constexpr size_t GPR_FIQ_FIRST     = 8;
 | 
			
		||||
    static constexpr size_t GPR_SVC_FIRST     = 13;
 | 
			
		||||
    static constexpr size_t GPR_ABT_FIRST     = 13;
 | 
			
		||||
    static constexpr size_t GPR_IRQ_FIRST     = 13;
 | 
			
		||||
    static constexpr size_t GPR_UND_FIRST     = 13;
 | 
			
		||||
    static constexpr size_t GPR_SYS_USR_FIRST = 8;
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t GPR_ABT_BANKED_FIRST = 13;
 | 
			
		||||
    static constexpr size_t GPR_ABT_BANKED_COUNT = 2;
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t GPR_IRQ_BANKED_FIRST = 13;
 | 
			
		||||
    static constexpr size_t GPR_IRQ_BANKED_COUNT = 2;
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t GPR_UND_BANKED_FIRST = 13;
 | 
			
		||||
    static constexpr size_t GPR_UND_BANKED_COUNT = 2;
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t GPR_SYS_USR_BANKED_FIRST = 8;
 | 
			
		||||
    static constexpr size_t GPR_SYS_USR_BANKED_COUNT = 7;
 | 
			
		||||
 | 
			
		||||
    static constexpr size_t GPR_VISIBLE_COUNT = 16;
 | 
			
		||||
 | 
			
		||||
    uint32_t gpr[GPR_VISIBLE_COUNT]; // general purpose registers
 | 
			
		||||
    Psr cpsr;                        // current program status register
 | 
			
		||||
    Psr spsr;                        // status program status register
 | 
			
		||||
    std::shared_ptr<Bus> bus;
 | 
			
		||||
    std::array<uint32_t, GPR_COUNT> gpr; // general purpose registers
 | 
			
		||||
 | 
			
		||||
    Psr cpsr; // current program status register
 | 
			
		||||
    Psr spsr; // status program status register
 | 
			
		||||
 | 
			
		||||
    uint32_t& pc = gpr[15];
 | 
			
		||||
 | 
			
		||||
    struct {
 | 
			
		||||
        uint32_t fiq[GPR_FIQ_BANKED_COUNT];
 | 
			
		||||
        uint32_t svc[GPR_SVC_BANKED_COUNT];
 | 
			
		||||
        uint32_t abt[GPR_ABT_BANKED_COUNT];
 | 
			
		||||
        uint32_t irq[GPR_IRQ_BANKED_COUNT];
 | 
			
		||||
        uint32_t und[GPR_UND_BANKED_COUNT];
 | 
			
		||||
        std::array<uint32_t, GPR_COUNT - GPR_FIQ_FIRST - 1> fiq;
 | 
			
		||||
        std::array<uint32_t, GPR_COUNT - GPR_SVC_FIRST - 1> svc;
 | 
			
		||||
        std::array<uint32_t, GPR_COUNT - GPR_ABT_FIRST - 1> abt;
 | 
			
		||||
        std::array<uint32_t, GPR_COUNT - GPR_IRQ_FIRST - 1> irq;
 | 
			
		||||
        std::array<uint32_t, GPR_COUNT - GPR_UND_FIRST - 1> und;
 | 
			
		||||
 | 
			
		||||
        // visible registers before the mode switch
 | 
			
		||||
        uint32_t old[GPR_SYS_USR_BANKED_COUNT];
 | 
			
		||||
        std::array<uint32_t, GPR_COUNT - GPR_SYS_USR_FIRST> old;
 | 
			
		||||
    } gpr_banked; // banked general purpose registers
 | 
			
		||||
 | 
			
		||||
    struct {
 | 
			
		||||
@@ -57,6 +49,6 @@ class Cpu {
 | 
			
		||||
        Psr und;
 | 
			
		||||
    } spsr_banked; // banked saved program status registers
 | 
			
		||||
 | 
			
		||||
    void chg_mode(Mode from, Mode to);
 | 
			
		||||
    std::string exec_arm(uint32_t insn);
 | 
			
		||||
    void chg_mode(const Mode to);
 | 
			
		||||
    std::string exec_arm(const uint32_t insn);
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -5,25 +5,27 @@
 | 
			
		||||
#include <cstdint>
 | 
			
		||||
 | 
			
		||||
using namespace logger;
 | 
			
		||||
using std::array;
 | 
			
		||||
using stringv = std::string_view;
 | 
			
		||||
 | 
			
		||||
std::string
 | 
			
		||||
Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
Cpu::exec_arm(const uint32_t insn) {
 | 
			
		||||
    Condition cond = static_cast<Condition>(get_bit_range(insn, 28, 31));
 | 
			
		||||
    std::string disassembled;
 | 
			
		||||
 | 
			
		||||
    auto pc_error = [](uint8_t r, const char* syn) {
 | 
			
		||||
    auto pc_error = [](uint8_t r, stringv syn) {
 | 
			
		||||
        if (r == 15)
 | 
			
		||||
            log_error("Using PC (R15) as operand in {}", syn);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    auto pc_undefined = [](uint8_t r, const char* syn) {
 | 
			
		||||
    auto pc_undefined = [](uint8_t r, stringv syn) {
 | 
			
		||||
        if (r == 15)
 | 
			
		||||
            log_warn("Using PC (R15) as operand in {}", syn);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Branch and exhcange
 | 
			
		||||
    if ((insn & 0x0FFFFFF0) == 0x012FFF10) {
 | 
			
		||||
        static constexpr char syn[] = "BX";
 | 
			
		||||
        static constexpr stringv syn = "BX";
 | 
			
		||||
 | 
			
		||||
        uint8_t rn = insn & 0b1111;
 | 
			
		||||
 | 
			
		||||
@@ -38,16 +40,16 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
            cpsr.set_state(state);
 | 
			
		||||
 | 
			
		||||
            // copy to PC
 | 
			
		||||
            gpr[15] = gpr[rn];
 | 
			
		||||
            pc = gpr[rn];
 | 
			
		||||
 | 
			
		||||
            // ignore [1:0] bits for arm and 0 bit for thumb
 | 
			
		||||
            rst_nth_bit(gpr[15], 0);
 | 
			
		||||
            rst_nth_bit(pc, 0);
 | 
			
		||||
            if (state == State::Arm)
 | 
			
		||||
                rst_nth_bit(gpr[15], 1);
 | 
			
		||||
                rst_nth_bit(pc, 1);
 | 
			
		||||
        }
 | 
			
		||||
        // Branch
 | 
			
		||||
    } else if ((insn & 0x0E000000) == 0x0A000000) {
 | 
			
		||||
        static constexpr char syn[] = "B";
 | 
			
		||||
        static constexpr stringv syn = "B";
 | 
			
		||||
 | 
			
		||||
        bool link       = get_nth_bit(insn, 24);
 | 
			
		||||
        uint32_t offset = get_bit_range(insn, 0, 23);
 | 
			
		||||
@@ -63,14 +65,14 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
                offset |= 0xFC000000;
 | 
			
		||||
 | 
			
		||||
            if (link)
 | 
			
		||||
                gpr[14] = gpr[15] - ARM_INSTRUCTION_SIZE;
 | 
			
		||||
                gpr[14] = pc - ARM_INSTRUCTION_SIZE;
 | 
			
		||||
 | 
			
		||||
            gpr[15] += offset;
 | 
			
		||||
            pc += offset - ARM_INSTRUCTION_SIZE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Multiply
 | 
			
		||||
    } else if ((insn & 0x0FC000F0) == 0x00000090) {
 | 
			
		||||
        static constexpr char syn[2][4] = { "MUL", "MLA" };
 | 
			
		||||
        static constexpr array<stringv, 2> syn = { "MUL", "MLA" };
 | 
			
		||||
 | 
			
		||||
        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t rs = get_bit_range(insn, 8, 11);
 | 
			
		||||
@@ -117,8 +119,9 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
        }
 | 
			
		||||
        // Multiply long
 | 
			
		||||
    } else if ((insn & 0x0F8000F0) == 0x00800090) {
 | 
			
		||||
        static constexpr char syn[2][2][6] = { { "SMULL", "SMLAL" },
 | 
			
		||||
                                               { "UMULL", "UMLAL" } };
 | 
			
		||||
        static constexpr array<array<stringv, 2>, 2> syn = {
 | 
			
		||||
            { { "SMULL", "SMLAL" }, { "UMULL", "UMLAL" } }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        uint8_t rm   = get_bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t rs   = get_bit_range(insn, 8, 11);
 | 
			
		||||
@@ -157,7 +160,7 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
                gpr[rdhi] = get_bit_range(eval, 32, 63);
 | 
			
		||||
 | 
			
		||||
            } else {
 | 
			
		||||
                int64_t eval = static_cast<uint64_t>(gpr[rm]) *
 | 
			
		||||
                int64_t eval = static_cast<int64_t>(gpr[rm]) *
 | 
			
		||||
                                 static_cast<int64_t>(gpr[rs]) +
 | 
			
		||||
                               (a ? static_cast<int64_t>(gpr[rdhi]) << 32 |
 | 
			
		||||
                                      static_cast<int64_t>(gpr[rdlo])
 | 
			
		||||
@@ -178,7 +181,7 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
 | 
			
		||||
        // Single data swap
 | 
			
		||||
    } else if ((insn & 0x0FB00FF0) == 0x01000090) {
 | 
			
		||||
        static constexpr char syn[] = "SWP";
 | 
			
		||||
        static constexpr stringv syn = "SWP";
 | 
			
		||||
 | 
			
		||||
        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t rd = get_bit_range(insn, 12, 15);
 | 
			
		||||
@@ -206,32 +209,32 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
        // TODO: create abstraction to reuse for block data and single data
 | 
			
		||||
        // transfer
 | 
			
		||||
    } else if ((insn & 0x0E000090) == 0x00000090) {
 | 
			
		||||
        static constexpr char syn[2][4] = { "STR", "LDR" };
 | 
			
		||||
        static constexpr array<stringv, 2> syn_ = { "STR", "LDR" };
 | 
			
		||||
 | 
			
		||||
        uint8_t rm = get_bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t h  = get_nth_bit(insn, 5);
 | 
			
		||||
        uint8_t s  = get_nth_bit(insn, 6);
 | 
			
		||||
        uint8_t rd = get_bit_range(insn, 12, 15);
 | 
			
		||||
        uint8_t rn = get_bit_range(insn, 16, 19);
 | 
			
		||||
        bool l     = get_nth_bit(insn, 20);
 | 
			
		||||
        bool w     = get_nth_bit(insn, 21);
 | 
			
		||||
        bool imm   = get_nth_bit(insn, 22);
 | 
			
		||||
        bool u     = get_nth_bit(insn, 23);
 | 
			
		||||
        bool p     = get_nth_bit(insn, 24);
 | 
			
		||||
        uint32_t offset;
 | 
			
		||||
        uint8_t rm      = get_bit_range(insn, 0, 3);
 | 
			
		||||
        uint8_t h       = get_nth_bit(insn, 5);
 | 
			
		||||
        uint8_t s       = get_nth_bit(insn, 6);
 | 
			
		||||
        uint8_t rd      = get_bit_range(insn, 12, 15);
 | 
			
		||||
        uint8_t rn      = get_bit_range(insn, 16, 19);
 | 
			
		||||
        bool l          = get_nth_bit(insn, 20);
 | 
			
		||||
        bool w          = get_nth_bit(insn, 21);
 | 
			
		||||
        bool imm        = get_nth_bit(insn, 22);
 | 
			
		||||
        bool u          = get_nth_bit(insn, 23);
 | 
			
		||||
        bool p          = get_nth_bit(insn, 24);
 | 
			
		||||
        uint32_t offset = 0;
 | 
			
		||||
 | 
			
		||||
        std::string syn =
 | 
			
		||||
          fmt::format("{}{}{}", syn_[l], (s ? "S" : ""), (h ? 'H' : 'B'));
 | 
			
		||||
 | 
			
		||||
        if (!p && w)
 | 
			
		||||
            log_error("Write-back enabled with post-indexing in {}", syn[l]);
 | 
			
		||||
            log_error("Write-back enabled with post-indexing in {}", syn);
 | 
			
		||||
 | 
			
		||||
        if (s && !l)
 | 
			
		||||
            log_error("Signed data found in {}", syn[l]);
 | 
			
		||||
            log_error("Signed data found in {}", syn);
 | 
			
		||||
 | 
			
		||||
        if (w)
 | 
			
		||||
            pc_error(rn, syn[l]);
 | 
			
		||||
        pc_error(rm, syn[l]);
 | 
			
		||||
 | 
			
		||||
        if (rd == 15 && !l && s && h)
 | 
			
		||||
            ;
 | 
			
		||||
            pc_error(rn, syn);
 | 
			
		||||
        pc_error(rm, syn);
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            offset = (imm ? get_bit_range(insn, 8, 11) << 4 | rm : gpr[rm]);
 | 
			
		||||
@@ -241,8 +244,8 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
                                                 (imm ? offset : rm));
 | 
			
		||||
 | 
			
		||||
            disassembled = fmt::format(
 | 
			
		||||
              "{}{}{}{} R{:d}{}",
 | 
			
		||||
              syn[l],
 | 
			
		||||
              "{}{}{}{} R{:d},{}",
 | 
			
		||||
              syn_[l],
 | 
			
		||||
              cond,
 | 
			
		||||
              (s ? "S" : ""),
 | 
			
		||||
              (h ? 'H' : 'B'),
 | 
			
		||||
@@ -254,7 +257,10 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cpsr.condition(cond)) {
 | 
			
		||||
            uint32_t address = (u ? gpr[rn] + offset : gpr[rn] - offset);
 | 
			
		||||
            uint32_t address = gpr[rn];
 | 
			
		||||
 | 
			
		||||
            if (p)
 | 
			
		||||
                address += (u ? offset : -offset);
 | 
			
		||||
 | 
			
		||||
            // load
 | 
			
		||||
            if (l) {
 | 
			
		||||
@@ -287,7 +293,92 @@ Cpu::exec_arm(uint32_t insn) {
 | 
			
		||||
                    bus->write_halfword(address, gpr[rd]);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!p)
 | 
			
		||||
                address += (u ? offset : -offset);
 | 
			
		||||
 | 
			
		||||
            if (!p || w)
 | 
			
		||||
                gpr[rn] = address;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Software Interrupt
 | 
			
		||||
        // What to do here?
 | 
			
		||||
    } else if ((insn & 0x0F000000) == 0x0F000000) {
 | 
			
		||||
        static constexpr stringv syn = "SWI";
 | 
			
		||||
 | 
			
		||||
        if (cpsr.condition(cond)) {
 | 
			
		||||
            chg_mode(Mode::Supervisor);
 | 
			
		||||
            pc   = 0x08;
 | 
			
		||||
            spsr = cpsr;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        disassembled = fmt::format("{}{} 0", syn, cond);
 | 
			
		||||
 | 
			
		||||
        // Coprocessor data transfer
 | 
			
		||||
    } else if ((insn & 0x0E000000) == 0x0C000000) {
 | 
			
		||||
        static constexpr array<stringv, 2> syn = { "STC", "LDC" };
 | 
			
		||||
 | 
			
		||||
        [[maybe_unused]] uint8_t offset = get_bit_range(insn, 0, 7);
 | 
			
		||||
        uint8_t cpn                     = get_bit_range(insn, 8, 11);
 | 
			
		||||
        uint8_t crd                     = get_bit_range(insn, 12, 15);
 | 
			
		||||
        [[maybe_unused]] uint8_t rn     = get_bit_range(insn, 16, 19);
 | 
			
		||||
        bool l                          = get_nth_bit(insn, 20);
 | 
			
		||||
        [[maybe_unused]] bool w         = get_nth_bit(insn, 21);
 | 
			
		||||
        bool n                          = get_nth_bit(insn, 22);
 | 
			
		||||
        [[maybe_unused]] bool u         = get_nth_bit(insn, 23);
 | 
			
		||||
        [[maybe_unused]] bool p         = get_nth_bit(insn, 24);
 | 
			
		||||
 | 
			
		||||
        disassembled = fmt::format(
 | 
			
		||||
          "{}{}{} p{},c{},{}", syn[l], cond, (n ? "L" : ""), cpn, crd, "a.");
 | 
			
		||||
 | 
			
		||||
        log_error("Unimplemented instruction: {}", syn[l]);
 | 
			
		||||
 | 
			
		||||
        // Coprocessor data operation
 | 
			
		||||
    } else if ((insn & 0x0F000010) == 0x0E000000) {
 | 
			
		||||
        static constexpr stringv syn = "CDP";
 | 
			
		||||
 | 
			
		||||
        uint8_t crm    = get_bit_range(insn, 0, 4);
 | 
			
		||||
        uint8_t cp     = get_bit_range(insn, 5, 7);
 | 
			
		||||
        uint8_t cpn    = get_bit_range(insn, 8, 11);
 | 
			
		||||
        uint8_t crd    = get_bit_range(insn, 12, 15);
 | 
			
		||||
        uint8_t crn    = get_bit_range(insn, 16, 19);
 | 
			
		||||
        uint8_t cp_opc = get_bit_range(insn, 20, 23);
 | 
			
		||||
 | 
			
		||||
        disassembled = fmt::format("{}{} p{},{},c{},c{},c{},{}",
 | 
			
		||||
                                   syn,
 | 
			
		||||
                                   cond,
 | 
			
		||||
                                   cpn,
 | 
			
		||||
                                   cp_opc,
 | 
			
		||||
                                   crd,
 | 
			
		||||
                                   crn,
 | 
			
		||||
                                   crm,
 | 
			
		||||
                                   cp);
 | 
			
		||||
 | 
			
		||||
        log_error("Unimplemented instruction: {}", syn);
 | 
			
		||||
 | 
			
		||||
        // Coprocessor register transfer
 | 
			
		||||
    } else if ((insn & 0x0F000010) == 0x0E000010) {
 | 
			
		||||
        static constexpr array<stringv, 2> syn = { "MCR", "MRC" };
 | 
			
		||||
 | 
			
		||||
        uint8_t crm    = get_bit_range(insn, 0, 4);
 | 
			
		||||
        uint8_t cp     = get_bit_range(insn, 5, 7);
 | 
			
		||||
        uint8_t cpn    = get_bit_range(insn, 8, 11);
 | 
			
		||||
        uint8_t rd     = get_bit_range(insn, 12, 15);
 | 
			
		||||
        uint8_t crn    = get_bit_range(insn, 16, 19);
 | 
			
		||||
        bool l         = get_nth_bit(insn, 20);
 | 
			
		||||
        uint8_t cp_opc = get_bit_range(insn, 21, 23);
 | 
			
		||||
 | 
			
		||||
        disassembled = fmt::format("{}{} p{},{},c{},c{},c{},{}",
 | 
			
		||||
                                   syn[l],
 | 
			
		||||
                                   cond,
 | 
			
		||||
                                   cpn,
 | 
			
		||||
                                   cp_opc,
 | 
			
		||||
                                   rd,
 | 
			
		||||
                                   crn,
 | 
			
		||||
                                   crm,
 | 
			
		||||
                                   cp);
 | 
			
		||||
 | 
			
		||||
        log_error("Unimplemented instruction: {}", syn[l]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return disassembled;
 | 
			
		||||
 
 | 
			
		||||
@@ -2,9 +2,8 @@
 | 
			
		||||
#include "util/bits.hh"
 | 
			
		||||
#include "util/log.hh"
 | 
			
		||||
 | 
			
		||||
Psr::Psr(uint32_t raw) {
 | 
			
		||||
    psr = raw & PSR_CLEAR_RESERVED;
 | 
			
		||||
}
 | 
			
		||||
Psr::Psr(uint32_t raw)
 | 
			
		||||
  : psr(raw & PSR_CLEAR_RESERVED) {}
 | 
			
		||||
 | 
			
		||||
Mode
 | 
			
		||||
Psr::mode() const {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,3 +32,23 @@ operator<<(std::ostream& os, const Condition cond) {
 | 
			
		||||
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::ostream&
 | 
			
		||||
operator<<(std::ostream& os, const ShiftType shift_type) {
 | 
			
		||||
 | 
			
		||||
#define CASE(type)                                                             \
 | 
			
		||||
    case ShiftType::type:                                                      \
 | 
			
		||||
        os << #type;                                                           \
 | 
			
		||||
        break;
 | 
			
		||||
 | 
			
		||||
    switch (shift_type) {
 | 
			
		||||
        CASE(LSL)
 | 
			
		||||
        CASE(LSR)
 | 
			
		||||
        CASE(ASR)
 | 
			
		||||
        CASE(ROR)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#undef CASE
 | 
			
		||||
 | 
			
		||||
    return os;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,12 @@ enum class Condition {
 | 
			
		||||
    AL = 0b1110
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// https://fmt.dev/dev/api.html#std-ostream-support
 | 
			
		||||
std::ostream&
 | 
			
		||||
operator<<(std::ostream& os, const Condition cond);
 | 
			
		||||
template<>
 | 
			
		||||
struct fmt::formatter<Condition> : ostream_formatter {};
 | 
			
		||||
 | 
			
		||||
enum class OpCode {
 | 
			
		||||
    AND = 0b0000,
 | 
			
		||||
    EOR = 0b0001,
 | 
			
		||||
@@ -68,6 +74,6 @@ enum class ShiftType {
 | 
			
		||||
 | 
			
		||||
// https://fmt.dev/dev/api.html#std-ostream-support
 | 
			
		||||
std::ostream&
 | 
			
		||||
operator<<(std::ostream& os, const Condition cond);
 | 
			
		||||
operator<<(std::ostream& os, const ShiftType cond);
 | 
			
		||||
template<>
 | 
			
		||||
struct fmt::formatter<Condition> : ostream_formatter {};
 | 
			
		||||
struct fmt::formatter<ShiftType> : ostream_formatter {};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user