diff --git a/InstructionSets/ARM/BarrelShifter.hpp b/InstructionSets/ARM/BarrelShifter.hpp index 36529a16a..449ac3fc1 100644 --- a/InstructionSets/ARM/BarrelShifter.hpp +++ b/InstructionSets/ARM/BarrelShifter.hpp @@ -22,7 +22,7 @@ template <> struct Carry { using type = uint32_t &; }; template <> struct Carry { - using type = uint32_t; + using type = const uint32_t; }; /// Apply a rotation of @c type to @c source of @c amount; @c carry should be either @c 1 or @c 0 diff --git a/InstructionSets/ARM/OperationMapper.hpp b/InstructionSets/ARM/OperationMapper.hpp index 884bac64f..65b834f7e 100644 --- a/InstructionSets/ARM/OperationMapper.hpp +++ b/InstructionSets/ARM/OperationMapper.hpp @@ -17,83 +17,6 @@ enum class Model { ARM2, }; -enum class DataProcessingOperation { - AND, /// Rd = Op1 AND Op2. - EOR, /// Rd = Op1 EOR Op2. - SUB, /// Rd = Op1 - Op2. - RSB, /// Rd = Op2 - Op1. - ADD, /// Rd = Op1 + Op2. - ADC, /// Rd = Op1 + Ord2 + C. - SBC, /// Rd = Op1 - Op2 + C. - RSC, /// Rd = Op2 - Op1 + C. - TST, /// Set condition codes on Op1 AND Op2. - TEQ, /// Set condition codes on Op1 EOR Op2. - CMP, /// Set condition codes on Op1 - Op2. - CMN, /// Set condition codes on Op1 + Op2. - ORR, /// Rd = Op1 OR Op2. - MOV, /// Rd = Op2 - BIC, /// Rd = Op1 AND NOT Op2. - MVN, /// Rd = NOT Op2. -}; - -constexpr bool is_logical(DataProcessingOperation operation) { - switch(operation) { - case DataProcessingOperation::AND: - case DataProcessingOperation::EOR: - case DataProcessingOperation::TST: - case DataProcessingOperation::TEQ: - case DataProcessingOperation::ORR: - case DataProcessingOperation::MOV: - case DataProcessingOperation::BIC: - case DataProcessingOperation::MVN: - return true; - - default: return false; - } -} - -constexpr bool is_comparison(DataProcessingOperation operation) { - switch(operation) { - case DataProcessingOperation::TST: - case DataProcessingOperation::TEQ: - case DataProcessingOperation::CMP: - case DataProcessingOperation::CMN: - return true; - - default: return false; - } -} - -enum class MultiplyOperation { - MUL, /// Rd = Rm * Rs - MLA, /// Rd = Rm * Rs + Rn -}; - -enum class BranchOperation { - B, /// Add offset to PC; programmer allows for PC being two words ahead. - BL, /// Copy PC and PSR to R14, then branch. Copied PC points to next instruction. -}; - -enum class SingleDataTransferOperation { - LDR, /// Read single byte or word from [base + offset], possibly mutating the base. - STR, /// Write a single byte or word to [base + offset], possibly mutating the base. -}; - -enum class BlockDataTransferOperation { - LDM, /// Read 1–16 words from [base], possibly mutating it. - STM, /// Write 1-16 words to [base], possibly mutating it. -}; - -enum class CoprocessorRegisterTransferOperation { - MRC, /// Move from coprocessor register to ARM register. - MCR, /// Move from ARM register to coprocessor register. -}; - -enum class CoprocessorDataTransferOperation { - LDC, /// Coprocessor data transfer load. - STC, /// Coprocessor data transfer store. -}; - enum class Condition { EQ, NE, CS, CC, MI, PL, VS, VC, @@ -140,9 +63,14 @@ protected: struct BranchFlags { constexpr BranchFlags(uint8_t flags) noexcept : flags_(flags) {} + enum class Operation { + B, /// Add offset to PC; programmer allows for PC being two words ahead. + BL, /// Copy PC and PSR to R14, then branch. Copied PC points to next instruction. + }; + /// @returns The operation to apply. - constexpr BranchOperation operation() const { - return flag_bit<24>(flags_) ? BranchOperation::BL : BranchOperation::B; + constexpr Operation operation() const { + return flag_bit<24>(flags_) ? Operation::BL : Operation::B; } private: @@ -162,6 +90,53 @@ private: // // Data processing (i.e. AND to MVN). // +enum class DataProcessingOperation { + AND, /// Rd = Op1 AND Op2. + EOR, /// Rd = Op1 EOR Op2. + SUB, /// Rd = Op1 - Op2. + RSB, /// Rd = Op2 - Op1. + ADD, /// Rd = Op1 + Op2. + ADC, /// Rd = Op1 + Ord2 + C. + SBC, /// Rd = Op1 - Op2 + C. + RSC, /// Rd = Op2 - Op1 + C. + TST, /// Set condition codes on Op1 AND Op2. + TEQ, /// Set condition codes on Op1 EOR Op2. + CMP, /// Set condition codes on Op1 - Op2. + CMN, /// Set condition codes on Op1 + Op2. + ORR, /// Rd = Op1 OR Op2. + MOV, /// Rd = Op2 + BIC, /// Rd = Op1 AND NOT Op2. + MVN, /// Rd = NOT Op2. +}; + +constexpr bool is_logical(DataProcessingOperation operation) { + switch(operation) { + case DataProcessingOperation::AND: + case DataProcessingOperation::EOR: + case DataProcessingOperation::TST: + case DataProcessingOperation::TEQ: + case DataProcessingOperation::ORR: + case DataProcessingOperation::MOV: + case DataProcessingOperation::BIC: + case DataProcessingOperation::MVN: + return true; + + default: return false; + } +} + +constexpr bool is_comparison(DataProcessingOperation operation) { + switch(operation) { + case DataProcessingOperation::TST: + case DataProcessingOperation::TEQ: + case DataProcessingOperation::CMP: + case DataProcessingOperation::CMN: + return true; + + default: return false; + } +} + struct DataProcessingFlags { constexpr DataProcessingFlags(uint8_t flags) noexcept : flags_(flags) {} @@ -209,9 +184,14 @@ struct MultiplyFlags { /// @c true if the status register should be updated; @c false otherwise. constexpr bool set_condition_codes() const { return flag_bit<20>(flags_); } + enum class Operation { + MUL, /// Rd = Rm * Rs + MLA, /// Rd = Rm * Rs + Rn + }; + /// @returns The operation to apply. - constexpr MultiplyOperation operation() const { - return flag_bit<21>(flags_) ? MultiplyOperation::MLA : MultiplyOperation::MUL; + constexpr Operation operation() const { + return flag_bit<21>(flags_) ? Operation::MLA : Operation::MUL; } private: @@ -243,8 +223,13 @@ private: struct SingleDataTransferFlags { constexpr SingleDataTransferFlags(uint8_t flags) noexcept : flags_(flags) {} - constexpr SingleDataTransferOperation operation() const { - return flag_bit<20>(flags_) ? SingleDataTransferOperation::LDR : SingleDataTransferOperation::STR; + enum class Operation { + LDR, /// Read single byte or word from [base + offset], possibly mutating the base. + STR, /// Write a single byte or word to [base + offset], possibly mutating the base. + }; + + constexpr Operation operation() const { + return flag_bit<20>(flags_) ? Operation::LDR : Operation::STR; } constexpr bool offset_is_immediate() const { return flag_bit<25>(flags_); } @@ -279,8 +264,13 @@ struct SingleDataTransfer: public WithShiftControlBits { struct BlockDataTransferFlags { constexpr BlockDataTransferFlags(uint8_t flags) noexcept : flags_(flags) {} - constexpr BlockDataTransferOperation operation() const { - return flag_bit<20>(flags_) ? BlockDataTransferOperation::LDM : BlockDataTransferOperation::STM; + enum class Operation { + LDM, /// Read 1–16 words from [base], possibly mutating it. + STM, /// Write 1-16 words to [base], possibly mutating it. + }; + + constexpr Operation operation() const { + return flag_bit<20>(flags_) ? Operation::LDM : Operation::STM; } constexpr bool pre_index() const { return flag_bit<24>(flags_); } @@ -333,8 +323,13 @@ private: struct CoprocessorRegisterTransferFlags { constexpr CoprocessorRegisterTransferFlags(uint8_t flags) noexcept : flags_(flags) {} - constexpr CoprocessorRegisterTransferOperation operation() const { - return flag_bit<20>(flags_) ? CoprocessorRegisterTransferOperation::MRC : CoprocessorRegisterTransferOperation::MCR; + enum class Operation { + MRC, /// Move from coprocessor register to ARM register. + MCR, /// Move from ARM register to coprocessor register. + }; + + constexpr Operation operation() const { + return flag_bit<20>(flags_) ? Operation::MRC : Operation::MCR; } constexpr int coprocessor_operation() const { return (flags_ >> (FlagsStartBit - 20)) & 0x7; } @@ -361,8 +356,13 @@ private: struct CoprocessorDataTransferFlags { constexpr CoprocessorDataTransferFlags(uint8_t flags) noexcept : flags_(flags) {} - constexpr CoprocessorDataTransferOperation operation() const { - return flag_bit<20>(flags_) ? CoprocessorDataTransferOperation::LDC : CoprocessorDataTransferOperation::STC; + enum class Operation { + LDC, /// Coprocessor data transfer load. + STC, /// Coprocessor data transfer store. + }; + + constexpr Operation operation() const { + return flag_bit<20>(flags_) ? Operation::LDC : Operation::STC; } constexpr bool pre_index() const { return flag_bit<24>(flags_); } constexpr bool add_offset() const { return flag_bit<23>(flags_); } diff --git a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm index 73f828966..5951f92ef 100644 --- a/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm +++ b/OSBindings/Mac/Clock SignalTests/ARMDecoderTests.mm @@ -199,7 +199,7 @@ struct Scheduler { const uint32_t multiplicand = fields.multiplicand() == 15 ? registers_.pc(8) : registers_.active[fields.multiplicand()]; const uint32_t multiplier = fields.multiplier() == 15 ? registers_.pc_status(8) : registers_.active[fields.multiplier()]; const uint32_t accumulator = - flags.operation() == MultiplyOperation::MUL ? 0 : + flags.operation() == MultiplyFlags::Operation::MUL ? 0 : (fields.multiplicand() == 15 ? registers_.pc_status(12) : registers_.active[fields.accumulator()]); const uint32_t result = multiplicand * multiplier + accumulator; @@ -217,7 +217,7 @@ struct Scheduler { template void perform(Branch branch) { constexpr BranchFlags flags(f); - if constexpr (flags.operation() == BranchOperation::BL) { + if constexpr (flags.operation() == BranchFlags::Operation::BL) { registers_.active[14] = registers_.pc(4); } registers_.set_pc(registers_.pc(8) + branch.offset());