summaryrefslogtreecommitdiffhomepage
path: root/asm
diff options
context:
space:
mode:
Diffstat (limited to 'asm')
-rw-r--r--asm/arm/instruction.h32
1 files changed, 23 insertions, 9 deletions
diff --git a/asm/arm/instruction.h b/asm/arm/instruction.h
index d8d4033..daadcce 100644
--- a/asm/arm/instruction.h
+++ b/asm/arm/instruction.h
@@ -32,7 +32,7 @@ uint32_t high_bits(uint8_t number)
class Pattern
{
public:
- Pattern(uint32_t bits, uint32_t mask, bool is_alternative_syntax = false): _bits{bits}, _mask{mask} {}
+ Pattern(uint32_t bits, uint32_t mask): _bits{bits}, _mask{mask} {}
template<typename T>
T encode()
@@ -40,6 +40,11 @@ public:
return static_cast<T>(_bits);
}
+ Pattern& alternative_syntax() {
+ throw std::runtime_error("alternative_syntax: Unimplemented");
+ return *this;
+ }
+
private:
uint32_t _bits;
@@ -117,6 +122,14 @@ namespace {
std::shared_ptr<Operand> same_reg(uint8_t index) { return std::make_shared<SameRegister>(index); }
std::shared_ptr<Operand> cond(uint8_t pos) { throw std::runtime_error("Unimplemented: cond"); }
+ std::shared_ptr<Operand> suffixed(std::shared_ptr<Operand> op) { throw std::runtime_error("Unimplemented: suffixed"); }
+ template<typename T, typename... Targs>
+ std::shared_ptr<Operand> suffixed(std::shared_ptr<Operand> op, T suffix, Targs... suffixes) {
+ // TODO: add suffix to op
+ return suffixed(op, suffixes...);
+ }
+
+ std::shared_ptr<Operand> bracketed(Operands operands) { throw std::runtime_error("Unimplemented: bracketed"); };
std::shared_ptr<Operand> optional(std::shared_ptr<Operand> op) { return op; }
// TODO: consistency checks:
@@ -134,13 +147,13 @@ namespace {
{"add", 2, Pattern(0x4468, 0xFF78), Operands{same_reg(2), reg("sp"), reg(0b10000111)}}, // T1
{"add", 2, Pattern(0x4485, 0xFF87), Operands{reg("sp"), reg(4, 3)}}, // T2
{"adr", 2, Pattern(0xA000, high_bits(5)), Operands{reg(3, 8), label(8, 0, 4)}}, // T1
- {"add", 2, Pattern(0xA000, high_bits(5), true), Operands{reg(3, 8), imm(8, 0, 4)}}, // T1, alternative syntax
+ {"add", 2, Pattern(0xA000, high_bits(5)).alternative_syntax(), Operands{reg(3, 8), imm(8, 0, 4)}}, // T1, alternative syntax
{"ands", 2, Pattern(0x4000, high_bits(10)), Operands{optional(same_reg(1)), reg(3, 0), reg(3, 3)}}, // T1
{"asrs", 2, Pattern(0x1000, high_bits(5)), Operands{reg(3, 0), reg(3, 3), imm(5, 6, 1, 32)}}, // T1
{"asrs", 2, Pattern(0x4100, high_bits(10)), Operands{same_reg(1), reg(3, 0), reg(3, 3)}}, // T1
{"b<c>", 2, Pattern(0xD000, high_bits(4)), Operands{cond(8), label(8, 0, 2, true)}}, // T1
{"b", 2, Pattern(0xE000, high_bits(5)), Operands{label(11, 0, 2, true)}}, // T2
- {"bal", 2, Pattern(0xE000, high_bits(5), true), Operands{label(11, 0, 2, true)}}, // T2
+ {"bal", 2, Pattern(0xE000, high_bits(5)).alternative_syntax(), Operands{label(11, 0, 2, true)}}, // T2
{"bics", 2, Pattern(0x4380, high_bits(10)), Operands{optional(same_reg(1)), reg(3, 0), reg(3, 3)}}, // T1
{"bkpt", 2, Pattern(0xBE00, high_bits(8)), Operands{imm(8, 0)}}, // T1
{"bl", 4, Pattern(0xF000D000, 0xF800D000), Operands{label(24, {11, 0, 10, 16, 1, 11, 1, 13, 1, 26}, 0x00002800, 2, true)}}, // T1
@@ -151,16 +164,17 @@ namespace {
{"cmp", 2, Pattern(0x4280, high_bits(10)), Operands{reg(3, 0), reg(3, 3)}}, // T1
{"cmp", 2, Pattern(0x4500, high_bits(8)), Operands{reg(0x87), reg(4, 3)}}, // T2
{"cps", 2, Pattern(0xB662, 0xFFEF), Operands{imm(1, 4)}}, // T1
- {"cpy", 2, Pattern(0x4600, high_bits(8), true), Operands{reg(0x87), reg(4, 3)}}, // T1
+ {"cpy", 2, Pattern(0x4600, high_bits(8)).alternative_syntax(), Operands{reg(0x87), reg(4, 3)}}, // T1
{"dmb", 4, Pattern(0xF3BF8F5F, high_bits(32)), Operands{optional(id("sy"))}}, // T1
{"dsb", 4, Pattern(0xF3BF8F4F, high_bits(32)), Operands{optional(id("sy"))}}, // T1
{"eors", 2, Pattern(0x4040, high_bits(10)), Operands{optional(same_reg(1)), reg(3, 0), reg(3, 3)}}, // T1
{"isb", 4, Pattern(0xF3BF8F6F, high_bits(32)), Operands{optional(id("sy"))}}, // T1
- {"ldm", 2, Pattern(0xC800, high_bits(5)), Operands{reg(3, 8, 1), reg_list(8, 0)}}, // T1
- {"ldm", 2, Pattern(0xC800, high_bits(5)), Operands{reg(3, 8, 1), reg_list(8, 0)}}, // T1
- {"ldmia", 2, Pattern(0xC800, high_bits(5), true), Operands{reg(3, 8, 1), reg_list(8, 0)}}, // T1
- {"ldmfd", 2, Pattern(0xC800, high_bits(5), true), Operands{reg(3, 8, 1), reg_list(8, 0)}}, // T1
-
+ {"ldm", 2, Pattern(0xC800, high_bits(5)), Operands{suffixed(reg(3, 8, 1), "!", ""), reg_list(8, 0)}}, // T1
+ {"ldmia", 2, Pattern(0xC800, high_bits(5)).alternative_syntax(), Operands{suffixed(reg(3, 8, 1), "!", ""), reg_list(8, 0)}}, // T1
+ {"ldmfd", 2, Pattern(0xC800, high_bits(5)).alternative_syntax(), Operands{suffixed(reg(3, 8, 1), "!", ""), reg_list(8, 0)}}, // T1
+ {"ldr", 2, Pattern(0x6800, high_bits(5)), Operands{reg(3, 0), bracketed(Operands{reg(3, 3), optional(imm(5, 6, 4))})}}, // T1
+ {"ldr", 2, Pattern(0x9800, high_bits(5)), Operands{reg(3, 8), bracketed(Operands{reg("sp"), optional(imm(8, 0, 4))})}}, // T2
+
{"lsls", 2, Pattern(0x0000, high_bits(5)), Operands{reg(3, 0), reg(3, 3), imm(5, 6, 1, 0, {0})}},
{"mov", 2, Pattern(0x4600, high_bits(8)), Operands{reg(0x87), reg(4, 3)}}, // T1
{"movs", 2, Pattern(0x0000, high_bits(10)), Operands{reg(3, 0), reg(3, 3)}}, // T2