diff options
Diffstat (limited to 'asm/arm/instruction.h')
-rw-r--r-- | asm/arm/instruction.h | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/asm/arm/instruction.h b/asm/arm/instruction.h new file mode 100644 index 0000000..224cc6e --- /dev/null +++ b/asm/arm/instruction.h @@ -0,0 +1,109 @@ +#pragma once + +#include <memory> +#include <stdexcept> +#include <string> +#include <vector> + +using namespace std::string_literals; + +using code_sequence = std::vector<uint8_t>; + +template<typename from_t> +code_sequence to_code_sequence(from_t v); + +template<> +code_sequence to_code_sequence<uint16_t>(uint16_t v) { + return code_sequence{static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8)}; +} + +template<> +code_sequence to_code_sequence<uint32_t>(uint32_t v) { + return code_sequence{static_cast<uint8_t>(v & 0xFF), static_cast<uint8_t>(v >> 8), static_cast<uint8_t>(v >> 16),static_cast<uint8_t>(v >> 24) }; +} + +uint32_t high_bits(uint8_t number) +{ + return ~((static_cast<uint32_t>(1) << (32 - number)) - 1); +} + +// Identify operator with leading bits +class Pattern +{ +public: + Pattern(uint32_t bits, uint32_t mask): _bits{bits}, _mask{mask} {} + + template<typename T> + T encode() + { + return static_cast<T>(_bits); + } + + +private: + uint32_t _bits; + uint32_t _mask; +}; + +class Operand +{ +protected: + Operand(uint8_t pos): _pos(pos){} +private: + uint8_t _pos; +}; + +class Register: public Operand +{ +public: + Register(uint8_t pos): Operand{pos} {}; +}; + +class Immediate: public Operand +{ +public: + Immediate(uint8_t pos, uint8_t bits): Operand{pos}, _bits{bits} {} +private: + uint8_t _bits; +}; + +using Operands = std::vector<std::shared_ptr<Operand>>; + +// Pattern [, Operand, ...] +class Instruction +{ +public: + Instruction(const std::string& mnemonic, uint8_t size, Pattern pattern, Operands operands): _mnemonic(mnemonic), _size(size), _pattern(pattern), _operands(operands) {} + code_sequence encode(const std::vector<std::string>& arguments) + { + if (_size == 2) { // 16 bit thumb insn + uint16_t result{ _pattern.encode<uint16_t>()}; + return to_code_sequence(result); + } else if (_size == 4) { // 32 bit thumb insn + uint32_t result{ _pattern.encode<uint32_t>()}; + return to_code_sequence(result); + } else { + throw std::runtime_error("Unsupported instruction size "s + std::to_string(_size)); + } + } + +private: + std::string _mnemonic; + uint8_t _size; + Pattern _pattern; + Operands _operands; +}; + +namespace { + // factory functions + std::shared_ptr<Operand> imm(uint8_t pos, uint8_t size){ return std::make_shared<Immediate>(pos, size); }; + std::shared_ptr<Operand> reg(uint8_t pos) { return std::make_shared<Register>(pos); }; + + std::vector<Instruction> insns{ + {"adcs", 2, Pattern(0x4140, high_bits(10)), Operands{reg(0), reg(3)}}, + + {"lsls", 2, Pattern(0x0000, high_bits(5)), Operands{reg(0), reg(3), imm(6, 5)}} + }; +}; + + |