From 6c33c77ef3d484e7af3eea0530ef39ddf7b10aca Mon Sep 17 00:00:00 2001 From: Amneesh Singh Date: Sat, 23 Sep 2023 14:12:53 +0530 Subject: [PATCH] restructure: get rid of cpu/utility Signed-off-by: Amneesh Singh --- src/cpu/{utility.cc => alu.cc} | 70 +--------------------- src/cpu/alu.hh | 35 +++++++++++ src/cpu/arm/exec.cc | 4 +- src/cpu/arm/instruction.cc | 37 +++++++++++- src/cpu/arm/instruction.hh | 36 +++++++++++- src/cpu/cpu-impl.cc | 1 - src/cpu/meson.build | 2 +- src/cpu/psr.cc | 39 +++++++++++-- src/cpu/psr.hh | 48 ++++++++++++++- src/cpu/utility.hh | 103 --------------------------------- tests/cpu/arm/exec.cc | 7 ++- tests/cpu/arm/instruction.cc | 6 +- 12 files changed, 197 insertions(+), 191 deletions(-) rename src/cpu/{utility.cc => alu.cc} (56%) create mode 100644 src/cpu/alu.hh delete mode 100644 src/cpu/utility.hh diff --git a/src/cpu/utility.cc b/src/cpu/alu.cc similarity index 56% rename from src/cpu/utility.cc rename to src/cpu/alu.cc index c5ff3ad..3131929 100644 --- a/src/cpu/utility.cc +++ b/src/cpu/alu.cc @@ -1,74 +1,7 @@ -#include "utility.hh" +#include "alu.hh" #include "util/bits.hh" -#include namespace matar { -namespace arm { -std::ostream& -operator<<(std::ostream& os, const Condition cond) { - -#define CASE(cond) \ - case Condition::cond: \ - os << #cond; \ - break; - - switch (cond) { - CASE(EQ) - CASE(NE) - CASE(CS) - CASE(CC) - CASE(MI) - CASE(PL) - CASE(VS) - CASE(VC) - CASE(HI) - CASE(LS) - CASE(GE) - CASE(LT) - CASE(GT) - CASE(LE) - case Condition::AL: { - // empty - } - } - -#undef CASE - - return os; -} - -std::ostream& -operator<<(std::ostream& os, const OpCode opcode) { - -#define CASE(opcode) \ - case OpCode::opcode: \ - os << #opcode; \ - break; - - switch (opcode) { - CASE(AND) - CASE(EOR) - CASE(SUB) - CASE(RSB) - CASE(ADD) - CASE(ADC) - CASE(SBC) - CASE(RSC) - CASE(TST) - CASE(TEQ) - CASE(CMP) - CASE(CMN) - CASE(ORR) - CASE(MOV) - CASE(BIC) - CASE(MVN) - } - -#undef CASE - - return os; -} - uint32_t eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry) { uint32_t eval = 0; @@ -136,4 +69,3 @@ operator<<(std::ostream& os, const ShiftType shift_type) { return os; } } -} diff --git a/src/cpu/alu.hh b/src/cpu/alu.hh new file mode 100644 index 0000000..883a877 --- /dev/null +++ b/src/cpu/alu.hh @@ -0,0 +1,35 @@ +#pragma once +#include +#include + +namespace matar { +enum class ShiftType { + LSL = 0b00, + LSR = 0b01, + ASR = 0b10, + ROR = 0b11 +}; + +struct ShiftData { + ShiftType type; + bool immediate; + uint8_t operand; +}; + +struct Shift { + uint8_t rm; + ShiftData data; +}; + +uint32_t +eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry); + +// https://fmt.dev/dev/api.html#std-ostream-support +std::ostream& +operator<<(std::ostream& os, const ShiftType cond); +} + +namespace fmt { +template<> +struct formatter : ostream_formatter {}; +} diff --git a/src/cpu/arm/exec.cc b/src/cpu/arm/exec.cc index 80b7656..9af0251 100644 --- a/src/cpu/arm/exec.cc +++ b/src/cpu/arm/exec.cc @@ -7,7 +7,7 @@ using namespace logger; namespace matar { void CpuImpl::exec_arm(const arm::Instruction instruction) { - arm::Condition cond = instruction.condition; + Condition cond = instruction.condition; arm::InstructionData data = instruction.data; debug(cpsr.condition(cond)); @@ -387,6 +387,8 @@ CpuImpl::exec_arm(const arm::Instruction instruction) { } }, [this, pc_error](DataProcessing& data) { + using OpCode = DataProcessing::OpCode; + uint32_t op_1 = gpr[data.rn]; uint32_t op_2 = 0; diff --git a/src/cpu/arm/instruction.cc b/src/cpu/arm/instruction.cc index 6d5f8d4..b0f6478 100644 --- a/src/cpu/arm/instruction.cc +++ b/src/cpu/arm/instruction.cc @@ -1,5 +1,4 @@ #include "instruction.hh" -#include "cpu/utility.hh" #include "util/bits.hh" #include @@ -153,6 +152,8 @@ Instruction::Instruction(uint32_t insn) // Data Processing } else if ((insn & 0x0C000000) == 0x00000000) { + using OpCode = DataProcessing::OpCode; + uint8_t rd = bit_range(insn, 12, 15); uint8_t rn = bit_range(insn, 16, 19); bool set = get_bit(insn, 20); @@ -420,6 +421,8 @@ Instruction::disassemble() { } }, [this](DataProcessing& data) { + using OpCode = DataProcessing::OpCode; + std::string op_2; if (const uint32_t* operand = @@ -496,5 +499,37 @@ Instruction::disassemble() { [](auto) { return std::string("unknown instruction"); } }, data); } + +std::ostream& +operator<<(std::ostream& os, const DataProcessing::OpCode opcode) { + +#define CASE(opcode) \ + case DataProcessing::OpCode::opcode: \ + os << #opcode; \ + break; + + switch (opcode) { + CASE(AND) + CASE(EOR) + CASE(SUB) + CASE(RSB) + CASE(ADD) + CASE(ADC) + CASE(SBC) + CASE(RSC) + CASE(TST) + CASE(TEQ) + CASE(CMP) + CASE(CMN) + CASE(ORR) + CASE(MOV) + CASE(BIC) + CASE(MVN) + } + +#undef CASE + + return os; +} } } diff --git a/src/cpu/arm/instruction.hh b/src/cpu/arm/instruction.hh index 8d5fcae..ce5d29c 100644 --- a/src/cpu/arm/instruction.hh +++ b/src/cpu/arm/instruction.hh @@ -1,8 +1,13 @@ #pragma once -#include "cpu/utility.hh" +#include "cpu/alu.hh" +#include "cpu/psr.hh" #include +#include #include +namespace matar { +namespace arm { + template struct overloaded : Ts... { using Ts::operator()...; @@ -10,8 +15,6 @@ struct overloaded : Ts... { template overloaded(Ts...) -> overloaded; -namespace matar { -namespace arm { static constexpr size_t INSTRUCTION_SIZE = 4; struct BranchAndExchange { @@ -84,6 +87,25 @@ struct BlockDataTransfer { }; struct DataProcessing { + enum class OpCode { + AND = 0b0000, + EOR = 0b0001, + SUB = 0b0010, + RSB = 0b0011, + ADD = 0b0100, + ADC = 0b0101, + SBC = 0b0110, + RSC = 0b0111, + TST = 0b1000, + TEQ = 0b1001, + CMP = 0b1010, + CMN = 0b1011, + ORR = 0b1100, + MOV = 0b1101, + BIC = 0b1110, + MVN = 0b1111 + }; + std::variant operand; uint8_t rd; uint8_t rn; @@ -166,5 +188,13 @@ struct Instruction { std::string disassemble(); }; + +std::ostream& +operator<<(std::ostream& os, const DataProcessing::OpCode cond); } } + +namespace fmt { +template<> +struct formatter : ostream_formatter {}; +} diff --git a/src/cpu/cpu-impl.cc b/src/cpu/cpu-impl.cc index 6f14323..948f740 100644 --- a/src/cpu/cpu-impl.cc +++ b/src/cpu/cpu-impl.cc @@ -1,7 +1,6 @@ #include "cpu-impl.hh" #include "util/bits.hh" #include "util/log.hh" -#include "utility.hh" #include #include diff --git a/src/cpu/meson.build b/src/cpu/meson.build index 139497d..8d83065 100644 --- a/src/cpu/meson.build +++ b/src/cpu/meson.build @@ -2,7 +2,7 @@ lib_sources += files( 'cpu-impl.cc', 'cpu.cc', 'psr.cc', - 'utility.cc' + 'alu.cc' ) subdir('arm') \ No newline at end of file diff --git a/src/cpu/psr.cc b/src/cpu/psr.cc index 73a9ec0..51fde21 100644 --- a/src/cpu/psr.cc +++ b/src/cpu/psr.cc @@ -60,9 +60,7 @@ GET_SET_NTH_BIT_FUNCTIONS(n, 31); #undef GET_SET_NTH_BIT_FUNCTIONS bool -Psr::condition(arm::Condition cond) const { - using arm::Condition; - +Psr::condition(Condition cond) const { switch (cond) { case Condition::EQ: return z(); @@ -93,9 +91,42 @@ Psr::condition(arm::Condition cond) const { case Condition::LE: return z() || (n() != v()); case Condition::AL: - return true; + return true && state() == State::Arm; } return false; } + +std::ostream& +operator<<(std::ostream& os, const Condition cond) { + +#define CASE(cond) \ + case Condition::cond: \ + os << #cond; \ + break; + + switch (cond) { + CASE(EQ) + CASE(NE) + CASE(CS) + CASE(CC) + CASE(MI) + CASE(PL) + CASE(VS) + CASE(VC) + CASE(HI) + CASE(LS) + CASE(GE) + CASE(LT) + CASE(GT) + CASE(LE) + case Condition::AL: { + // empty + } + } + +#undef CASE + + return os; +} } diff --git a/src/cpu/psr.hh b/src/cpu/psr.hh index a56087a..8496796 100644 --- a/src/cpu/psr.hh +++ b/src/cpu/psr.hh @@ -1,10 +1,43 @@ #pragma once -#include "arm/instruction.hh" -#include "utility.hh" #include +#include namespace matar { +enum class Mode { + /* M[4:0] in PSR */ + User = 0b10000, + Fiq = 0b10001, + Irq = 0b10010, + Supervisor = 0b10011, + Abort = 0b10111, + Undefined = 0b11011, + System = 0b11111, +}; + +enum class State { + Arm = 0, + Thumb = 1 +}; + +enum class Condition { + EQ = 0b0000, + NE = 0b0001, + CS = 0b0010, + CC = 0b0011, + MI = 0b0100, + PL = 0b0101, + VS = 0b0110, + VC = 0b0111, + HI = 0b1000, + LS = 0b1001, + GE = 0b1010, + LT = 0b1011, + GT = 0b1100, + LE = 0b1101, + AL = 0b1110 +}; + class Psr { public: // clear the reserved bits i.e, [8:27] @@ -47,7 +80,7 @@ class Psr { #undef GET_SET_NTH_BIT_FUNCTIONS - bool condition(arm::Condition cond) const; + bool condition(Condition cond) const; private: static constexpr uint32_t PSR_CLEAR_RESERVED = 0xF00000FF; @@ -55,4 +88,13 @@ class Psr { uint32_t psr; }; + +// https://fmt.dev/dev/api.html#std-ostream-support +std::ostream& +operator<<(std::ostream& os, const Condition cond); +} + +namespace fmt { +template<> +struct formatter : ostream_formatter {}; } diff --git a/src/cpu/utility.hh b/src/cpu/utility.hh deleted file mode 100644 index 626301c..0000000 --- a/src/cpu/utility.hh +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include -#include - -static constexpr size_t THUMB_INSTRUCTION_SIZE = 2; - -namespace matar { -enum class Mode { - /* M[4:0] in PSR */ - User = 0b10000, - Fiq = 0b10001, - Irq = 0b10010, - Supervisor = 0b10011, - Abort = 0b10111, - Undefined = 0b11011, - System = 0b11111, -}; - -enum class State { - Arm = 0, - Thumb = 1 -}; - -namespace arm { -enum class Condition { - EQ = 0b0000, - NE = 0b0001, - CS = 0b0010, - CC = 0b0011, - MI = 0b0100, - PL = 0b0101, - VS = 0b0110, - VC = 0b0111, - HI = 0b1000, - LS = 0b1001, - GE = 0b1010, - LT = 0b1011, - GT = 0b1100, - LE = 0b1101, - AL = 0b1110 -}; - -// https://fmt.dev/dev/api.html#std-ostream-support -std::ostream& -operator<<(std::ostream& os, const Condition cond); - -enum class OpCode { - AND = 0b0000, - EOR = 0b0001, - SUB = 0b0010, - RSB = 0b0011, - ADD = 0b0100, - ADC = 0b0101, - SBC = 0b0110, - RSC = 0b0111, - TST = 0b1000, - TEQ = 0b1001, - CMP = 0b1010, - CMN = 0b1011, - ORR = 0b1100, - MOV = 0b1101, - BIC = 0b1110, - MVN = 0b1111 -}; - -// https://fmt.dev/dev/api.html#std-ostream-support -std::ostream& -operator<<(std::ostream& os, const OpCode cond); - -enum class ShiftType { - LSL = 0b00, - LSR = 0b01, - ASR = 0b10, - ROR = 0b11 -}; - -struct ShiftData { - ShiftType type; - bool immediate; - uint8_t operand; -}; - -struct Shift { - uint8_t rm; - ShiftData data; -}; - -uint32_t -eval_shift(ShiftType shift_type, uint32_t value, uint8_t amount, bool& carry); - -// https://fmt.dev/dev/api.html#std-ostream-support -std::ostream& -operator<<(std::ostream& os, const ShiftType cond); -} -} - -template<> -struct fmt::formatter : ostream_formatter {}; -template<> -struct fmt::formatter : ostream_formatter {}; -template<> -struct fmt::formatter : ostream_formatter {}; diff --git a/tests/cpu/arm/exec.cc b/tests/cpu/arm/exec.cc index 0beaecd..68dd5cb 100644 --- a/tests/cpu/arm/exec.cc +++ b/tests/cpu/arm/exec.cc @@ -1,11 +1,11 @@ #include "cpu/cpu-impl.hh" -#include "cpu/utility.hh" #include "util/bits.hh" #include #include #include using namespace matar; + class CpuFixture { public: CpuFixture() @@ -13,8 +13,7 @@ class CpuFixture { std::vector(Header::HEADER_SIZE)))) {} protected: - void exec(arm::InstructionData data, - arm::Condition condition = arm::Condition::AL) { + void exec(arm::InstructionData data, Condition condition = Condition::AL) { arm::Instruction instruction(condition, data); cpu.exec_arm(instruction); } @@ -746,6 +745,8 @@ TEST_CASE_METHOD(CpuFixture, "PSR Transfer", TAG) { } TEST_CASE_METHOD(CpuFixture, "Data Processing", TAG) { + using OpCode = DataProcessing::OpCode; + InstructionData data = DataProcessing{ .operand = Shift{ .rm = 3, .data = diff --git a/tests/cpu/arm/instruction.cc b/tests/cpu/arm/instruction.cc index bb186e2..010f63e 100644 --- a/tests/cpu/arm/instruction.cc +++ b/tests/cpu/arm/instruction.cc @@ -1,10 +1,10 @@ #include "cpu/arm/instruction.hh" -#include "cpu/utility.hh" #include #define TAG "disassembler" -using namespace matar::arm; +using namespace matar; +using namespace arm; TEST_CASE("Branch and Exchange", TAG) { uint32_t raw = 0b11000001001011111111111100011010; @@ -309,6 +309,8 @@ TEST_CASE("PSR Transfer", TAG) { } TEST_CASE("Data Processing", TAG) { + using OpCode = DataProcessing::OpCode; + uint32_t raw = 0b11100000000111100111101101100001; Instruction instruction(raw); DataProcessing* alu = nullptr;