diff --git a/InstructionSets/ARM/Decoder.hpp b/InstructionSets/ARM/Decoder.hpp index f68be950f..b11300373 100644 --- a/InstructionSets/ARM/Decoder.hpp +++ b/InstructionSets/ARM/Decoder.hpp @@ -16,25 +16,25 @@ namespace InstructionSet::ARM { template -constexpr std::array operation_table() { - std::array result{}; - for(int c = 0; c < 256; c++) { - const uint32_t opcode = c << 20; +using OperationTable = std::array; + +template +constexpr OperationTable operation_table() { + OperationTable result{}; + for(std::size_t c = 0; c < result.size(); c++) { + const auto opcode = static_cast(c << 21); + + // Cf. the ARM2 datasheet, p45. Tests below match its ordering + // other than that 'undefined' is the fallthrough case. if(((opcode >> 26) & 0b11) == 0b00) { result[c] = Operation((c >> 21) & 0xf); continue; } - if(((opcode >> 25) & 0b111) == 0b101) { - result[c] = - ((opcode >> 24) & 1) ? Operation::BranchWithLink : Operation::Branch; - continue; - } - if(((opcode >> 22) & 0b111'111) == 0b000'000) { result[c] = - ((opcode >> 21) & 1) ? Operation::MultiplyWithAccumulate : Operation::Multiply; + ((opcode >> 21) & 1) ? Operation::MLA : Operation::MUL; continue; } @@ -48,8 +48,14 @@ constexpr std::array operation_table() { continue; } - if(((opcode >> 24) & 0b1111) == 0b1111) { - result[c] = Operation::SoftwareInterrupt; + if(((opcode >> 25) & 0b111) == 0b101) { + result[c] = + ((opcode >> 24) & 1) ? Operation::BL : Operation::B; + continue; + } + + if(((opcode >> 25) & 0b111) == 0b110) { + result[c] = Operation::CoprocessorDataTransfer; continue; } @@ -58,8 +64,8 @@ constexpr std::array operation_table() { continue; } - if(((opcode >> 25) & 0b111) == 0b110) { - result[c] = Operation::CoprocessorDataTransfer; + if(((opcode >> 24) & 0b1111) == 0b1111) { + result[c] = Operation::SoftwareInterrupt; continue; } @@ -70,8 +76,8 @@ constexpr std::array operation_table() { template constexpr Operation operation(uint32_t opcode) { - constexpr std::array operations = operation_table(); - return operations[(opcode >> 20) & 0xff]; + constexpr OperationTable operations = operation_table(); + return operations[(opcode >> 21) & 0x7f]; } } diff --git a/InstructionSets/ARM/Operation.hpp b/InstructionSets/ARM/Operation.hpp index 978441f68..6b2450513 100644 --- a/InstructionSets/ARM/Operation.hpp +++ b/InstructionSets/ARM/Operation.hpp @@ -16,11 +16,11 @@ enum class Operation { TST, TEQ, CMP, CMN, ORR, MOV, BIC, MVN, - Branch, BranchWithLink, - Multiply, MultiplyWithAccumulate, + B, BL, + MUL, MLA, - SingleDataTransfer, - BlockDataTransfer, + SingleDataTransfer, // TODO: LDR or STR? + BlockDataTransfer, // TODO: LDM or STM? SoftwareInterrupt, CoprocessorDataOperationOrRegisterTransfer,